The Battle for Wesnoth  1.19.7+dev
simple_wml.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2024
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 <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  node& child_or_add(const char* name);
158 
159  const child_list& children(const char* name) const;
160 
161  const string_span& first_child() const;
162 
163  bool is_dirty() const { return output_cache_.is_null(); }
164 
166 
167  int output_size() const;
168  void output(char*& buf, CACHE_STATUS status=DO_NOT_MODIFY_CACHE);
169 
170  void copy_into(node& n) const;
171 
172  bool no_children() const { return children_.empty(); }
173  bool one_child() const { return children_.size() == 1 && children_.begin()->second.size() == 1; }
174 
175  void apply_diff(const node& diff);
176 
177  void set_doc(document* doc);
178 
179  int nchildren() const;
180  int nattributes_recursive() const;
181 
182 private:
183  node(const node&) = delete;
184  node& operator=(const node&) = delete;
185 
186  int get_children(const string_span& name);
187  int get_children(const char* name);
188 
189  void set_dirty();
190  void shift_buffers(ptrdiff_t offset);
191 
193 
194  typedef std::vector<attribute> attribute_list;
196 
198 
199  typedef std::pair<string_span, child_list> child_pair;
200  typedef std::vector<child_pair> child_map;
201 
202  static child_map::const_iterator find_in_map(const child_map& m, const string_span& attr);
205 
206  //a node position indicates the index into the child map where the node
207  //is, and then the index into the child list within where the node is.
208  struct node_pos {
210  : child_map_index(static_cast<unsigned short>(child_map_index)),
211  child_list_index(static_cast<unsigned short>(child_list_index))
212  {}
213  unsigned short child_map_index;
214  unsigned short child_list_index;
215  };
216 
217  //a list of all the children in order.
218  std::vector<node_pos> ordered_children_;
219 
220  void insert_ordered_child(int child_map_index, int child_list_index);
221  void remove_ordered_child(int child_map_index, int child_list_index);
222  void insert_ordered_child_list(int child_map_index);
223  void remove_ordered_child_list(int child_map_index);
224 
225  void check_ordered_children() const;
226 
228 };
229 
230 std::string node_to_string(const node& n);
231 
233 
235 
236 class document
237 {
238 public:
239  document();
240  explicit document(char* buf, INIT_BUFFER_CONTROL control=INIT_TAKE_OWNERSHIP);
241  document(const char* buf, INIT_STATE state);
242  explicit document(string_span compressed_buf);
243  ~document();
244  const char* dup_string(const char* str);
245  node& root() { if(!root_) { generate_root(); } return *root_; }
246  const node& root() const { if(!root_) { const_cast<document*>(this)->generate_root(); } return *root_; }
247 
248  const char* output();
249  string_span output_compressed(bool bzip2 = false);
250 
251  void compress();
252 
253  std::unique_ptr<document> clone();
254 
255  const string_span& operator[](const char* key) const {
256  return root()[key];
257  }
258 
259  const string_span& attr(const char* key) const {
260  return root()[key];
261  }
262 
263  node* child(const char* name) {
264  return root().child(name);
265  }
266 
267  const node* child(const char* name) const {
268  return root().child(name);
269  }
270 
271  const node::child_list& children(const char* name) const {
272  return root().children(name);
273  }
274 
275  node& set_attr(const char* key, const char* value) {
276  return root().set_attr(key, value);
277  }
278 
279  node& set_attr_dup(const char* key, const char* value) {
280  return root().set_attr_dup(key, value);
281  }
282 
283  void take_ownership_of_buffer(char* buffer) {
284  buffers_.push_back(buffer);
285  }
286 
287  void swap(document& o);
288  void clear();
289 
290  static std::string stats();
291 
292  static std::size_t document_size_limit;
293 private:
294  void generate_root();
295  document(const document&) = delete;
296  document& operator=(const document&) = delete;
297 
299  const char* output_;
300  std::vector<char*> buffers_;
302 
303  //linked list of documents for accounting purposes
304  void attach_list();
305  void detach_list();
308 };
309 
310 /** Implement non-member swap function for std::swap (calls @ref document::swap). */
311 void swap(document& lhs, document& rhs);
312 
313 }
void take_ownership_of_buffer(char *buffer)
Definition: simple_wml.hpp:283
const char * output()
const node & root() const
Definition: simple_wml.hpp:246
node & set_attr_dup(const char *key, const char *value)
Definition: simple_wml.hpp:279
std::unique_ptr< document > clone()
static std::string stats()
const node * child(const char *name) const
Definition: simple_wml.hpp:267
document & operator=(const document &)=delete
document(const document &)=delete
static std::size_t document_size_limit
Definition: simple_wml.hpp:292
const string_span & operator[](const char *key) const
Definition: simple_wml.hpp:255
node * child(const char *name)
Definition: simple_wml.hpp:263
const char * output_
Definition: simple_wml.hpp:299
const node::child_list & children(const char *name) const
Definition: simple_wml.hpp:271
void swap(document &o)
std::vector< char * > buffers_
Definition: simple_wml.hpp:300
string_span output_compressed(bool bzip2=false)
const char * dup_string(const char *str)
const string_span & attr(const char *key) const
Definition: simple_wml.hpp:259
string_span compressed_buf_
Definition: simple_wml.hpp:298
node & set_attr(const char *key, const char *value)
Definition: simple_wml.hpp:275
const string_span & attr(const char *key) const
Definition: simple_wml.hpp:128
int output_size() const
Definition: simple_wml.cpp:706
void set_doc(document *doc)
Definition: simple_wml.cpp:910
void insert_ordered_child(int child_map_index, int child_list_index)
Definition: simple_wml.cpp:505
void insert_ordered_child_list(int child_map_index)
Definition: simple_wml.cpp:546
void check_ordered_children() const
Definition: simple_wml.cpp:573
void remove_child(const char *name, std::size_t index)
Definition: simple_wml.cpp:603
int nchildren() const
Definition: simple_wml.cpp:921
node(const node &)=delete
bool no_children() const
Definition: simple_wml.hpp:172
bool is_dirty() const
Definition: simple_wml.hpp:163
node(document &doc, node *parent)
Definition: simple_wml.cpp:208
int get_children(const string_span &name)
Definition: simple_wml.cpp:660
document * doc_
Definition: simple_wml.hpp:192
const string_span & operator[](const char *key) const
Definition: simple_wml.cpp:392
const child_list & children(const char *name) const
Definition: simple_wml.cpp:643
void apply_diff(const node &diff)
Definition: simple_wml.cpp:842
attribute_list attr_
Definition: simple_wml.hpp:195
bool has_attr(const char *key) const
Definition: simple_wml.cpp:405
node & set_attr_int(const char *key, int value)
Definition: simple_wml.cpp:441
std::vector< child_pair > child_map
Definition: simple_wml.hpp:200
node * child(const char *name)
Definition: simple_wml.cpp:608
std::vector< node * > child_list
Definition: simple_wml.hpp:125
void remove_ordered_child_list(int child_map_index)
Definition: simple_wml.cpp:556
int nattributes_recursive() const
Definition: simple_wml.cpp:934
std::vector< node_pos > ordered_children_
Definition: simple_wml.hpp:218
std::vector< attribute > attribute_list
Definition: simple_wml.hpp:194
const string_span & first_child() const
Definition: simple_wml.cpp:696
child_map children_
Definition: simple_wml.hpp:204
void output(char *&buf, CACHE_STATUS status=DO_NOT_MODIFY_CACHE)
Definition: simple_wml.cpp:752
node & add_child(const char *name)
Definition: simple_wml.cpp:466
node & child_or_add(const char *name)
Definition: simple_wml.cpp:635
node & operator=(const node &)=delete
node & set_attr(const char *key, const char *value)
Definition: simple_wml.cpp:413
string_span output_cache_
Definition: simple_wml.hpp:227
node & add_child_at(const char *name, std::size_t index)
Definition: simple_wml.cpp:447
void copy_into(node &n) const
Definition: simple_wml.cpp:821
node & set_attr_dup(const char *key, const char *value)
Definition: simple_wml.cpp:429
void remove_ordered_child(int child_map_index, int child_list_index)
Definition: simple_wml.cpp:527
void shift_buffers(ptrdiff_t offset)
Definition: simple_wml.cpp:732
std::pair< string_span, child_list > child_pair
Definition: simple_wml.hpp:199
bool one_child() const
Definition: simple_wml.hpp:173
static child_map::const_iterator find_in_map(const child_map &m, const string_span &attr)
Definition: simple_wml.cpp:672
bool to_bool(bool default_value=false) const
Definition: simple_wml.cpp:159
std::string to_string() const
Definition: simple_wml.cpp:183
string_span(const char *begin, const char *end)
Definition: simple_wml.hpp:43
bool operator<(const string_span &o) const
Definition: simple_wml.hpp:75
bool operator==(const std::string &o) const
Definition: simple_wml.hpp:63
const char * begin() const
Definition: simple_wml.hpp:90
char * duplicate() const
Definition: simple_wml.cpp:188
const char * end() const
Definition: simple_wml.hpp:91
bool operator!=(const string_span &o) const
Definition: simple_wml.hpp:72
string_span(const char *str)
Definition: simple_wml.hpp:41
string_span(const char *str, int size)
Definition: simple_wml.hpp:39
bool operator==(const char *o) const
Definition: simple_wml.hpp:50
const char * const_iterator
Definition: simple_wml.hpp:46
bool operator==(const string_span &o) const
Definition: simple_wml.hpp:69
bool operator!=(const char *o) const
Definition: simple_wml.hpp:60
bool operator!=(const std::string &o) const
Definition: simple_wml.hpp:66
void swap(document &lhs, document &rhs)
Implement non-member swap function for std::swap (calls document::swap).
std::ostream & operator<<(std::ostream &o, const string_span &s)
Definition: simple_wml.cpp:202
std::string node_to_string(const node &n)
Definition: simple_wml.cpp:809
@ INIT_TAKE_OWNERSHIP
Definition: simple_wml.hpp:232
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:29
attribute(const string_span &k, const string_span &v)
Definition: simple_wml.hpp:121
node_pos(int child_map_index, int child_list_index)
Definition: simple_wml.hpp:209
unsigned short child_map_index
Definition: simple_wml.hpp:213
unsigned short child_list_index
Definition: simple_wml.hpp:214
static map_location::direction n
static map_location::direction s