1#include <xrpl/json/Writer.h>
3#include <xrpl/basics/ToString.h>
4#include <xrpl/json/Output.h>
19std::map<char, char const*> gJsonSpecialCharacterEscape = {
29size_t const kJsonEscapeLength = 2;
32char const kCloseBrace =
'}';
33char const kCloseBracket =
']';
34char const kColon =
':';
35char const kComma =
',';
36char const kOpenBrace =
'{';
37char const kOpenBracket =
'[';
38char const kQuote =
'"';
40auto const kIntegralFloatsBecomeInts =
false;
43lengthWithoutTrailingZeros(std::string
const& s)
45 auto dotPos = s.
find(
'.');
46 if (dotPos == std::string::npos)
50 auto hasDecimals = dotPos != lastNonZero;
53 return lastNonZero + 1;
55 if (kIntegralFloatsBecomeInts || lastNonZero + 2 > s.
size())
58 return lastNonZero + 2;
90 output(boost::beast::string_view
const& bytes)
103 auto data = bytes.data();
104 for (; position < bytes.size(); ++position)
106 auto i = gJsonSpecialCharacterEscape.
find(data[position]);
107 if (i != gJsonSpecialCharacterEscape.
end())
109 if (writtenUntil < position)
111 output_({data + writtenUntil, position - writtenUntil});
113 output_({i->second, kJsonEscapeLength});
114 writtenUntil = position + 1;
117 if (writtenUntil < position)
118 output_({data + writtenUntil, position - writtenUntil});
134 auto t =
stack_.top().type;
143 stack_.top().isFirst =
false;
156 auto& tags =
stack_.top().tags;
157 check(!tags.contains(tag),
"Already seen tag " + tag);
177 auto ch = isArray ? kCloseBracket : kCloseBrace;
192 [[nodiscard]]
Output const&
235 impl_ = std::move(w.impl_);
241 impl_ = std::move(w.impl_);
248 impl_->stringOutput(s);
254 impl_->stringOutput(s);
260 impl_->markStarted();
268 impl_->output({s.
data(), lengthWithoutTrailingZeros(s)});
275 impl_->output({s.
data(), lengthWithoutTrailingZeros(s)});
281 impl_->output(
"null");
287 impl_->output(b ?
"true" :
"false");
315 impl_->writeObjectTag(tag);
335 impl_->writeObjectTag(key);
Output const & getOutput() const
std::stack< Collection, std::vector< Collection > > Stack
void writeObjectTag(std::string const &tag)
Impl & operator=(Impl &&)=delete
void nextCollectionEntry(CollectionType type, std::string const &message)
void stringOutput(boost::beast::string_view const &bytes)
void output(boost::beast::string_view const &bytes)
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).
void outputJson(json::Value const &, Output const &)
Writes a minimal representation of a Json value to an Output in O(n) time.
std::function< void(boost::beast::string_view const &)> Output
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?