1 #ifndef SIMPLE_WML_HPP_INCLUDED
2 #define SIMPLE_WML_HPP_INCLUDED
3 
4 #include <string.h>
5 
6 #include <iosfwd>
7 #include <map>
8 #include <string>
9 #include <vector>
10 
11 namespace simple_wml {
12 
13 struct error {
14 	error(const char* msg);
15 	std::string message;
16 };
17 
18 class string_span
19 {
20 public:
string_span()21 	string_span() : str_(NULL), size_(0)
22 	{}
string_span(const char * str,int size)23 	string_span(const char* str, int size) : str_(str), size_(size)
24 	{}
string_span(const char * str)25 	string_span(const char* str) : str_(str), size_(strlen(str))
26 	{}
27 
operator ==(const char * o) const28 	bool operator==(const char* o) const {
29 		const char* i1 = str_;
30 		const char* i2 = str_ + size_;
31 		while(i1 != i2 && *o && *i1 == *o) {
32 			++i1;
33 			++o;
34 		}
35 
36 		return i1 == i2 && *o == 0;
37 	}
operator !=(const char * o) const38 	bool operator!=(const char* o) const {
39 		return !operator==(o);
40 	}
operator ==(const std::string & o) const41 	bool operator==(const std::string& o) const {
42 		return size_ == o.size() && memcmp(str_, o.data(), size_) == 0;
43 	}
operator !=(const std::string & o) const44 	bool operator!=(const std::string& o) const {
45 		return !operator==(o);
46 	}
operator ==(const string_span & o) const47 	bool operator==(const string_span& o) const {
48 		return size_ == o.size_ && memcmp(str_, o.str_, size_) == 0;
49 	}
operator !=(const string_span & o) const50 	bool operator!=(const string_span& o) const {
51 		return !operator==(o);
52 	}
operator <(const string_span & o) const53 	bool operator<(const string_span& o) const {
54 		const int len = size_ < o.size_ ? size_ : o.size_;
55 		for(int n = 0; n < len; ++n) {
56 			if(str_[n] != o.str_[n]) {
57 				if(str_[n] < o.str_[n]) {
58 					return true;
59 				} else {
60 					return false;
61 				}
62 			}
63 		}
64 
65 		return size_ < o.size_;
66 	}
67 
begin() const68 	const char* begin() const { return str_; }
end() const69 	const char* end() const { return str_ + size_; }
70 
size() const71 	int size() const { return size_; }
empty() const72 	bool empty() const { return size_ == 0; }
is_null() const73 	bool is_null() const { return str_ == NULL; }
74 
75 	bool to_bool(bool default_value=false) const;
76 	int to_int() const;
77 	std::string to_string() const;
78 
79 	//returns a duplicate of the string span in a new[] allocated buffer
80 	char* duplicate() const;
81 
82 private:
83         const char* str_;
84         unsigned int size_;
85 };
86 
87 std::ostream& operator<<(std::ostream& o, const string_span& s);
88 
89 class document;
90 
91 class node
92 {
93 public:
94 	node(document& doc, node* parent);
95 	node(document& doc, node* parent, const char** str, int depth=0);
96 	~node();
97 
98 	typedef std::pair<string_span, string_span> attribute;
99 	typedef std::vector<node*> child_list;
100 
101 	const string_span& operator[](const char* key) const;
attr(const char * key) const102 	const string_span& attr(const char* key) const {
103 		return (*this)[key];
104 	}
105 
106 	bool has_attr(const char* key) const;
107 
108 	//sets an attribute in the WML node. The node will keep a direct reference
109 	//to key and value which it will maintain for its lifetime. The caller
110 	//MUST guarantee that the key and value buffers remain valid for the
111 	//lifetime of the node.
112 	node& set_attr(const char* key, const char* value);
113 
114 	//functions which are identical to set_attr() except that the buffer
115 	//referred to by 'value' will be duplicated and the new buffer managed by
116 	//the node. The caller may destroy the value buffer as soon as the function
117 	//returns. The key buffer must remain valid for the lifetime of the node.
118 	node& set_attr_dup(const char* key, const char* value);
119 	node& set_attr_dup(const char* key, const string_span& value);
120 
121 	//sets an attribute with identical behavior to set_attr_dup, except that
122 	//the buffer referred to by 'key' will also be duplicated and managed by
123 	//the node. The caller may destroy both key and value as soon as the
124 	//call returns.
125 	node& set_attr_dup_key_and_value(const char* key, const char* value);
126 
127 	node& set_attr_int(const char* key, int value);
128 
129 	node& add_child(const char* name);
130 	node& add_child_at(const char* name, size_t index);
131 	void remove_child(const char* name, size_t index);
132 	void remove_child(const string_span& name, size_t index);
133 
134 	node* child(const char* name);
135 	const node* child(const char* name) const;
136 
137 	const child_list& children(const char* name) const;
138 
139 	const string_span& first_child() const;
140 
is_dirty() const141 	bool is_dirty() const { return output_cache_.is_null(); }
142 
143 	int output_size() const;
144 	void output(char*& buf);
145 	const char* output();
146 
147 	void copy_into(node& n) const;
148 
no_children() const149 	bool no_children() const { return children_.empty(); }
one_child() const150 	bool one_child() const { return children_.size() == 1 && children_.begin()->second.size() == 1; }
151 
152 	void apply_diff(const node& diff);
153 
154 	void set_doc(document* doc);
155 
156 	int nchildren() const;
157 	int nattributes_recursive() const;
158 
159 private:
160 	node(const node&);
161 	void operator=(const node&);
162 
163 	int get_children(const string_span& name);
164 	int get_children(const char* name);
165 
166 	void set_dirty();
167 	void shift_buffers(ptrdiff_t offset);
168 
169 	document* doc_;
170 
171 	typedef std::vector<attribute> attribute_list;
172 	attribute_list attr_;
173 
174 	node* parent_;
175 
176 	typedef std::pair<string_span, child_list> child_pair;
177 	typedef std::vector<child_pair> child_map;
178 
179 	static child_map::const_iterator find_in_map(const child_map& m, const string_span& attr);
180 	static child_map::iterator find_in_map(child_map& m, const string_span& attr);
181 	child_map children_;
182 
183 	//a node position indicates the index into the child map where the node
184 	//is, and then the index into the child list within where the node is.
185 	struct node_pos {
node_possimple_wml::node::node_pos186 		node_pos(int child_map_index, int child_list_index)
187 		  : child_map_index(child_map_index), child_list_index(child_list_index)
188 		{}
189 		unsigned short child_map_index;
190 		unsigned short child_list_index;
191 	};
192 
193 	//a list of all the children in order.
194 	std::vector<node_pos> ordered_children_;
195 
196 	void insert_ordered_child(int child_map_index, int child_list_index);
197 	void remove_ordered_child(int child_map_index, int child_list_index);
198 	void insert_ordered_child_list(int child_map_index);
199 	void remove_ordered_child_list(int child_map_index);
200 
201 	void check_ordered_children() const;
202 
203 	string_span output_cache_;
204 };
205 
206 enum INIT_BUFFER_CONTROL { INIT_TAKE_OWNERSHIP };
207 
208 enum INIT_STATE { INIT_COMPRESSED, INIT_STATIC };
209 
210 class document
211 {
212 public:
213 	document();
214 	explicit document(char* buf, INIT_BUFFER_CONTROL control=INIT_TAKE_OWNERSHIP);
215 	document(const char* buf, INIT_STATE state);
216 	explicit document(string_span compressed_buf);
217 	~document();
218 	const char* dup_string(const char* str);
root()219 	node& root() { if(!root_) { generate_root(); } return *root_; }
root() const220 	const node& root() const { if(!root_) { const_cast<document*>(this)->generate_root(); } return *root_; }
221 
222 	const char* output();
223 	string_span output_compressed();
224 
225 	void compress();
226 
227 	document* clone();
228 
operator [](const char * key) const229 	const string_span& operator[](const char* key) const {
230 		return root()[key];
231 	}
232 
attr(const char * key) const233 	const string_span& attr(const char* key) const {
234 		return root()[key];
235 	}
236 
child(const char * name)237 	node* child(const char* name) {
238 		return root().child(name);
239 	}
240 
child(const char * name) const241 	const node* child(const char* name) const {
242 		return root().child(name);
243 	}
244 
set_attr(const char * key,const char * value)245 	node& set_attr(const char* key, const char* value) {
246 		return root().set_attr(key, value);
247 	}
248 
set_attr_dup(const char * key,const char * value)249 	node& set_attr_dup(const char* key, const char* value) {
250 		return root().set_attr_dup(key, value);
251 	}
252 
take_ownership_of_buffer(char * buffer)253 	void take_ownership_of_buffer(char* buffer) {
254 		buffers_.push_back(buffer);
255 	}
256 
257 	void swap(document& o);
258 	void clear();
259 
260 	static std::string stats();
261 
262 private:
263 	void generate_root();
264 	document(const document&);
265 	void operator=(const document&);
266 
267 	string_span compressed_buf_;
268 	const char* output_;
269 	std::vector<char*> buffers_;
270 	node* root_;
271 
272 	//linked list of documents for accounting purposes
273 	void attach_list();
274 	void detach_list();
275 	document* prev_;
276 	document* next_;
277 };
278 
279 }
280 
281 #endif
282