Expose JSON parse flag options
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
@@ -304,183 +304,165 @@ namespace AZ::Dom::Json
|
||||
//
|
||||
// struct JsonReadHandler
|
||||
//
|
||||
// Handler for a rapidjson::Reader that translates reads into an AZ::Dom::Visitor
|
||||
struct JsonReadHandler
|
||||
RapidJsonReadHandler::RapidJsonReadHandler(Visitor* visitor, Lifetime stringLifetime)
|
||||
: m_visitor(visitor)
|
||||
, m_stringLifetime(stringLifetime)
|
||||
, m_outcome(AZ::Success())
|
||||
{
|
||||
public:
|
||||
JsonReadHandler(Visitor* visitor, Lifetime stringLifetime)
|
||||
: m_visitor(visitor)
|
||||
, m_stringLifetime(stringLifetime)
|
||||
, m_outcome(AZ::Success())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
bool Null()
|
||||
{
|
||||
return CheckResult(m_visitor->Null());
|
||||
}
|
||||
bool RapidJsonReadHandler::Null()
|
||||
{
|
||||
return CheckResult(m_visitor->Null());
|
||||
}
|
||||
|
||||
bool Bool(bool b)
|
||||
{
|
||||
return CheckResult(m_visitor->Bool(b));
|
||||
}
|
||||
bool RapidJsonReadHandler::Bool(bool b)
|
||||
{
|
||||
return CheckResult(m_visitor->Bool(b));
|
||||
}
|
||||
|
||||
bool Int(int i)
|
||||
{
|
||||
return CheckResult(m_visitor->Int64(static_cast<AZ::s64>(i)));
|
||||
}
|
||||
bool RapidJsonReadHandler::Int(int i)
|
||||
{
|
||||
return CheckResult(m_visitor->Int64(static_cast<AZ::s64>(i)));
|
||||
}
|
||||
|
||||
bool Uint(unsigned i)
|
||||
{
|
||||
return CheckResult(m_visitor->Uint64(static_cast<AZ::u64>(i)));
|
||||
}
|
||||
bool RapidJsonReadHandler::Uint(unsigned i)
|
||||
{
|
||||
return CheckResult(m_visitor->Uint64(static_cast<AZ::u64>(i)));
|
||||
}
|
||||
|
||||
bool Int64(int64_t i)
|
||||
{
|
||||
return CheckResult(m_visitor->Int64(i));
|
||||
}
|
||||
bool RapidJsonReadHandler::Int64(int64_t i)
|
||||
{
|
||||
return CheckResult(m_visitor->Int64(i));
|
||||
}
|
||||
|
||||
bool Uint64(uint64_t i)
|
||||
{
|
||||
return CheckResult(m_visitor->Uint64(i));
|
||||
}
|
||||
bool RapidJsonReadHandler::Uint64(uint64_t i)
|
||||
{
|
||||
return CheckResult(m_visitor->Uint64(i));
|
||||
}
|
||||
|
||||
bool Double(double d)
|
||||
{
|
||||
return CheckResult(m_visitor->Double(d));
|
||||
}
|
||||
bool RapidJsonReadHandler::Double(double d)
|
||||
{
|
||||
return CheckResult(m_visitor->Double(d));
|
||||
}
|
||||
|
||||
bool RawNumber([[maybe_unused]] const char* str, [[maybe_unused]] rapidjson::SizeType length, [[maybe_unused]] bool copy)
|
||||
bool RapidJsonReadHandler::RawNumber(
|
||||
[[maybe_unused]] const char* str, [[maybe_unused]] rapidjson::SizeType length, [[maybe_unused]] bool copy)
|
||||
{
|
||||
AZ_Assert(false, "Raw numbers are unsupported in the rapidjson DOM backend");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RapidJsonReadHandler::String(const char* str, rapidjson::SizeType length, bool copy)
|
||||
{
|
||||
Lifetime lifetime = m_stringLifetime;
|
||||
if (!copy)
|
||||
{
|
||||
AZ_Assert(false, "Raw numbers are unsupported in the rapidjson DOM backend");
|
||||
lifetime = Lifetime::Temporary;
|
||||
}
|
||||
return CheckResult(m_visitor->String(AZStd::string_view(str, length), lifetime));
|
||||
}
|
||||
|
||||
bool RapidJsonReadHandler::StartObject()
|
||||
{
|
||||
return CheckResult(m_visitor->StartObject());
|
||||
}
|
||||
|
||||
bool RapidJsonReadHandler::Key(const char* str, rapidjson::SizeType length, [[maybe_unused]] bool copy)
|
||||
{
|
||||
AZStd::string_view key = AZStd::string_view(str, length);
|
||||
if (!m_visitor->SupportsRawKeys())
|
||||
{
|
||||
m_visitor->Key(AZ::Name(key));
|
||||
}
|
||||
Lifetime lifetime = m_stringLifetime;
|
||||
if (!copy)
|
||||
{
|
||||
lifetime = Lifetime::Temporary;
|
||||
}
|
||||
return CheckResult(m_visitor->RawKey(key, lifetime));
|
||||
}
|
||||
|
||||
bool RapidJsonReadHandler::EndObject([[maybe_unused]] rapidjson::SizeType memberCount)
|
||||
{
|
||||
return CheckResult(m_visitor->EndObject(memberCount));
|
||||
}
|
||||
|
||||
bool RapidJsonReadHandler::StartArray()
|
||||
{
|
||||
return CheckResult(m_visitor->StartArray());
|
||||
}
|
||||
|
||||
bool RapidJsonReadHandler::EndArray([[maybe_unused]] rapidjson::SizeType elementCount)
|
||||
{
|
||||
return CheckResult(m_visitor->EndArray(elementCount));
|
||||
}
|
||||
|
||||
Visitor::Result&& RapidJsonReadHandler::TakeOutcome()
|
||||
{
|
||||
return AZStd::move(m_outcome);
|
||||
}
|
||||
|
||||
bool RapidJsonReadHandler::CheckResult(Visitor::Result result)
|
||||
{
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
m_outcome = AZStd::move(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool String(const char* str, rapidjson::SizeType length, bool copy)
|
||||
{
|
||||
Lifetime lifetime = m_stringLifetime;
|
||||
if (!copy)
|
||||
{
|
||||
lifetime = Lifetime::Temporary;
|
||||
}
|
||||
return CheckResult(m_visitor->String(AZStd::string_view(str, length), lifetime));
|
||||
}
|
||||
|
||||
bool StartObject()
|
||||
{
|
||||
return CheckResult(m_visitor->StartObject());
|
||||
}
|
||||
|
||||
bool Key(const char* str, rapidjson::SizeType length, [[maybe_unused]] bool copy)
|
||||
{
|
||||
AZStd::string_view key = AZStd::string_view(str, length);
|
||||
if (!m_visitor->SupportsRawKeys())
|
||||
{
|
||||
m_visitor->Key(AZ::Name(key));
|
||||
}
|
||||
Lifetime lifetime = m_stringLifetime;
|
||||
if (!copy)
|
||||
{
|
||||
lifetime = Lifetime::Temporary;
|
||||
}
|
||||
return CheckResult(m_visitor->RawKey(key, lifetime));
|
||||
}
|
||||
|
||||
bool EndObject([[maybe_unused]] rapidjson::SizeType memberCount)
|
||||
{
|
||||
return CheckResult(m_visitor->EndObject(memberCount));
|
||||
}
|
||||
|
||||
bool StartArray()
|
||||
{
|
||||
return CheckResult(m_visitor->StartArray());
|
||||
}
|
||||
|
||||
bool EndArray([[maybe_unused]] rapidjson::SizeType elementCount)
|
||||
{
|
||||
return CheckResult(m_visitor->EndArray(elementCount));
|
||||
}
|
||||
|
||||
Visitor::Result&& TakeOutcome()
|
||||
{
|
||||
return AZStd::move(m_outcome);
|
||||
}
|
||||
|
||||
private:
|
||||
bool CheckResult(Visitor::Result result)
|
||||
{
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
m_outcome = AZStd::move(result);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Visitor::Result m_outcome;
|
||||
Visitor* m_visitor;
|
||||
Lifetime m_stringLifetime;
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// struct AzStringStream
|
||||
//
|
||||
// rapidjson stream wrapper for AZStd::string suitable for in-situ parsing
|
||||
struct AzStringStream
|
||||
AzStringStream::AzStringStream(AZStd::string& buffer)
|
||||
{
|
||||
using Ch = char;
|
||||
m_cursor = buffer.data();
|
||||
m_begin = m_cursor;
|
||||
}
|
||||
|
||||
AzStringStream(AZStd::string& buffer)
|
||||
{
|
||||
m_cursor = buffer.data();
|
||||
m_begin = m_cursor;
|
||||
}
|
||||
char AzStringStream::Peek() const
|
||||
{
|
||||
return *m_cursor;
|
||||
}
|
||||
|
||||
char Peek() const
|
||||
{
|
||||
return *m_cursor;
|
||||
}
|
||||
char AzStringStream::Take()
|
||||
{
|
||||
return *m_cursor++;
|
||||
}
|
||||
|
||||
char Take()
|
||||
{
|
||||
return *m_cursor++;
|
||||
}
|
||||
size_t AzStringStream::Tell() const
|
||||
{
|
||||
return static_cast<size_t>(m_cursor - m_begin);
|
||||
}
|
||||
|
||||
size_t Tell() const
|
||||
{
|
||||
return static_cast<size_t>(m_cursor - m_begin);
|
||||
}
|
||||
char* AzStringStream::PutBegin()
|
||||
{
|
||||
m_write = m_cursor;
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
char* PutBegin()
|
||||
{
|
||||
m_write = m_cursor;
|
||||
return m_cursor;
|
||||
}
|
||||
void AzStringStream::Put(char c)
|
||||
{
|
||||
(*m_write++) = c;
|
||||
}
|
||||
|
||||
void Put(char c)
|
||||
{
|
||||
(*m_write++) = c;
|
||||
}
|
||||
void AzStringStream::Flush()
|
||||
{
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
}
|
||||
size_t AzStringStream::PutEnd(char* begin)
|
||||
{
|
||||
return m_write - begin;
|
||||
}
|
||||
|
||||
size_t PutEnd(char* begin)
|
||||
{
|
||||
return m_write - begin;
|
||||
}
|
||||
|
||||
const char* Peek4() const
|
||||
{
|
||||
AZ_Assert(false, "Not implemented, encoding is hard-coded to UTF-8");
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
char* m_cursor; //!< Current read position.
|
||||
char* m_write; //!< Current write position.
|
||||
const char* m_begin; //!< Head of string.
|
||||
};
|
||||
const char* AzStringStream::Peek4() const
|
||||
{
|
||||
AZ_Assert(false, "Not implemented, encoding is hard-coded to UTF-8");
|
||||
return m_cursor;
|
||||
}
|
||||
|
||||
//
|
||||
// Serialized JSON util functions
|
||||
@@ -499,28 +481,6 @@ namespace AZ::Dom::Json
|
||||
}
|
||||
}
|
||||
|
||||
Visitor::Result VisitSerializedJson(AZStd::string_view buffer, Lifetime lifetime, Visitor& visitor)
|
||||
{
|
||||
rapidjson::Reader reader;
|
||||
rapidjson::MemoryStream stream(buffer.data(), buffer.size());
|
||||
JsonReadHandler handler(&visitor, lifetime);
|
||||
|
||||
constexpr int flags = rapidjson::kParseCommentsFlag;
|
||||
reader.Parse<flags>(stream, handler);
|
||||
return handler.TakeOutcome();
|
||||
}
|
||||
|
||||
Visitor::Result VisitSerializedJsonInPlace(AZStd::string& buffer, Visitor& visitor)
|
||||
{
|
||||
rapidjson::Reader reader;
|
||||
AzStringStream stream(buffer);
|
||||
JsonReadHandler handler(&visitor, Lifetime::Persistent);
|
||||
|
||||
constexpr int flags = rapidjson::kParseCommentsFlag | rapidjson::kParseInsituFlag;
|
||||
reader.Parse<flags>(stream, handler);
|
||||
return handler.TakeOutcome();
|
||||
}
|
||||
|
||||
//
|
||||
// In-memory rapidjson util functions
|
||||
//
|
||||
|
||||
@@ -67,6 +67,56 @@ namespace AZ::Dom::Json
|
||||
AZStd::deque<ValueInfo> m_entryStack;
|
||||
};
|
||||
|
||||
//! Handler for a rapidjson::Reader that translates reads into an AZ::Dom::Visitor
|
||||
struct RapidJsonReadHandler
|
||||
{
|
||||
public:
|
||||
RapidJsonReadHandler(Visitor* visitor, Lifetime stringLifetime);
|
||||
|
||||
bool Null();
|
||||
bool Bool(bool b);
|
||||
bool Int(int i);
|
||||
bool Uint(unsigned i);
|
||||
bool Int64(int64_t i);
|
||||
bool Uint64(uint64_t i);
|
||||
bool Double(double d);
|
||||
bool RawNumber(const char* str, rapidjson::SizeType length, bool copy);
|
||||
bool String(const char* str, rapidjson::SizeType length, bool copy);
|
||||
bool StartObject();
|
||||
bool Key(const char* str, rapidjson::SizeType length, bool copy);
|
||||
bool EndObject(rapidjson::SizeType memberCount);
|
||||
bool StartArray();
|
||||
bool EndArray(rapidjson::SizeType elementCount);
|
||||
Visitor::Result&& TakeOutcome();
|
||||
|
||||
private:
|
||||
bool CheckResult(Visitor::Result result);
|
||||
|
||||
Visitor::Result m_outcome;
|
||||
Visitor* m_visitor;
|
||||
Lifetime m_stringLifetime;
|
||||
};
|
||||
|
||||
//! rapidjson stream wrapper for AZStd::string suitable for in-situ parsing
|
||||
struct AzStringStream
|
||||
{
|
||||
using Ch = char; //<! Denotes the string character storage type for rapidjson
|
||||
|
||||
AzStringStream(AZStd::string& buffer);
|
||||
char Peek() const;
|
||||
char Take();
|
||||
size_t Tell() const;
|
||||
char* PutBegin();
|
||||
void Put(char c);
|
||||
void Flush();
|
||||
size_t PutEnd(char* begin);
|
||||
const char* Peek4() const;
|
||||
|
||||
char* m_cursor; //!< Current read position.
|
||||
char* m_write; //!< Current write position.
|
||||
const char* m_begin; //!< Head of string.
|
||||
};
|
||||
|
||||
//! Creates a Visitor that will write serialized JSON to the specified stream.
|
||||
//! \param stream The stream the visitor will write to.
|
||||
//! \param format The format to write in.
|
||||
@@ -76,9 +126,10 @@ namespace AZ::Dom::Json
|
||||
//! Reads serialized JSON from a string and applies it to a visitor.
|
||||
//! \param buffer The UTF-8 serialized JSON to read.
|
||||
//! \param lifetime Specifies the lifetime of the specified buffer. If the string specified by buffer might be deallocated,
|
||||
//! ensure specify Lifetime::Temporary is specified.
|
||||
//! ensure Lifetime::Temporary is specified.
|
||||
//! \param visitor The visitor to visit with the JSON buffer's contents.
|
||||
//! \return The aggregate result specifying whether the visitor operations were successful.
|
||||
template<int ParseFlags = rapidjson::kParseCommentsFlag>
|
||||
Visitor::Result VisitSerializedJson(AZStd::string_view buffer, Lifetime lifetime, Visitor& visitor);
|
||||
//! Reads serialized JSON from a string in-place and applies it to a visitor.
|
||||
//! \param buffer The UTF-8 serialized JSON to read. This buffer will be modified as part of the deserialization process to
|
||||
@@ -86,6 +137,7 @@ namespace AZ::Dom::Json
|
||||
//! \param visitor The visitor to visit with the JSON buffer's contents. The strings provided to the visitor will only
|
||||
//! be valid for the lifetime of buffer.
|
||||
//! \return The aggregate result specifying whether the visitor operations were successful.
|
||||
template<int ParseFlags = rapidjson::kParseCommentsFlag | rapidjson::kParseInsituFlag>
|
||||
Visitor::Result VisitSerializedJsonInPlace(AZStd::string& buffer, Visitor& visitor);
|
||||
|
||||
//! Takes a visitor specified by a callback and produces a rapidjson::Document.
|
||||
@@ -106,4 +158,32 @@ namespace AZ::Dom::Json
|
||||
//! before the visitor is finished using these values, Lifetime::Temporary should be specified.
|
||||
//! \return The aggregate result specifying whether the visitor operations were successful.
|
||||
Visitor::Result VisitRapidJsonValue(const rapidjson::Value& value, Visitor& visitor, Lifetime lifetime);
|
||||
|
||||
template<int ParseFlags>
|
||||
Visitor::Result VisitSerializedJson(AZStd::string_view buffer, Lifetime lifetime, Visitor& visitor)
|
||||
{
|
||||
static_assert(
|
||||
(ParseFlags & rapidjson::kParseInsituFlag) == 0,
|
||||
"VisitSerializedJsonInPlace requires kParseInSituFlag not to be set, use VisitSerializedJsonInPlace to parse in-situ");
|
||||
|
||||
rapidjson::Reader reader;
|
||||
rapidjson::MemoryStream stream(buffer.data(), buffer.size());
|
||||
RapidJsonReadHandler handler(&visitor, lifetime);
|
||||
|
||||
reader.Parse<ParseFlags>(stream, handler);
|
||||
return handler.TakeOutcome();
|
||||
}
|
||||
|
||||
template<int ParseFlags>
|
||||
Visitor::Result VisitSerializedJsonInPlace(AZStd::string& buffer, Visitor& visitor)
|
||||
{
|
||||
static_assert((ParseFlags & rapidjson::kParseInsituFlag) != 0, "VisitSerializedJsonInPlace requires kParseInSituFlag to be set");
|
||||
|
||||
rapidjson::Reader reader;
|
||||
AzStringStream stream(buffer);
|
||||
RapidJsonReadHandler handler(&visitor, Lifetime::Persistent);
|
||||
|
||||
reader.Parse<ParseFlags>(stream, handler);
|
||||
return handler.TakeOutcome();
|
||||
}
|
||||
} // namespace AZ::Dom::Json
|
||||
|
||||
Reference in New Issue
Block a user