The Battle for Wesnoth  1.19.0-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  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 
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;
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);
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 {
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 }
void take_ownership_of_buffer(char *buffer)
Definition: simple_wml.hpp:281
const char * output()
const node & root() const
Definition: simple_wml.hpp:244
node & set_attr_dup(const char *key, const char *value)
Definition: simple_wml.hpp:277
std::unique_ptr< document > clone()
static std::string stats()
const node * child(const char *name) const
Definition: simple_wml.hpp:265
document & operator=(const document &)=delete
document(const document &)=delete
static std::size_t document_size_limit
Definition: simple_wml.hpp:290
const string_span & operator[](const char *key) const
Definition: simple_wml.hpp:253
node * child(const char *name)
Definition: simple_wml.hpp:261
const char * output_
Definition: simple_wml.hpp:297
const node::child_list & children(const char *name) const
Definition: simple_wml.hpp:269
void swap(document &o)
std::vector< char * > buffers_
Definition: simple_wml.hpp:298
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:257
string_span compressed_buf_
Definition: simple_wml.hpp:296
node & set_attr(const char *key, const char *value)
Definition: simple_wml.hpp:273
const string_span & attr(const char *key) const
Definition: simple_wml.hpp:128
int output_size() const
Definition: simple_wml.cpp:698
void set_doc(document *doc)
Definition: simple_wml.cpp:896
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:907
node(const node &)=delete
bool no_children() const
Definition: simple_wml.hpp:170
bool is_dirty() const
Definition: simple_wml.hpp:161
node(document &doc, node *parent)
Definition: simple_wml.cpp:208
int get_children(const string_span &name)
Definition: simple_wml.cpp:652
document * doc_
Definition: simple_wml.hpp:190
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:635
void apply_diff(const node &diff)
Definition: simple_wml.cpp:828
attribute_list attr_
Definition: simple_wml.hpp:193
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:198
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:920
std::vector< node_pos > ordered_children_
Definition: simple_wml.hpp:216
std::vector< attribute > attribute_list
Definition: simple_wml.hpp:192
const string_span & first_child() const
Definition: simple_wml.cpp:688
child_map children_
Definition: simple_wml.hpp:202
void output(char *&buf, CACHE_STATUS status=DO_NOT_MODIFY_CACHE)
Definition: simple_wml.cpp:744
node & add_child(const char *name)
Definition: simple_wml.cpp:466
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:225
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:807
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:724
std::pair< string_span, child_list > child_pair
Definition: simple_wml.hpp:197
bool one_child() const
Definition: simple_wml.hpp:171
static child_map::const_iterator find_in_map(const child_map &m, const string_span &attr)
Definition: simple_wml.cpp:664
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:795
@ INIT_TAKE_OWNERSHIP
Definition: simple_wml.hpp:230
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: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:207
unsigned short child_map_index
Definition: simple_wml.hpp:211
unsigned short child_list_index
Definition: simple_wml.hpp:212
static map_location::DIRECTION n
static map_location::DIRECTION s