1#include <xrpl/json/Writer.h>
3#include <xrpl/basics/ToString.h>
4#include <xrpl/json/Output.h>
20std::map<char, char const*> gJsonSpecialCharacterEscape = {
30size_t const kJsonEscapeLength = 2;
33char const kCloseBrace =
'}';
34char const kCloseBracket =
']';
35char const kColon =
':';
36char const kComma =
',';
37char const kOpenBrace =
'{';
38char const kOpenBracket =
'[';
39char const kQuote =
'"';
41auto const kIntegralFloatsBecomeInts =
false;
44lengthWithoutTrailingZeros(std::string
const& s)
46 auto dotPos = s.
find(
'.');
47 if (dotPos == std::string::npos)
51 auto hasDecimals = dotPos != lastNonZero;
54 return lastNonZero + 1;
56 if (kIntegralFloatsBecomeInts || lastNonZero + 2 > s.
size())
59 return lastNonZero + 2;
104 auto data = bytes.
data();
105 for (; position < bytes.
size(); ++position)
107 auto i = gJsonSpecialCharacterEscape.
find(data[position]);
108 if (i != gJsonSpecialCharacterEscape.
end())
110 if (writtenUntil < position)
112 output_({data + writtenUntil, position - writtenUntil});
114 output_({i->second, kJsonEscapeLength});
115 writtenUntil = position + 1;
118 if (writtenUntil < position)
119 output_({data + writtenUntil, position - writtenUntil});
135 auto t =
stack_.top().type;
144 stack_.top().isFirst =
false;
157 auto& tags =
stack_.top().tags;
158 check(!tags.contains(tag),
"Already seen tag " + tag);
178 auto ch = isArray ? kCloseBracket : kCloseBrace;
193 [[nodiscard]]
Output const&
247 impl_ = std::move(w.impl_);
254 impl_->stringOutput(s);
260 impl_->stringOutput(s);
266 impl_->markStarted();
274 impl_->output({s.
data(), lengthWithoutTrailingZeros(s)});
281 impl_->output({s.
data(), lengthWithoutTrailingZeros(s)});
287 impl_->output(
"null");
293 impl_->output(b ?
"true" :
"false");
321 impl_->writeObjectTag(tag);
341 impl_->writeObjectTag(key);
void stringOutput(std::string_view bytes)
Output const & getOutput() const
std::stack< Collection, std::vector< Collection > > Stack
void output(std::string_view bytes)
void writeObjectTag(std::string const &tag)
Impl & operator=(Impl &&)=delete
void nextCollectionEntry(CollectionType type, std::string const &message)
void start(CollectionType ct)
Writer implements an O(1)-space, O(1)-granular output JSON writer.
void finishAll()
Finish all objects and arrays.
void rawAppend()
Add a comma before this next item if not the first item in an array.
void startRoot(CollectionType)
Start a new collection at the root level.
Writer & operator=(Writer &&) noexcept
void startAppend(CollectionType)
Start a new collection inside an array.
void implOutput(std::string const &)
void output(std::string const &)
Writer(Output const &output)
void startSet(CollectionType, std::string const &key)
Start a new collection inside an object.
std::unique_ptr< Impl > impl_
void rawSet(std::string const &key)
Emit just "tag": as part of an object.
void finish()
Finish the collection most recently started.
T find_last_not_of(T... args)
JSON (JavaScript Object Notation).
std::function< void(std::string_view)> Output
void outputJson(json::Value const &, Output const &)
Writes a minimal representation of a Json value to an Output in O(n) time.
void check(bool condition, std::string const &message)
std::string to_string(BaseUInt< Bits, Tag > const &a)
Writer::CollectionType type
What type of collection are we in?
std::set< std::string > tags
What tags have we already seen in this collection?
bool isFirst
Is this the first entry in a collection?