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