Go to the documentation of this file.00001 #ifndef SIMPLE_WML_HPP_INCLUDED
00002 #define SIMPLE_WML_HPP_INCLUDED
00003
00004 #include <string.h>
00005
00006 #include <cstddef>
00007 #include <iosfwd>
00008 #include <map>
00009 #include <string>
00010 #include <vector>
00011
00012 #include "exceptions.hpp"
00013
00014 namespace simple_wml {
00015
00016 struct error : public game::error {
00017 error(const char* msg);
00018 };
00019
00020 class string_span
00021 {
00022 public:
00023 string_span() : str_(NULL), size_(0)
00024 {}
00025 string_span(const char* str, int size) : str_(str), size_(size)
00026 {}
00027 string_span(const char* str) : str_(str), size_(strlen(str))
00028 {}
00029
00030 bool operator==(const char* o) const {
00031 const char* i1 = str_;
00032 const char* i2 = str_ + size_;
00033 while(i1 != i2 && *o && *i1 == *o) {
00034 ++i1;
00035 ++o;
00036 }
00037
00038 return i1 == i2 && *o == 0;
00039 }
00040 bool operator!=(const char* o) const {
00041 return !operator==(o);
00042 }
00043 bool operator==(const std::string& o) const {
00044 return size_ == o.size() && memcmp(str_, o.data(), size_) == 0;
00045 }
00046 bool operator!=(const std::string& o) const {
00047 return !operator==(o);
00048 }
00049 bool operator==(const string_span& o) const {
00050 return size_ == o.size_ && memcmp(str_, o.str_, size_) == 0;
00051 }
00052 bool operator!=(const string_span& o) const {
00053 return !operator==(o);
00054 }
00055 bool operator<(const string_span& o) const {
00056 const int len = size_ < o.size_ ? size_ : o.size_;
00057 for(int n = 0; n < len; ++n) {
00058 if(str_[n] != o.str_[n]) {
00059 if(str_[n] < o.str_[n]) {
00060 return true;
00061 } else {
00062 return false;
00063 }
00064 }
00065 }
00066
00067 return size_ < o.size_;
00068 }
00069
00070 const char* begin() const { return str_; }
00071 const char* end() const { return str_ + size_; }
00072
00073 int size() const { return size_; }
00074 bool empty() const { return size_ == 0; }
00075 bool is_null() const { return str_ == NULL; }
00076
00077 bool to_bool(bool default_value=false) const;
00078 int to_int() const;
00079 std::string to_string() const;
00080
00081
00082 char* duplicate() const;
00083
00084 private:
00085 const char* str_;
00086 unsigned int size_;
00087 };
00088
00089 std::ostream& operator<<(std::ostream& o, const string_span& s);
00090
00091 class document;
00092
00093 class node
00094 {
00095 public:
00096 node(document& doc, node* parent);
00097 node(document& doc, node* parent, const char** str, int depth=0);
00098 ~node();
00099
00100 typedef std::pair<string_span, string_span> attribute;
00101 typedef std::vector<node*> child_list;
00102
00103 const string_span& operator[](const char* key) const;
00104 const string_span& attr(const char* key) const {
00105 return (*this)[key];
00106 }
00107
00108 bool has_attr(const char* key) const;
00109
00110
00111
00112
00113
00114 node& set_attr(const char* key, const char* value);
00115
00116
00117
00118
00119
00120 node& set_attr_dup(const char* key, const char* value);
00121 node& set_attr_dup(const char* key, const string_span& value);
00122
00123 node& set_attr_int(const char* key, int value);
00124
00125 node& add_child(const char* name);
00126 node& add_child_at(const char* name, size_t index);
00127 void remove_child(const char* name, size_t index);
00128 void remove_child(const string_span& name, size_t index);
00129
00130 node* child(const char* name);
00131 const node* child(const char* name) const;
00132
00133 const child_list& children(const char* name) const;
00134
00135 const string_span& first_child() const;
00136
00137 bool is_dirty() const { return output_cache_.is_null(); }
00138
00139 enum CACHE_STATUS { REFRESH_CACHE, DO_NOT_MODIFY_CACHE };
00140
00141 int output_size() const;
00142 void output(char*& buf, CACHE_STATUS status=DO_NOT_MODIFY_CACHE);
00143
00144 void copy_into(node& n) const;
00145
00146 bool no_children() const { return children_.empty(); }
00147 bool one_child() const { return children_.size() == 1 && children_.begin()->second.size() == 1; }
00148
00149 void apply_diff(const node& diff);
00150
00151 void set_doc(document* doc);
00152
00153 int nchildren() const;
00154 int nattributes_recursive() const;
00155
00156 private:
00157 node(const node&);
00158 void operator=(const node&);
00159
00160 int get_children(const string_span& name);
00161 int get_children(const char* name);
00162
00163 void set_dirty();
00164 void shift_buffers(ptrdiff_t offset);
00165
00166 document* doc_;
00167
00168 typedef std::vector<attribute> attribute_list;
00169 attribute_list attr_;
00170
00171 node* parent_;
00172
00173 typedef std::pair<string_span, child_list> child_pair;
00174 typedef std::vector<child_pair> child_map;
00175
00176 static child_map::const_iterator find_in_map(const child_map& m, const string_span& attr);
00177 static child_map::iterator find_in_map(child_map& m, const string_span& attr);
00178 child_map children_;
00179
00180
00181
00182 struct node_pos {
00183 node_pos(int child_map_index, int child_list_index)
00184 : child_map_index(static_cast<unsigned short>(child_map_index)),
00185 child_list_index(static_cast<unsigned short>(child_list_index))
00186 {}
00187 unsigned short child_map_index;
00188 unsigned short child_list_index;
00189 };
00190
00191
00192 std::vector<node_pos> ordered_children_;
00193
00194 void insert_ordered_child(int child_map_index, int child_list_index);
00195 void remove_ordered_child(int child_map_index, int child_list_index);
00196 void insert_ordered_child_list(int child_map_index);
00197 void remove_ordered_child_list(int child_map_index);
00198
00199 void check_ordered_children() const;
00200
00201 string_span output_cache_;
00202 };
00203
00204 std::string node_to_string(const node& n);
00205
00206 enum INIT_BUFFER_CONTROL { INIT_TAKE_OWNERSHIP };
00207
00208 enum INIT_STATE { INIT_COMPRESSED, INIT_STATIC };
00209
00210 class document
00211 {
00212 public:
00213 document();
00214 explicit document(char* buf, INIT_BUFFER_CONTROL control=INIT_TAKE_OWNERSHIP);
00215 document(const char* buf, INIT_STATE state);
00216 explicit document(string_span compressed_buf);
00217 ~document();
00218 const char* dup_string(const char* str);
00219 node& root() { if(!root_) { generate_root(); } return *root_; }
00220 const node& root() const { if(!root_) { const_cast<document*>(this)->generate_root(); } return *root_; }
00221
00222 const char* output();
00223 string_span output_compressed();
00224
00225 void compress();
00226
00227 document* clone();
00228
00229 const string_span& operator[](const char* key) const {
00230 return root()[key];
00231 }
00232
00233 const string_span& attr(const char* key) const {
00234 return root()[key];
00235 }
00236
00237 node* child(const char* name) {
00238 return root().child(name);
00239 }
00240
00241 const node* child(const char* name) const {
00242 return root().child(name);
00243 }
00244
00245 node& set_attr(const char* key, const char* value) {
00246 return root().set_attr(key, value);
00247 }
00248
00249 node& set_attr_dup(const char* key, const char* value) {
00250 return root().set_attr_dup(key, value);
00251 }
00252
00253 void take_ownership_of_buffer(char* buffer) {
00254 buffers_.push_back(buffer);
00255 }
00256
00257 void swap(document& o);
00258 void clear();
00259
00260 static std::string stats();
00261
00262 private:
00263 void generate_root();
00264 document(const document&);
00265 void operator=(const document&);
00266
00267 string_span compressed_buf_;
00268 const char* output_;
00269 std::vector<char*> buffers_;
00270 node* root_;
00271
00272
00273 void attach_list();
00274 void detach_list();
00275 document* prev_;
00276 document* next_;
00277 };
00278
00279 }
00280
00281 #endif