1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcm/ast/Attribute.hpp>
  7 #include <sngcm/ast/Visitor.hpp>
  8 #include <sngcm/ast/AstWriter.hpp>
  9 #include <sngcm/ast/AstReader.hpp>
 10 #include <soulng/util/Unicode.hpp>
 11 
 12 namespace sngcm { namespace ast {
 13 
 14 using namespace soulng::unicode;
 15 
 16 AttributeNode::AttributeNode(const Span& span_const boost::uuids::uuid& moduleId_) : Node(NodeType::attributeNodespan_moduleId_)name()value()
 17 {
 18 }
 19 
 20 AttributeNode::AttributeNode(const Span& span_const boost::uuids::uuid& moduleId_const std::u32string& name_const std::u32string& value_) :
 21     Node(NodeType::attributeNodespan_moduleId_)name(name_)value(value_)
 22 {
 23 }
 24 
 25 Node* AttributeNode::Clone(CloneContext& cloneContext) const
 26 {
 27     return new AttributeNode(GetSpan()ModuleId()namevalue);
 28 }
 29 
 30 void AttributeNode::Accept(Visitor& visitor)
 31 {
 32     visitor.Visit(*this);
 33 }
 34 
 35 void AttributeNode::Write(AstWriter& writer)
 36 {
 37     Node::Write(writer);
 38     writer.GetBinaryWriter().Write(name);
 39     writer.GetBinaryWriter().Write(value);
 40 }
 41 
 42 void AttributeNode::Read(AstReader& reader)
 43 {
 44     Node::Read(reader);
 45     name = reader.GetBinaryReader().ReadUtf32String();
 46     value = reader.GetBinaryReader().ReadUtf32String();
 47 }
 48 
 49 AttributesNode::AttributesNode(const Span& span_const boost::uuids::uuid& moduleId_) : Node(NodeType::attributesNodespan_moduleId_)
 50 {
 51 }
 52 
 53 AttributeNode* AttributesNode::GetAttribute(const std::u32string& name) const
 54 {
 55     std::map<std::u32stringAttributeNode*>::const_iterator it = attributeMap.find(name);
 56     if (it != attributeMap.cend())
 57     {
 58         return it->second;
 59     }
 60     return nullptr;
 61 }
 62 
 63 void AttributesNode::AddAttribute(const Span& spanconst boost::uuids::uuid& moduleIdconst std::u32string& name)
 64 {
 65     AddAttribute(spanmoduleIdnameU"true");
 66 }
 67 
 68 void AttributesNode::AddAttribute(const Span& spanconst boost::uuids::uuid& moduleIdconst std::u32string& nameconst std::u32string& value)
 69 {
 70     AttributeNode* prev = GetAttribute(name);
 71     if (prev != nullptr)
 72     {
 73         throw AttributeNotUniqueException("attribute '" + ToUtf8(name) + "' not unique"spanmoduleIdprev->GetSpan()prev->ModuleId());
 74     }
 75     AttributeNode* attribute = new AttributeNode(spanmoduleIdnamevalue);
 76     AddAttribute(attribute);
 77 }
 78 
 79 void AttributesNode::AddAttribute(AttributeNode* attribute)
 80 {
 81     attributes.push_back(std::unique_ptr<AttributeNode>(attribute));
 82     attributeMap[attribute->Name()] = attribute;
 83 }
 84 
 85 Node* AttributesNode::Clone(CloneContext& cloneContext) const
 86 {
 87     std::unique_ptr<AttributesNode> clone(new AttributesNode(GetSpan()ModuleId()));
 88     for (const std::std::unique_ptr<AttributeNode>&attribute : attributes)
 89     {
 90         clone->AddAttribute(attribute->GetSpan()attribute->ModuleId()attribute->Name()attribute->Value());
 91     }
 92     return clone.release();
 93 }
 94 
 95 void AttributesNode::Accept(Visitor& visitor)
 96 {
 97     visitor.Visit(*this);
 98 }
 99 
100 void AttributesNode::Write(AstWriter& writer)
101 {
102     Node::Write(writer);
103     writer.GetBinaryWriter().WriteULEB128UInt(static_cast<uint32_t>(attributes.size()));
104     for (const std::std::unique_ptr<AttributeNode>&attribute : attributes)
105     {
106         writer.Write(attribute.get());
107     }
108 }
109 
110 void AttributesNode::Read(AstReader& reader)
111 {
112     Node::Read(reader);
113     uint32_t n = reader.GetBinaryReader().ReadULEB128UInt();
114     for (uint32_t i = 0u; i < n; ++i)
115     {
116         AttributeNode* attribute = reader.ReadAttributeNode();
117         AddAttribute(attribute);
118     }
119 }
120 
121 AttributeNotUniqueException::AttributeNotUniqueException(const std::string& message_const Span& span_const boost::uuids::uuid& moduleId_
122     const Span& prevSpan_const boost::uuids::uuid& prevModuleId_) : std::runtime_error(message_)span(span_)moduleId(moduleId_)prevSpan(prevSpan_)prevModuleId(prevModuleId_)
123 {
124 }
125 
126 } } // namespace sngcm::ast