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