Move ValueWriter out, add DeepCompareIsEqual

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
Nicholas Van Sickle
2021-12-09 15:25:20 -08:00
parent fada7ace23
commit e7c92b5658
5 changed files with 504 additions and 260 deletions
+200 -205
View File
@@ -9,7 +9,7 @@
#pragma once
#include <AzCore/DOM/DomValue.h>
#include <AzCore/DOM/DomValueWriter.h>
#include <AzCore/std/smart_ptr/make_shared.h>
namespace AZ::Dom
@@ -26,6 +26,11 @@ namespace AZ::Dom
return refCountedPointer;
}
Node::Node(AZ::Name name)
: m_name(name)
{
}
AZ::Name Node::GetName() const
{
return m_name;
@@ -36,31 +41,24 @@ namespace AZ::Dom
m_name = name;
}
ObjectPtr Node::GetMutableProperties()
Object::ContainerType& Node::GetProperties()
{
CheckCopyOnWrite(m_object);
return m_object;
return m_properties;
}
ConstObjectPtr Node::GetProperties() const
const Object::ContainerType& Node::GetProperties() const
{
return m_object;
return m_properties;
}
ArrayPtr Node::GetMutableChildren()
Array::ContainerType& Node::GetChildren()
{
CheckCopyOnWrite(m_array);
return m_array;
return m_children;
}
ConstArrayPtr Node::GetChildren() const
const Array::ContainerType& Node::GetChildren() const
{
return m_array;
}
bool Node::operator==(const Node& rhs) const
{
return m_name == rhs.m_name && m_array == rhs.m_array && m_object == rhs.m_object;
return m_children;
}
Value::Value()
@@ -187,7 +185,7 @@ namespace AZ::Dom
return Type::ObjectType;
case 8: // ArrayPtr
return Type::ArrayType;
case 9: // Node
case 9: // NodePtr
return Type::NodeType;
case 10: // AZStd::any*
return Type::OpaqueType;
@@ -267,18 +265,31 @@ namespace AZ::Dom
return *this;
}
const Node& Value::GetNodeInternal() const
{
AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: attempted to retrieve a node from a non-node value");
return *AZStd::get<NodePtr>(m_value);
}
Node& Value::GetNodeInternal()
{
AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: attempted to retrieve a node from a non-node value");
return *CheckCopyOnWrite(AZStd::get<NodePtr>(m_value));
}
const Object::ContainerType& Value::GetObjectInternal() const
{
const Type type = GetType();
AZ_Assert(
type == Type::ObjectType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an object from a non-object value");
type == Type::ObjectType || type == Type::NodeType,
"AZ::Dom::Value: attempted to retrieve an object from a value that isn't an object or a node");
if (type == Type::ObjectType)
{
return AZStd::get<ObjectPtr>(m_value)->m_values;
}
else
{
return AZStd::get<Node>(m_value).GetProperties()->m_values;
return AZStd::get<NodePtr>(m_value)->GetProperties();
}
}
@@ -286,14 +297,15 @@ namespace AZ::Dom
{
const Type type = GetType();
AZ_Assert(
type == Type::ObjectType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an object from a non-object value");
type == Type::ObjectType || type == Type::NodeType,
"AZ::Dom::Value: attempted to retrieve an object from a value that isn't an object or a node");
if (type == Type::ObjectType)
{
return CheckCopyOnWrite(AZStd::get<ObjectPtr>(m_value))->m_values;
}
else
{
return AZStd::get<Node>(m_value).GetMutableProperties()->m_values;
return CheckCopyOnWrite(AZStd::get<NodePtr>(m_value))->GetProperties();
}
}
@@ -301,14 +313,15 @@ namespace AZ::Dom
{
const Type type = GetType();
AZ_Assert(
type == Type::ArrayType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an array from a non-array value");
type == Type::ArrayType || type == Type::NodeType,
"AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or a node");
if (type == Type::ObjectType)
{
return AZStd::get<ArrayPtr>(m_value)->m_values;
}
else
{
return AZStd::get<Node>(m_value).GetChildren()->m_values;
return AZStd::get<NodePtr>(m_value)->GetChildren();
}
}
@@ -316,14 +329,15 @@ namespace AZ::Dom
{
const Type type = GetType();
AZ_Assert(
type == Type::ArrayType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an array from a non-array value");
type == Type::ArrayType || type == Type::NodeType,
"AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or node");
if (type == Type::ObjectType)
{
return CheckCopyOnWrite(AZStd::get<ArrayPtr>(m_value))->m_values;
}
else
{
return AZStd::get<Node>(m_value).GetMutableChildren()->m_values;
return CheckCopyOnWrite(AZStd::get<NodePtr>(m_value))->GetChildren();
}
}
@@ -627,6 +641,67 @@ namespace AZ::Dom
return GetArrayInternal();
}
void Value::SetNode(AZ::Name name)
{
m_value = AZStd::make_shared<Node>(name);
}
void Value::SetNode(AZStd::string_view name)
{
SetNode(AZ::Name(name));
}
AZ::Name Value::GetNodeName() const
{
return GetNodeInternal().GetName();
}
void Value::SetNodeName(AZ::Name name)
{
GetNodeInternal().SetName(name);
}
void Value::SetNodeName(AZStd::string_view name)
{
SetNodeName(AZ::Name(name));
}
void Value::SetNodeValue(Value value)
{
AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: Attempted to set value for non-node type");
Array::ContainerType& nodeChildren = GetArrayInternal();
// Set the first non-node child, if one is found
for (Value& entry : nodeChildren)
{
if (entry.GetType() != Type::NodeType)
{
entry = AZStd::move(value);
return;
}
}
// Otherwise, append the value entry
nodeChildren.push_back(AZStd::move(value));
}
Value Value::GetNodeValue() const
{
AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: Attempted to get value for non-node type");
const Array::ContainerType& nodeChildren = GetArrayInternal();
// Get the first non-node child, if one is found
for (const Value& entry : nodeChildren)
{
if (entry.GetType() != Type::NodeType)
{
return entry;
}
}
return Value();
}
int64_t Value::GetInt() const
{
switch (m_value.index())
@@ -812,9 +887,9 @@ namespace AZ::Dom
result = visitor.EndArray(arrayContainer.size());
}
}
else if constexpr (AZStd::is_same_v<Alternative, Node>)
else if constexpr (AZStd::is_same_v<Alternative, NodePtr>)
{
const Node& node = AZStd::get<Node>(m_value);
const Node& node = *AZStd::get<NodePtr>(m_value);
result = visitor.StartNode(node.GetName());
if (result.IsSuccess())
{
@@ -850,204 +925,124 @@ namespace AZ::Dom
return result;
}
ValueWriter::ValueWriter(Value& outputValue)
: m_result(outputValue)
AZStd::unique_ptr<Visitor> Value::GetWriteHandler()
{
return AZStd::make_unique<ValueWriter>(*this);
}
VisitorFlags ValueWriter::GetVisitorFlags() const
bool Value::DeepCompareIsEqual(const Value& other) const
{
return VisitorFlags::SupportsRawKeys | VisitorFlags::SupportsArrays | VisitorFlags::SupportsObjects | VisitorFlags::SupportsNodes;
}
ValueWriter::ValueInfo::ValueInfo(Value& container)
: m_container(container)
{
}
Visitor::Result ValueWriter::Null()
{
CurrentValue().SetNull();
return FinishWrite();
}
Visitor::Result ValueWriter::Bool(bool value)
{
CurrentValue().SetBool(value);
return FinishWrite();
}
Visitor::Result ValueWriter::Int64(AZ::s64 value)
{
CurrentValue().SetInt(value);
return FinishWrite();
}
Visitor::Result ValueWriter::Uint64(AZ::u64 value)
{
CurrentValue().SetUint(value);
return FinishWrite();
}
Visitor::Result ValueWriter::Double(double value)
{
CurrentValue().SetDouble(value);
return FinishWrite();
}
Visitor::Result ValueWriter::String(AZStd::string_view value, Lifetime lifetime)
{
if (lifetime == Lifetime::Persistent)
if (m_value.index() != other.m_value.index())
{
CurrentValue().SetString(value);
}
else
{
CurrentValue().CopyFromString(value);
}
return FinishWrite();
}
Visitor::Result ValueWriter::StartObject()
{
CurrentValue().SetObject();
m_entryStack.emplace(CurrentValue());
return VisitorSuccess();
}
Visitor::Result ValueWriter::EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount)
{
const char* endMethodName;
switch (containerType)
{
case Type::ObjectType:
endMethodName = "EndObject";
break;
case Type::ArrayType:
endMethodName = "EndArray";
break;
case Type::NodeType:
endMethodName = "EndNode";
break;
default:
AZ_Assert(false, "Invalid container type specified");
return VisitorFailure(VisitorErrorCode::InternalError, "AZ::Dom::ValueWriter: EndContainer called with invalid container type");
return false;
}
if (m_entryStack.empty())
{
return VisitorFailure(
VisitorErrorCode::InternalError,
AZStd::string::format("AZ::Dom::ValueWriter: %s called without a matching call", endMethodName));
}
return AZStd::visit(
[&](auto&& ourValue) -> bool
{
using Alternative = AZStd::decay_t<decltype(ourValue)>;
auto&& theirValue = AZStd::get<AZStd::remove_cvref_t<decltype(ourValue)>>(other.m_value);
const ValueInfo& topEntry = m_entryStack.top();
if (topEntry.m_container.GetType() != containerType)
{
return VisitorFailure(
VisitorErrorCode::InternalError,
AZStd::string::format("AZ::Dom::ValueWriter: %s called from within a different container type", endMethodName));
}
if constexpr (AZStd::is_same_v<Alternative, AZStd::monostate>)
{
return true;
}
else if constexpr (AZStd::is_same_v<Alternative, ObjectPtr>)
{
if (ourValue == theirValue)
{
return true;
}
if (topEntry.m_attributeCount != attributeCount)
{
return VisitorFailure(
VisitorErrorCode::InternalError,
AZStd::string::format(
"AZ::Dom::ValueWriter: %s expected %llu attributes but received %llu attributes instead", endMethodName, attributeCount,
topEntry.m_attributeCount));
}
if (ourValue->m_values.size() != theirValue->m_values.size())
{
return false;
}
if (topEntry.m_elementCount != elementCount)
{
return VisitorFailure(
VisitorErrorCode::InternalError,
AZStd::string::format(
"AZ::Dom::ValueWriter: %s expected %llu elements but received %llu elements instead", endMethodName, elementCount,
topEntry.m_elementCount));
}
for (size_t i = 0; i < ourValue->m_values.size(); ++i)
{
const Object::EntryType& lhs = ourValue->m_values[i];
const Object::EntryType& rhs = theirValue->m_values[i];
if (lhs.first != rhs.first || !lhs.second.DeepCompareIsEqual(rhs.second))
{
return false;
}
}
m_entryStack.pop();
return FinishWrite();
}
return true;
}
else if constexpr (AZStd::is_same_v<Alternative, ArrayPtr>)
{
if (ourValue == theirValue)
{
return true;
}
Visitor::Result ValueWriter::EndObject(AZ::u64 attributeCount)
{
return EndContainer(Type::ObjectType, attributeCount, 0);
}
if (ourValue->m_values.size() != theirValue->m_values.size())
{
return false;
}
Visitor::Result ValueWriter::Key(AZ::Name key)
{
AZ_Assert(!m_entryStack.empty(), "Attempmted to push a key with no object");
AZ_Assert(!m_entryStack.top().m_container.IsArray(), "Attempted to push a key to an array");
m_entryStack.top().m_key = key;
return VisitorSuccess();
}
for (size_t i = 0; i < ourValue->m_values.size(); ++i)
{
const Value& lhs = ourValue->m_values[i];
const Value& rhs = theirValue->m_values[i];
if (!lhs.DeepCompareIsEqual(rhs))
{
return false;
}
}
Visitor::Result ValueWriter::RawKey(AZStd::string_view key, [[maybe_unused]] Lifetime lifetime)
{
return Key(AZ::Name(key));
}
return true;
}
else if constexpr (AZStd::is_same_v<Alternative, NodePtr>)
{
if (ourValue == theirValue)
{
return true;
}
Visitor::Result ValueWriter::StartArray()
{
CurrentValue().SetArray();
const Node& ourNode = *ourValue;
const Node& theirNode = *theirValue;
m_entryStack.emplace(CurrentValue());
return VisitorSuccess();
}
const Object::ContainerType& ourProperties = ourNode.GetProperties();
const Object::ContainerType& theirProperties = theirNode.GetProperties();
Visitor::Result ValueWriter::EndArray(AZ::u64 elementCount)
{
return EndContainer(Type::ArrayType, 0, elementCount);
}
if (ourProperties.size() != theirProperties.size())
{
return false;
}
Visitor::Result ValueWriter::StartNode(AZ::Name name)
{
CurrentValue().SetNode(name);
for (size_t i = 0; i < ourProperties.size(); ++i)
{
const Object::EntryType& lhs = ourProperties[i];
const Object::EntryType& rhs = theirProperties[i];
if (lhs.first != rhs.first || !lhs.second.DeepCompareIsEqual(rhs.second))
{
return false;
}
}
m_entryStack.emplace(CurrentValue());
return VisitorSuccess();
}
const Array::ContainerType& ourChildren = ourNode.GetChildren();
const Array::ContainerType& theirChildren = theirNode.GetChildren();
Visitor::Result ValueWriter::EndNode(AZ::u64 attributeCount, AZ::u64 elementCount)
{
return EndContainer(Type::NodeType, attributeCount, elementCount);
}
for (size_t i = 0; i < ourChildren.size(); ++i)
{
const Value& lhs = ourChildren[i];
const Value& rhs = theirChildren[i];
if (!lhs.DeepCompareIsEqual(rhs))
{
return false;
}
}
Visitor::Result ValueWriter::FinishWrite()
{
if (m_entryStack.empty())
{
return VisitorSuccess();
}
Value value;
m_entryStack.top().m_value.Swap(value);
ValueInfo& newEntry = m_entryStack.top();
if (!newEntry.m_key.IsEmpty())
{
newEntry.m_container.AddMember(newEntry.m_key, AZStd::move(value));
newEntry.m_key = AZ::Name();
++newEntry.m_attributeCount;
}
else
{
newEntry.m_container.PushBack(AZStd::move(value));
++newEntry.m_elementCount;
}
return VisitorSuccess();
}
Value& ValueWriter::CurrentValue()
{
if (m_entryStack.empty())
{
return m_result;
}
return m_entryStack.top().m_value;
return true;
}
else
{
return ourValue == theirValue;
}
},
m_value);
}
} // namespace AZ::Dom
+26 -55
View File
@@ -8,13 +8,13 @@
#pragma once
#include <AzCore/DOM/DomBackend.h>
#include <AzCore/DOM/DomVisitor.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/std/containers/stack.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/containers/variant.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/stack.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
namespace AZ::Dom
@@ -72,25 +72,34 @@ namespace AZ::Dom
class Node
{
public:
Node() = default;
Node(AZ::Name name);
Node(const Node&) = default;
Node(Node&&) = default;
Node& operator=(const Node&) = default;
Node& operator=(Node&&) = default;
AZ::Name GetName() const;
void SetName(AZ::Name name);
ObjectPtr GetMutableProperties();
ConstObjectPtr GetProperties() const;
Object::ContainerType& GetProperties();
const Object::ContainerType& GetProperties() const;
ArrayPtr GetMutableChildren();
ConstArrayPtr GetChildren() const;
bool operator==(const Node& rhs) const;
Array::ContainerType& GetChildren();
const Array::ContainerType& GetChildren() const;
private:
AZ::Name m_name;
ArrayPtr m_array;
ObjectPtr m_object;
Object::ContainerType m_properties;
Array::ContainerType m_children;
friend class Value;
};
using NodePtr = AZStd::shared_ptr<Node>;
using ConstNodePtr = AZStd::shared_ptr<Node>;
class Value
{
public:
@@ -252,8 +261,13 @@ namespace AZ::Dom
// Visitor API
Visitor::Result Accept(Visitor& visitor, bool copyStrings) const;
AZStd::unique_ptr<Visitor> GetWriteHandler();
bool DeepCompareIsEqual(const Value& other) const;
private:
const Node& GetNodeInternal() const;
Node& GetNodeInternal();
const Object::ContainerType& GetObjectInternal() const;
Object::ContainerType& GetObjectInternal();
const Array::ContainerType& GetArrayInternal() const;
@@ -284,53 +298,10 @@ namespace AZ::Dom
// ArrayType
ArrayPtr,
// NodeType
Node,
NodePtr,
// OpaqueType
AZStd::any*>;
ValueType m_value;
};
class ValueWriter : public Visitor
{
public:
ValueWriter(Value& outputValue);
VisitorFlags GetVisitorFlags() const override;
Result Null() override;
Result Bool(bool value) override;
Result Int64(AZ::s64 value) override;
Result Uint64(AZ::u64 value) override;
Result Double(double value) override;
Result String(AZStd::string_view value, Lifetime lifetime) override;
Result StartObject() override;
Result EndObject(AZ::u64 attributeCount) override;
Result Key(AZ::Name key) override;
Result RawKey(AZStd::string_view key, Lifetime lifetime) override;
Result StartArray() override;
Result EndArray(AZ::u64 elementCount) override;
Result StartNode(AZ::Name name) override;
Result RawStartNode(AZStd::string_view name, Lifetime lifetime) override;
Result EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) override;
private:
Result FinishWrite();
Value& CurrentValue();
Visitor::Result EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount);
struct ValueInfo
{
ValueInfo(Value& container);
KeyType m_key;
Value m_value;
Value& m_container;
AZ::u64 m_attributeCount = 0;
AZ::u64 m_elementCount = 0;
};
Value& m_result;
AZStd::stack<ValueInfo> m_entryStack;
};
} // namespace AZ::Dom
} // namespace AZ::Dom
@@ -0,0 +1,218 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/DOM/DomValueWriter.h>
namespace AZ::Dom
{
ValueWriter::ValueWriter(Value& outputValue)
: m_result(outputValue)
{
}
VisitorFlags ValueWriter::GetVisitorFlags() const
{
return VisitorFlags::SupportsRawKeys | VisitorFlags::SupportsArrays | VisitorFlags::SupportsObjects | VisitorFlags::SupportsNodes;
}
ValueWriter::ValueInfo::ValueInfo(Value& container)
: m_container(container)
{
}
Visitor::Result ValueWriter::Null()
{
CurrentValue().SetNull();
return FinishWrite();
}
Visitor::Result ValueWriter::Bool(bool value)
{
CurrentValue().SetBool(value);
return FinishWrite();
}
Visitor::Result ValueWriter::Int64(AZ::s64 value)
{
CurrentValue().SetInt(value);
return FinishWrite();
}
Visitor::Result ValueWriter::Uint64(AZ::u64 value)
{
CurrentValue().SetUint(value);
return FinishWrite();
}
Visitor::Result ValueWriter::Double(double value)
{
CurrentValue().SetDouble(value);
return FinishWrite();
}
Visitor::Result ValueWriter::String(AZStd::string_view value, Lifetime lifetime)
{
if (lifetime == Lifetime::Persistent)
{
CurrentValue().SetString(value);
}
else
{
CurrentValue().CopyFromString(value);
}
return FinishWrite();
}
Visitor::Result ValueWriter::StartObject()
{
CurrentValue().SetObject();
m_entryStack.emplace(CurrentValue());
return VisitorSuccess();
}
Visitor::Result ValueWriter::EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount)
{
const char* endMethodName;
switch (containerType)
{
case Type::ObjectType:
endMethodName = "EndObject";
break;
case Type::ArrayType:
endMethodName = "EndArray";
break;
case Type::NodeType:
endMethodName = "EndNode";
break;
default:
AZ_Assert(false, "Invalid container type specified");
return VisitorFailure(VisitorErrorCode::InternalError, "AZ::Dom::ValueWriter: EndContainer called with invalid container type");
}
if (m_entryStack.empty())
{
return VisitorFailure(
VisitorErrorCode::InternalError,
AZStd::string::format("AZ::Dom::ValueWriter: %s called without a matching call", endMethodName));
}
const ValueInfo& topEntry = m_entryStack.top();
if (topEntry.m_container.GetType() != containerType)
{
return VisitorFailure(
VisitorErrorCode::InternalError,
AZStd::string::format("AZ::Dom::ValueWriter: %s called from within a different container type", endMethodName));
}
if (topEntry.m_attributeCount != attributeCount)
{
return VisitorFailure(
VisitorErrorCode::InternalError,
AZStd::string::format(
"AZ::Dom::ValueWriter: %s expected %llu attributes but received %llu attributes instead", endMethodName, attributeCount,
topEntry.m_attributeCount));
}
if (topEntry.m_elementCount != elementCount)
{
return VisitorFailure(
VisitorErrorCode::InternalError,
AZStd::string::format(
"AZ::Dom::ValueWriter: %s expected %llu elements but received %llu elements instead", endMethodName, elementCount,
topEntry.m_elementCount));
}
m_entryStack.pop();
return FinishWrite();
}
Visitor::Result ValueWriter::EndObject(AZ::u64 attributeCount)
{
return EndContainer(Type::ObjectType, attributeCount, 0);
}
Visitor::Result ValueWriter::Key(AZ::Name key)
{
AZ_Assert(!m_entryStack.empty(), "Attempmted to push a key with no object");
AZ_Assert(!m_entryStack.top().m_container.IsArray(), "Attempted to push a key to an array");
m_entryStack.top().m_key = key;
return VisitorSuccess();
}
Visitor::Result ValueWriter::RawKey(AZStd::string_view key, [[maybe_unused]] Lifetime lifetime)
{
return Key(AZ::Name(key));
}
Visitor::Result ValueWriter::StartArray()
{
CurrentValue().SetArray();
m_entryStack.emplace(CurrentValue());
return VisitorSuccess();
}
Visitor::Result ValueWriter::EndArray(AZ::u64 elementCount)
{
return EndContainer(Type::ArrayType, 0, elementCount);
}
Visitor::Result ValueWriter::StartNode(AZ::Name name)
{
CurrentValue().SetNode(name);
m_entryStack.emplace(CurrentValue());
return VisitorSuccess();
}
Visitor::Result ValueWriter::RawStartNode(AZStd::string_view name, [[maybe_unused]] Lifetime lifetime)
{
return StartNode(AZ::Name(name));
}
Visitor::Result ValueWriter::EndNode(AZ::u64 attributeCount, AZ::u64 elementCount)
{
return EndContainer(Type::NodeType, attributeCount, elementCount);
}
Visitor::Result ValueWriter::FinishWrite()
{
if (m_entryStack.empty())
{
return VisitorSuccess();
}
Value value;
m_entryStack.top().m_value.Swap(value);
ValueInfo& newEntry = m_entryStack.top();
if (!newEntry.m_key.IsEmpty())
{
newEntry.m_container.AddMember(newEntry.m_key, AZStd::move(value));
newEntry.m_key = AZ::Name();
++newEntry.m_attributeCount;
}
else
{
newEntry.m_container.PushBack(AZStd::move(value));
++newEntry.m_elementCount;
}
return VisitorSuccess();
}
Value& ValueWriter::CurrentValue()
{
if (m_entryStack.empty())
{
return m_result;
}
return m_entryStack.top().m_value;
}
} // namespace AZ::Dom
@@ -0,0 +1,58 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/DOM/DomValue.h>
#include <AzCore/std/containers/stack.h>
namespace AZ::Dom
{
class ValueWriter : public Visitor
{
public:
ValueWriter(Value& outputValue);
VisitorFlags GetVisitorFlags() const override;
Result Null() override;
Result Bool(bool value) override;
Result Int64(AZ::s64 value) override;
Result Uint64(AZ::u64 value) override;
Result Double(double value) override;
Result String(AZStd::string_view value, Lifetime lifetime) override;
Result StartObject() override;
Result EndObject(AZ::u64 attributeCount) override;
Result Key(AZ::Name key) override;
Result RawKey(AZStd::string_view key, Lifetime lifetime) override;
Result StartArray() override;
Result EndArray(AZ::u64 elementCount) override;
Result StartNode(AZ::Name name) override;
Result RawStartNode(AZStd::string_view name, Lifetime lifetime) override;
Result EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) override;
private:
Result FinishWrite();
Value& CurrentValue();
Visitor::Result EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount);
struct ValueInfo
{
ValueInfo(Value& container);
KeyType m_key;
Value m_value;
Value& m_container;
AZ::u64 m_attributeCount = 0;
AZ::u64 m_elementCount = 0;
};
Value& m_result;
AZStd::stack<ValueInfo> m_entryStack;
};
} // namespace AZ::Dom
@@ -133,6 +133,8 @@ set(FILES
DOM/DomUtils.h
DOM/DomValue.cpp
DOM/DomValue.h
DOM/DomValueWriter.cpp
DOM/DomValueWriter.h
DOM/DomVisitor.cpp
DOM/DomVisitor.h
DOM/Backends/JSON/JsonBackend.h