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