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