The Battle for Wesnoth  1.17.0-dev
simple_wml.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 #include <cstring>
19 
20 #include <cstddef>
21 #include <iosfwd>
22 #include <map>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 
27 #include "exceptions.hpp"
28 
29 namespace simple_wml {
30 
31 struct error : public game::error {
32  error(const char* msg);
33 };
34 
36 {
37 public:
38  string_span() : str_(nullptr), size_(0)
39  {}
40  string_span(const char* str, int size) : str_(str), size_(size)
41  {}
42  string_span(const char* str) : str_(str), size_(strlen(str))
43  {}
44  string_span(const char* begin, const char* end) : str_(begin), size_(end - begin)
45  {}
46 
47  typedef const char* const_iterator;
48  typedef const char* iterator;
49  typedef const char value_type;
50 
51  bool operator==(const char* o) const {
52  const char* i1 = str_;
53  const char* i2 = str_ + size_;
54  while(i1 != i2 && *o && *i1 == *o) {
55  ++i1;
56  ++o;
57  }
58 
59  return i1 == i2 && *o == 0;
60  }
61  bool operator!=(const char* o) const {
62  return !operator==(o);
63  }
64  bool operator==(const std::string& o) const {
65  return size_ == o.size() && memcmp(str_, o.data(), size_) == 0;
66  }
67  bool operator!=(const std::string& o) const {
68  return !operator==(o);
69  }
70  bool operator==(const string_span& o) const {
71  return size_ == o.size_ && memcmp(str_, o.str_, size_) == 0;
72  }
73  bool operator!=(const string_span& o) const {
74  return !operator==(o);
75  }
76  bool operator<(const string_span& o) const {
77  const int len = size_ < o.size_ ? size_ : o.size_;
78  for(int n = 0; n < len; ++n) {
79  if(str_[n] != o.str_[n]) {
80  if(str_[n] < o.str_[n]) {
81  return true;
82  } else {
83  return false;
84  }
85  }
86  }
87 
88  return size_ < o.size_;
89  }
90 
91  const char* begin() const { return str_; }
92  const char* end() const { return str_ + size_; }
93 
94  int size() const { return size_; }
95  bool empty() const { return size_ == 0; }
96  bool is_null() const { return str_ == nullptr; }
97 
98  bool to_bool(bool default_value=false) const;
99  int to_int() const;
100  std::string to_string() const;
101 
102  //returns a duplicate of the string span in a new[] allocated buffer
103  char* duplicate() const;
104 
105 private:
106  const char* str_;
107  unsigned int size_;
108 };
109 
110 std::ostream& operator<<(std::ostream& o, const string_span& s);
111 
112 class document;
113 
114 class node
115 {
116 public:
117  node(document& doc, node* parent);
118  node(document& doc, node* parent, const char** str, int depth=0);
119  ~node();
120  struct attribute
121  {
122  attribute(const string_span& k, const string_span& v) : key(k), value(v) {}
125  };
126  typedef std::vector<node*> child_list;
127 
128  const string_span& operator[](const char* key) const;
129  const string_span& attr(const char* key) const {
130  return (*this)[key];
131  }
132 
133  bool has_attr(const char* key) const;
134 
135  //sets an attribute in the WML node. The node will keep a direct reference
136  //to key and value which it will maintain for its lifetime. The caller
137  //MUST guarantee that the key and value buffers remain valid for the
138  //lifetime of the node.
139  node& set_attr(const char* key, const char* value);
140 
141  //functions which are identical to set_attr() except that the buffer
142  //referred to by 'value' will be duplicated and the new buffer managed by
143  //the node. The caller may destroy the value buffer as soon as the function
144  //returns. The key buffer must remain valid for the lifetime of the node.
145  node& set_attr_dup(const char* key, const char* value);
146  node& set_attr_dup(const char* key, const string_span& value);
147 
148  node& set_attr_int(const char* key, int value);
149 
150  node& add_child(const char* name);
151  node& add_child_at(const char* name, std::size_t index);
152  void remove_child(const char* name, std::size_t index);
153  void remove_child(const string_span& name, std::size_t index);
154 
155  node* child(const char* name);
156  const node* child(const char* name) const;
157 
158  const child_list& children(const char* name) const;
159 
160  const string_span& first_child() const;
161 
162  bool is_dirty() const { return output_cache_.is_null(); }
163 
164  enum CACHE_STATUS { REFRESH_CACHE, DO_NOT_MODIFY_CACHE };
165 
166  int output_size() const;
167  void output(char*& buf, CACHE_STATUS status=DO_NOT_MODIFY_CACHE);
168 
169  void copy_into(node& n) const;
170 
171  bool no_children() const { return children_.empty(); }
172  bool one_child() const { return children_.size() == 1 && children_.begin()->second.size() == 1; }
173 
174  void apply_diff(const node& diff);
175 
176  void set_doc(document* doc);
177 
178  int nchildren() const;
179  int nattributes_recursive() const;
180 
181 private:
182  node(const node&) = delete;
183  node& operator=(const node&) = delete;
184 
185  int get_children(const string_span& name);
186  int get_children(const char* name);
187 
188  void set_dirty();
189  void shift_buffers(ptrdiff_t offset);
190 
192 
193  typedef std::vector<attribute> attribute_list;
194  attribute_list attr_;
195 
197 
198  typedef std::pair<string_span, child_list> child_pair;
199  typedef std::vector<child_pair> child_map;
200 
201  static child_map::const_iterator find_in_map(const child_map& m, const string_span& attr);
202  static child_map::iterator find_in_map(child_map& m, const string_span& attr);
203  child_map children_;
204 
205  //a node position indicates the index into the child map where the node
206  //is, and then the index into the child list within where the node is.
207  struct node_pos {
208  node_pos(int child_map_index, int child_list_index)
209  : child_map_index(static_cast<unsigned short>(child_map_index)),
210  child_list_index(static_cast<unsigned short>(child_list_index))
211  {}
212  unsigned short child_map_index;
213  unsigned short child_list_index;
214  };
215 
216  //a list of all the children in order.
217  std::vector<node_pos> ordered_children_;
218 
219  void insert_ordered_child(int child_map_index, int child_list_index);
220  void remove_ordered_child(int child_map_index, int child_list_index);
221  void insert_ordered_child_list(int child_map_index);
222  void remove_ordered_child_list(int child_map_index);
223 
224  void check_ordered_children() const;
225 
227 };
228 
229 std::string node_to_string(const node& n);
230 
232 
234 
235 class document
236 {
237 public:
238  document();
239  explicit document(char* buf, INIT_BUFFER_CONTROL control=INIT_TAKE_OWNERSHIP);
240  document(const char* buf, INIT_STATE state);
241  explicit document(string_span compressed_buf);
242  ~document();
243  const char* dup_string(const char* str);
244  node& root() { if(!root_) { generate_root(); } return *root_; }
245  const node& root() const { if(!root_) { const_cast<document*>(this)->generate_root(); } return *root_; }
246 
247  const char* output();
248  string_span output_compressed(bool bzip2 = false);
249 
250  void compress();
251 
252  std::unique_ptr<document> clone();
253 
254  const string_span& operator[](const char* key) const {
255  return root()[key];
256  }
257 
258  const string_span& attr(const char* key) const {
259  return root()[key];
260  }
261 
262  node* child(const char* name) {
263  return root().child(name);
264  }
265 
266  const node* child(const char* name) const {
267  return root().child(name);
268  }
269 
270  const node::child_list& children(const char* name) const {
271  return root().children(name);
272  }
273 
274  node& set_attr(const char* key, const char* value) {
275  return root().set_attr(key, value);
276  }
277 
278  node& set_attr_dup(const char* key, const char* value) {
279  return root().set_attr_dup(key, value);
280  }
281 
282  void take_ownership_of_buffer(char* buffer) {
283  buffers_.push_back(buffer);
284  }
285 
286  void swap(document& o);
287  void clear();
288 
289  static std::string stats();
290 
291  static std::size_t document_size_limit;
292 private:
293  void generate_root();
294  document(const document&) = delete;
295  document& operator=(const document&) = delete;
296 
298  const char* output_;
299  std::vector<char*> buffers_;
301 
302  //linked list of documents for accounting purposes
303  void attach_list();
304  void detach_list();
307 };
308 
309 /** Implement non-member swap function for std::swap (calls @ref document::swap). */
310 void swap(document& lhs, document& rhs);
311 
312 }
const char * const_iterator
Definition: simple_wml.hpp:47
const string_span & attr(const char *key) const
Definition: simple_wml.hpp:129
string_span compressed_buf_
Definition: simple_wml.hpp:297
std::vector< attribute > attribute_list
Definition: simple_wml.hpp:193
bool operator==(const string_span &o) const
Definition: simple_wml.hpp:70
node & set_attr(const char *key, const char *value)
Definition: simple_wml.hpp:274
std::ostream & operator<<(std::ostream &o, const string_span &s)
Definition: simple_wml.cpp:201
const node * child(const char *name) const
Definition: simple_wml.hpp:266
string_span output_cache_
Definition: simple_wml.hpp:226
std::vector< char * > buffers_
Definition: simple_wml.hpp:299
const char * end() const
Definition: simple_wml.hpp:92
std::pair< string_span, child_list > child_pair
Definition: simple_wml.hpp:198
unsigned short child_list_index
Definition: simple_wml.hpp:213
void clear(const std::string &key)
Definition: general.cpp:186
node & set_attr(const char *key, const char *value)
Definition: simple_wml.cpp:412
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
attribute_list attr_
Definition: simple_wml.hpp:194
node & set_attr_dup(const char *key, const char *value)
Definition: simple_wml.hpp:278
document * doc_
Definition: simple_wml.hpp:191
string_span(const char *str, int size)
Definition: simple_wml.hpp:40
bool no_children() const
Definition: simple_wml.hpp:171
std::vector< child_pair > child_map
Definition: simple_wml.hpp:199
bool is_dirty() const
Definition: simple_wml.hpp:162
node * child(const char *name)
Definition: simple_wml.hpp:262
node * child(const char *name)
Definition: simple_wml.cpp:607
node_pos(int child_map_index, int child_list_index)
Definition: simple_wml.hpp:208
const char * begin() const
Definition: simple_wml.hpp:91
static std::ostream & output()
Definition: log.cpp:50
const string_span & operator[](const char *key) const
Definition: simple_wml.hpp:254
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
string_span(const char *begin, const char *end)
Definition: simple_wml.hpp:44
attribute(const string_span &k, const string_span &v)
Definition: simple_wml.hpp:122
const string_span & attr(const char *key) const
Definition: simple_wml.hpp:258
bool operator!=(const std::string &o) const
Definition: simple_wml.hpp:67
bool operator==(const char *o) const
Definition: simple_wml.hpp:51
bool operator!=(const string_span &o) const
Definition: simple_wml.hpp:73
unsigned short child_map_index
Definition: simple_wml.hpp:212
child_map children_
Definition: simple_wml.hpp:203
const node & root() const
Definition: simple_wml.hpp:245
static std::size_t document_size_limit
Definition: simple_wml.hpp:291
const char * output_
Definition: simple_wml.hpp:298
node & set_attr_dup(const char *key, const char *value)
Definition: simple_wml.cpp:428
const node::child_list & children(const char *name) const
Definition: simple_wml.hpp:270
bool operator==(const config &a, const config &b)
Definition: config.cpp:1475
static map_location::DIRECTION s
std::vector< node * > child_list
Definition: simple_wml.hpp:126
bool operator<(const string_span &o) const
Definition: simple_wml.hpp:76
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:72
string_span(const char *str)
Definition: simple_wml.hpp:42
bool one_child() const
Definition: simple_wml.hpp:172
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:28
bool operator==(const std::string &o) const
Definition: simple_wml.hpp:64
bool operator!=(const char *o) const
Definition: simple_wml.hpp:61
std::vector< node_pos > ordered_children_
Definition: simple_wml.hpp:217
void swap(document &lhs, document &rhs)
Implement non-member swap function for std::swap (calls document::swap).
static map_location::DIRECTION n
void take_ownership_of_buffer(char *buffer)
Definition: simple_wml.hpp:282
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
std::string node_to_string(const node &n)
Definition: simple_wml.cpp:794