simple_wml.hpp

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

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs