openMSX
XMLElement.hh
Go to the documentation of this file.
1 #ifndef XMLELEMENT_HH
2 #define XMLELEMENT_HH
3 
4 #include "serialize_meta.hh"
5 #include <utility>
6 #include <string>
7 #include <string_view>
8 #include <vector>
9 #include <memory>
10 
11 namespace openmsx {
12 
13 class FileContext;
14 
16 {
17 public:
18  //
19  // Basic functions
20  //
21 
22  // Construction.
23  // (copy, assign, move, destruct are default)
24  XMLElement() = default;
25  XMLElement(XMLElement&&) = default;
26  XMLElement& operator=(const XMLElement&) = default;
28 
29  //workaround msvc bug(?)
30  //XMLElement(const XMLElement&) = default;
32  : name(e.name), data(e.data)
33  , children(e.children), attributes(e.attributes) {}
34 
35  // needed because the template below hides this version
36  XMLElement(XMLElement& x) : XMLElement(const_cast<const XMLElement&>(x)) {}
37 
38  template<typename String>
39  explicit XMLElement(String&& name_)
40  : name(std::forward<String>(name_)) {}
41 
42  template<typename String1, typename String2>
43  XMLElement(String1&& name_, String2&& data_)
44  : name(std::forward<String1>(name_)), data(std::forward<String2>(data_)) {}
45 
46  // name
47  [[nodiscard]] const std::string& getName() const { return name; }
48  void clearName() { name.clear(); }
49 
50  template<typename String>
51  void setName(String&& name_) { name = std::forward<String>(name_); }
52 
53  // data
54  [[nodiscard]] const std::string& getData() const { return data; }
55 
56  template<typename String>
57  void setData(String&& data_) {
58  assert(children.empty()); // no mixed-content elements
59  data = std::forward<String>(data_);
60  }
61 
62  // attribute
63  template<typename String1, typename String2>
64  void addAttribute(String1&& attrName, String2&& value) {
65  assert(!hasAttribute(attrName));
66  attributes.emplace_back(std::forward<String1>(attrName),
67  std::forward<String2>(value));
68  }
69 
70  template<typename String1, typename String2>
71  void setAttribute(String1&& attrName, String2&& value) {
72  auto it = getAttributeIter(attrName);
73  if (it != end(attributes)) {
74  it->second = std::forward<String2>(value);
75  } else {
76  attributes.emplace_back(std::forward<String1>(attrName),
77  std::forward<String2>(value));
78  }
79  }
80 
81  void removeAttribute(std::string_view name);
82  [[nodiscard]] bool hasAttribute(std::string_view name) const;
83  [[nodiscard]] const std::string& getAttribute(std::string_view attrName) const;
84  [[nodiscard]] std::string_view getAttribute(std::string_view attrName,
85  std::string_view defaultValue) const;
86  // Returns ptr to attribute value, or nullptr when not found.
87  [[nodiscard]] const std::string* findAttribute(std::string_view attrName) const;
88 
89  // child
90  using Children = std::vector<XMLElement>;
91 
92  // note: returned XMLElement& is validated on the next addChild() call
93  template<typename String>
94  XMLElement& addChild(String&& childName) {
95  return children.emplace_back(std::forward<String>(childName));
96  }
97 
98  template<typename String1, typename String2>
99  XMLElement& addChild(String1&& childName, String2&& childData) {
100  return children.emplace_back(std::forward<String1>(childName),
101  std::forward<String2>(childData));
102  }
103 
104  void removeChild(const XMLElement& child);
105  [[nodiscard]] const Children& getChildren() const { return children; }
106  [[nodiscard]] bool hasChildren() const { return !children.empty(); }
107 
108  //
109  // Convenience functions
110  //
111 
112  // attribute
113  [[nodiscard]] bool getAttributeAsBool(std::string_view attrName,
114  bool defaultValue = false) const;
115  [[nodiscard]] int getAttributeAsInt(std::string_view attrName,
116  int defaultValue = 0) const;
117  [[nodiscard]] bool findAttributeInt(std::string_view attrName,
118  unsigned& result) const;
119 
120  // child
121  [[nodiscard]] const XMLElement* findChild(std::string_view childName) const;
122  [[nodiscard]] XMLElement* findChild(std::string_view childName);
123  [[nodiscard]] const XMLElement& getChild(std::string_view childName) const;
124  [[nodiscard]] XMLElement& getChild(std::string_view childName);
125 
126  [[nodiscard]] const XMLElement* findChildWithAttribute(
127  std::string_view childName, std::string_view attrName,
128  std::string_view attValue) const;
129  [[nodiscard]] XMLElement* findChildWithAttribute(
130  std::string_view childName, std::string_view attrName,
131  std::string_view attValue);
132  [[nodiscard]] const XMLElement* findNextChild(std::string_view name,
133  size_t& fromIndex) const;
134 
135  [[nodiscard]] std::vector<const XMLElement*> getChildren(std::string_view childName) const;
136 
137  template<typename String>
138  XMLElement& getCreateChild(String&& childName) {
139  if (auto* result = findChild(childName)) {
140  return *result;
141  }
142  return addChild(std::forward<String>(childName));
143  }
144 
145  template<typename String1, typename String2>
146  XMLElement& getCreateChild(String1&& childName, String2&& defaultValue) {
147  if (auto* result = findChild(childName)) {
148  return *result;
149  }
150  return addChild(std::forward<String1>(childName),
151  std::forward<String2>(defaultValue));
152  }
153 
154  template<typename String1, typename String2, typename String3>
156  String1&& childName, String2&& attrName, String3&& attValue)
157  {
158  if (auto* result = findChildWithAttribute(childName, attrName, attValue)) {
159  return *result;
160  }
161  auto& result = addChild(std::forward<String1>(childName));
162  result.addAttribute(std::forward<String2>(attrName),
163  std::forward<String3>(attValue));
164  return result;
165  }
166 
167  [[nodiscard]] const std::string& getChildData(std::string_view childName) const;
168  [[nodiscard]] std::string_view getChildData(std::string_view childName,
169  std::string_view defaultValue) const;
170  [[nodiscard]] bool getChildDataAsBool(std::string_view childName,
171  bool defaultValue = false) const;
172  [[nodiscard]] int getChildDataAsInt(std::string_view childName,
173  int defaultValue = 0) const;
174 
175  template<typename String1, typename String2>
176  void setChildData(String1&& childName, String2&& value) {
177  if (auto* child = findChild(childName)) {
178  child->setData(std::forward<String2>(value));
179  } else {
180  addChild(std::forward<String1>(childName),
181  std::forward<String2>(value));
182  }
183  }
184 
185  void removeAllChildren();
186 
187  // various
188  [[nodiscard]] std::string dump() const;
189  [[nodiscard]] static std::string XMLEscape(std::string_view str);
190 
191  template<typename Archive>
192  void serialize(Archive& ar, unsigned version);
193 
194  // For backwards compatibility with older savestates
195  static std::unique_ptr<FileContext> getLastSerializedFileContext();
196 
197 private:
198  using Attribute = std::pair<std::string, std::string>;
199  using Attributes = std::vector<Attribute>;
200  [[nodiscard]] Attributes::iterator getAttributeIter(std::string_view attrName);
201  [[nodiscard]] Attributes::const_iterator getAttributeIter(std::string_view attrName) const;
202  void dump(std::string& result, unsigned indentNum) const;
203 
204  std::string name;
205  std::string data;
206  Children children;
207  Attributes attributes;
208 };
210 
211 } // namespace openmsx
212 
213 #endif
openmsx::XMLElement::addAttribute
void addAttribute(String1 &&attrName, String2 &&value)
Definition: XMLElement.hh:64
openmsx::XMLElement::XMLElement
XMLElement(String &&name_)
Definition: XMLElement.hh:39
openmsx::XMLElement::findAttribute
const std::string * findAttribute(std::string_view attrName) const
Definition: XMLElement.cc:37
openmsx::XMLElement::getChildDataAsBool
bool getChildDataAsBool(std::string_view childName, bool defaultValue=false) const
Definition: XMLElement.cc:133
openmsx::XMLElement::hasAttribute
bool hasAttribute(std::string_view name) const
Definition: XMLElement.cc:152
openmsx::XMLElement::getAttribute
const std::string & getAttribute(std::string_view attrName) const
Definition: XMLElement.cc:157
openmsx::XMLElement::findChildWithAttribute
const XMLElement * findChildWithAttribute(std::string_view childName, std::string_view attrName, std::string_view attValue) const
Definition: XMLElement.cc:102
openmsx::XMLElement::setName
void setName(String &&name_)
Definition: XMLElement.hh:51
serialize_meta.hh
openmsx::XMLElement::getChildData
const std::string & getChildData(std::string_view childName) const
Definition: XMLElement.cc:121
openmsx::XMLElement::addChild
XMLElement & addChild(String &&childName)
Definition: XMLElement.hh:94
openmsx::XMLElement::operator=
XMLElement & operator=(const XMLElement &)=default
end
auto end(const zstring_view &x)
Definition: zstring_view.hh:83
openmsx::XMLElement::removeChild
void removeChild(const XMLElement &child)
Definition: XMLElement.cc:20
openmsx::XMLElement::operator=
XMLElement & operator=(XMLElement &&)=default
openmsx::XMLElement::removeAllChildren
void removeAllChildren()
Definition: XMLElement.cc:147
openmsx::XMLElement::findNextChild
const XMLElement * findNextChild(std::string_view name, size_t &fromIndex) const
Definition: XMLElement.cc:72
openmsx::SERIALIZE_CLASS_VERSION
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
openmsx::XMLElement::serialize
void serialize(Archive &ar, unsigned version)
Definition: XMLElement.cc:283
openmsx::XMLElement::findChild
const XMLElement * findChild(std::string_view childName) const
Definition: XMLElement.cc:67
openmsx::XMLElement::findAttributeInt
bool findAttributeInt(std::string_view attrName, unsigned &result) const
Definition: XMLElement.cc:188
openmsx::XMLElement::XMLElement
XMLElement(XMLElement &&)=default
openmsx::XMLElement
Definition: XMLElement.hh:16
openmsx::XMLElement::getCreateChild
XMLElement & getCreateChild(String1 &&childName, String2 &&defaultValue)
Definition: XMLElement.hh:146
openmsx::XMLElement::getLastSerializedFileContext
static std::unique_ptr< FileContext > getLastSerializedFileContext()
Definition: XMLElement.cc:266
openmsx::XMLElement::removeAttribute
void removeAttribute(std::string_view name)
Definition: XMLElement.cc:43
openmsx::FileContext
FileContext
Definition: FileContext.cc:128
openmsx::XMLElement::clearName
void clearName()
Definition: XMLElement.hh:48
openmsx::XMLElement::dump
std::string dump() const
Definition: XMLElement.cc:200
openmsx::XMLElement::getName
const std::string & getName() const
Definition: XMLElement.hh:47
openmsx::XMLElement::Children
std::vector< XMLElement > Children
Definition: XMLElement.hh:90
openmsx::XMLElement::setData
void setData(String &&data_)
Definition: XMLElement.hh:57
openmsx::XMLElement::XMLElement
XMLElement(const XMLElement &e)
Definition: XMLElement.hh:31
openmsx::x
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:1414
openmsx::XMLElement::addChild
XMLElement & addChild(String1 &&childName, String2 &&childData)
Definition: XMLElement.hh:99
openmsx::XMLElement::getData
const std::string & getData() const
Definition: XMLElement.hh:54
openmsx::XMLElement::getAttributeAsInt
int getAttributeAsInt(std::string_view attrName, int defaultValue=0) const
Definition: XMLElement.cc:179
openmsx::XMLElement::getChildDataAsInt
int getChildDataAsInt(std::string_view childName, int defaultValue=0) const
Definition: XMLElement.cc:139
openmsx::XMLElement::getAttributeAsBool
bool getAttributeAsBool(std::string_view attrName, bool defaultValue=false) const
Definition: XMLElement.cc:172
openmsx::XMLElement::hasChildren
bool hasChildren() const
Definition: XMLElement.hh:106
openmsx::XMLElement::XMLEscape
static std::string XMLEscape(std::string_view str)
Definition: XMLElement.cc:237
openmsx::XMLElement::setAttribute
void setAttribute(String1 &&attrName, String2 &&value)
Definition: XMLElement.hh:71
openmsx::XMLElement::XMLElement
XMLElement(XMLElement &x)
Definition: XMLElement.hh:36
openmsx::XMLElement::getCreateChild
XMLElement & getCreateChild(String &&childName)
Definition: XMLElement.hh:138
openmsx::XMLElement::getChildren
const Children & getChildren() const
Definition: XMLElement.hh:105
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
openmsx::XMLElement::getCreateChildWithAttribute
XMLElement & getCreateChildWithAttribute(String1 &&childName, String2 &&attrName, String3 &&attValue)
Definition: XMLElement.hh:155
openmsx::XMLElement::setChildData
void setChildData(String1 &&childName, String2 &&value)
Definition: XMLElement.hh:176
openmsx::XMLElement::XMLElement
XMLElement()=default
openmsx::XMLElement::getChild
const XMLElement & getChild(std::string_view childName) const
Definition: XMLElement.cc:116
openmsx::XMLElement::XMLElement
XMLElement(String1 &&name_, String2 &&data_)
Definition: XMLElement.hh:43