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
static std::string XMLEscape(std::string_view str)
Definition: XMLElement.cc:237
static std::unique_ptr< FileContext > getLastSerializedFileContext()
Definition: XMLElement.cc:266
void serialize(Archive &ar, unsigned version)
Definition: XMLElement.cc:283
XMLElement & addChild(String1 &&childName, String2 &&childData)
Definition: XMLElement.hh:99
void removeAttribute(std::string_view name)
Definition: XMLElement.cc:43
void addAttribute(String1 &&attrName, String2 &&value)
Definition: XMLElement.hh:64
XMLElement & addChild(String &&childName)
Definition: XMLElement.hh:94
void setAttribute(String1 &&attrName, String2 &&value)
Definition: XMLElement.hh:71
const XMLElement * findChild(std::string_view childName) const
Definition: XMLElement.cc:67
const std::string & getName() const
Definition: XMLElement.hh:47
const Children & getChildren() const
Definition: XMLElement.hh:105
XMLElement(XMLElement &x)
Definition: XMLElement.hh:36
XMLElement(XMLElement &&)=default
const XMLElement * findNextChild(std::string_view name, size_t &fromIndex) const
Definition: XMLElement.cc:72
std::vector< XMLElement > Children
Definition: XMLElement.hh:90
int getAttributeAsInt(std::string_view attrName, int defaultValue=0) const
Definition: XMLElement.cc:179
void setName(String &&name_)
Definition: XMLElement.hh:51
void setData(String &&data_)
Definition: XMLElement.hh:57
const std::string & getData() const
Definition: XMLElement.hh:54
bool findAttributeInt(std::string_view attrName, unsigned &result) const
Definition: XMLElement.cc:188
bool hasChildren() const
Definition: XMLElement.hh:106
bool hasAttribute(std::string_view name) const
Definition: XMLElement.cc:152
XMLElement & operator=(XMLElement &&)=default
const std::string & getChildData(std::string_view childName) const
Definition: XMLElement.cc:121
XMLElement(const XMLElement &e)
Definition: XMLElement.hh:31
void removeChild(const XMLElement &child)
Definition: XMLElement.cc:20
XMLElement & getCreateChild(String1 &&childName, String2 &&defaultValue)
Definition: XMLElement.hh:146
const XMLElement & getChild(std::string_view childName) const
Definition: XMLElement.cc:116
const XMLElement * findChildWithAttribute(std::string_view childName, std::string_view attrName, std::string_view attValue) const
Definition: XMLElement.cc:102
bool getAttributeAsBool(std::string_view attrName, bool defaultValue=false) const
Definition: XMLElement.cc:172
int getChildDataAsInt(std::string_view childName, int defaultValue=0) const
Definition: XMLElement.cc:139
void setChildData(String1 &&childName, String2 &&value)
Definition: XMLElement.hh:176
XMLElement & getCreateChild(String &&childName)
Definition: XMLElement.hh:138
XMLElement & getCreateChildWithAttribute(String1 &&childName, String2 &&attrName, String3 &&attValue)
Definition: XMLElement.hh:155
XMLElement(String1 &&name_, String2 &&data_)
Definition: XMLElement.hh:43
std::string dump() const
Definition: XMLElement.cc:200
XMLElement(String &&name_)
Definition: XMLElement.hh:39
bool getChildDataAsBool(std::string_view childName, bool defaultValue=false) const
Definition: XMLElement.cc:133
const std::string & getAttribute(std::string_view attrName) const
Definition: XMLElement.cc:157
XMLElement & operator=(const XMLElement &)=default
const std::string * findAttribute(std::string_view attrName) const
Definition: XMLElement.cc:37
This file implemented 3 utility functions:
Definition: Autofire.cc:5
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:124
constexpr auto end(const zstring_view &x)
Definition: zstring_view.hh:83