server/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 <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     //returns a duplicate of the string span in a new[] allocated buffer
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     //sets an attribute in the WML node. The node will keep a direct reference
00111     //to key and value which it will maintain for its lifetime. The caller
00112     //MUST guarantee that the key and value buffers remain valid for the
00113     //lifetime of the node.
00114     node& set_attr(const char* key, const char* value);
00115 
00116     //functions which are identical to set_attr() except that the buffer
00117     //referred to by 'value' will be duplicated and the new buffer managed by
00118     //the node. The caller may destroy the value buffer as soon as the function
00119     //returns. The key buffer must remain valid for the lifetime of the node.
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     //a node position indicates the index into the child map where the node
00181     //is, and then the index into the child list within where the node is.
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     //a list of all the children in order.
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     //linked list of documents for accounting purposes
00273     void attach_list();
00274     void detach_list();
00275     document* prev_;
00276     document* next_;
00277 };
00278 
00279 }
00280 
00281 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:10 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs