1
2
3
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::attributeNode, span_, 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::attributeNode, span_, moduleId_), name(name_), value(value_)
22 {
23 }
24
25 Node* AttributeNode::Clone(CloneContext& cloneContext) const
26 {
27 return new AttributeNode(GetSpan(), ModuleId(), name, value);
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::attributesNode, span_, moduleId_)
50 {
51 }
52
53 AttributeNode* AttributesNode::GetAttribute(const std::u32string& name) const
54 {
55 std::map<std::u32string, AttributeNode*>::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& span, const boost::uuids::uuid& moduleId, const std::u32string& name)
64 {
65 AddAttribute(span, moduleId, name, U"true");
66 }
67
68 void AttributesNode::AddAttribute(const Span& span, const boost::uuids::uuid& moduleId, const std::u32string& name, const std::u32string& value)
69 {
70 AttributeNode* prev = GetAttribute(name);
71 if (prev != nullptr)
72 {
73 throw AttributeNotUniqueException("attribute '" + ToUtf8(name) + "' not unique", span, moduleId, prev->GetSpan(), prev->ModuleId());
74 }
75 AttributeNode* attribute = new AttributeNode(span, moduleId, name, value);
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 } }