Mirror reflection library 0.5.13

mirror/utils/mijson.hpp

Go to the documentation of this file.
00001 
00010 #ifndef MIRROR_UTILS_MIJSON_1011291729_HPP
00011 #define MIRROR_UTILS_MIJSON_1011291729_HPP
00012 
00013 #include <mirror/config.hpp>
00014 #include <mirror/utils/string/unescape.hpp>
00015 
00016 #include <utility>
00017 #include <cctype>
00018 #include <list>
00019 #include <map>
00020 
00021 
00022 MIRROR_NAMESPACE_BEGIN
00023 
00024 template <typename Iterator>
00025 class mijson_fragment;
00026 
00027 template <typename Iterator>
00028 class mijson_element
00029 {
00030 public:
00031     enum class element_type
00032     {
00033         json_unknown,
00034         json_string,
00035         json_number,
00036         json_object,
00037         json_array,
00038         json_keyword
00039     };
00040 
00041     static const char* element_type_name(element_type val)
00042     {
00043         switch(val)
00044         {
00045             case element_type::json_string: return "string";
00046             case element_type::json_number: return "number";
00047             case element_type::json_object: return "object";
00048             case element_type::json_array:  return "array";
00049             case element_type::json_keyword:return "keyword";
00050             default:;
00051         }
00052         return "unknown";
00053     }
00054 
00055     typedef Iterator iterator;
00056     typedef std::list<mijson_element> element_list;
00057 private:
00058     element_type elem_type;
00059 
00060     Iterator elem_name_begin;
00061     Iterator elem_name_end;
00062 
00063     Iterator elem_value_begin;
00064     Iterator elem_value_end;
00065 
00066     element_list elem_elements;
00067     element_list elem_members;
00068 
00069     std::map<
00070         std::string,
00071         typename element_list::const_iterator
00072     > elem_member_map;
00073 
00074     void init_elems(element_list& elems)
00075     {
00076         if(elem_type == element_type::json_array)
00077             std::swap(elem_elements, elems);
00078         else if(elem_type == element_type::json_object)
00079             std::swap(elem_members, elems);
00080         typename element_list::const_iterator
00081             i = elem_members.begin(),
00082             e = elem_members.end();
00083         while(i != e)
00084         {
00085             elem_member_map[i->name()] = i;
00086             ++i;
00087         }
00088     }
00089 protected:
00090     friend class mijson_fragment<Iterator>;
00091 
00092     mijson_element(const mijson_element&) = delete;
00093 
00094     mijson_element(
00095         element_type _type,
00096         Iterator _value_begin,
00097         Iterator _value_end,
00098         element_list& elems
00099     ): elem_type(_type)
00100      , elem_name_begin(Iterator())
00101      , elem_name_end(Iterator())
00102      , elem_value_begin(_value_begin)
00103      , elem_value_end(_value_end)
00104     {
00105         init_elems(elems);
00106     }
00107 
00108     mijson_element(
00109         element_type _type,
00110         Iterator _name_begin,
00111         Iterator _name_end,
00112         Iterator _value_begin,
00113         Iterator _value_end,
00114         element_list& elems
00115     ): elem_type(_type)
00116      , elem_name_begin(_name_begin)
00117      , elem_name_end(_name_end)
00118      , elem_value_begin(_value_begin)
00119      , elem_value_end(_value_end)
00120     {
00121         init_elems(elems);
00122     }
00123 
00124 public:
00125     mijson_element(mijson_element&& src)
00126      : elem_type(src.elem_type)
00127      , elem_name_begin(std::move(src.elem_name_begin))
00128      , elem_name_end(std::move(src.elem_name_end))
00129      , elem_value_begin(std::move(src.elem_value_begin))
00130      , elem_value_end(std::move(src.elem_value_end))
00131      , elem_elements(std::move(src.elem_elements))
00132      , elem_members(std::move(src.elem_members))
00133      , elem_member_map(std::move(src.elem_member_map))
00134     { }
00135 
00136     element_type type(void) const
00137     {
00138         return elem_type;
00139     }
00140 
00141     const char* type_name(void) const
00142     {
00143         return element_type_name(type());
00144     }
00145 
00146     bool is_leaf(void) const
00147     {
00148         return  (elem_type == element_type::json_string) ||
00149             (elem_type == element_type::json_number) ||
00150             (elem_type == element_type::json_keyword);
00151     }
00152 
00153     bool is_node(void) const
00154     {
00155         return  (elem_type == element_type::json_object) ||
00156             (elem_type == element_type::json_array);
00157     }
00158 
00159     bool has_name(void) const
00160     {
00161         return elem_name_begin != elem_name_end;
00162     }
00163 
00164     Iterator name_begin(void) const
00165     {
00166         return elem_name_begin;
00167     }
00168 
00169     Iterator name_end(void) const
00170     {
00171         return elem_name_end;
00172     }
00173 
00174     std::string name(void) const
00175     {
00176         return aux::unescape(name_begin(), name_end());
00177     }
00178 
00179     bool has_value(void) const
00180     {
00181         return elem_value_begin != elem_value_end;
00182     }
00183 
00184     Iterator value_begin(void) const
00185     {
00186         return elem_value_begin;
00187     }
00188 
00189     Iterator value_end(void) const
00190     {
00191         return elem_value_end;
00192     }
00193 
00194     std::string value(void) const
00195     {
00196         if(elem_type == element_type::json_string)
00197             return aux::unescape(value_begin(), value_end());
00198         else return std::string(value_begin(), value_end());
00199     }
00200 
00201     const element_list& elements(void) const
00202     {
00203         return elem_elements;
00204     }
00205 
00206     const element_list& members(void) const
00207     {
00208         return elem_members;
00209     }
00210 
00211     const mijson_element& member(const std::string& name) const
00212     {
00213         auto p = elem_member_map.find(name);
00214         if(p == elem_member_map.end())
00215             throw std::runtime_error("Element "+name+" not found");
00216         return *(p->second);
00217     }
00218 };
00219 
00220 template <typename Iterator>
00221 class mijson_fragment
00222  : public mijson_element<Iterator>
00223 {
00224 private:
00225     typedef mijson_element<Iterator> element;
00226     typedef typename element::element_list element_list;
00227 
00228     static bool is_quasi_space(char c)
00229     {
00230         return std::isspace(c) ||
00231             (c == '"') ||
00232             (c == '\'');
00233     }
00234 
00235     static bool is_trail_sep(char c)
00236     {
00237         return std::isspace(c) ||
00238             (c == ',') ||
00239             (c == '}') ||
00240             (c == ']');
00241     }
00242 
00243     static void skip_space(Iterator& cur, Iterator end)
00244     {
00245         while(cur != end)
00246             if(std::isspace(*cur)) ++cur;
00247             else break;
00248     }
00249 
00250     static void skip_trail_space(Iterator& cur, Iterator end)
00251     {
00252         if(cur != end)
00253         {
00254             if(is_quasi_space(*cur)) ++cur;
00255             skip_space(cur, end);
00256         }
00257     }
00258 
00259     static bool parse_string(Iterator& begin, Iterator& end)
00260     {
00261         if(begin == end) return false;
00262         // current char iterator
00263         Iterator cur = begin;
00264         // the possible quotation mark
00265         char quot = *cur;
00266         // if it is not a quotmark nor an apostrophe quit
00267         if(quot != '\'' && quot != '"') return false;
00268         else ++cur;
00269         // remember the begin of the potential literal
00270         Iterator lit_begin = cur;
00271         bool escape = false;
00272         // go through the input
00273         while(cur != end)
00274         {
00275             // if this character was not escaped and it is
00276             // the quotation mark that started the string
00277             if(*cur == quot && !escape)
00278             {
00279                 // return the iterators marking the literal
00280                 begin = lit_begin;
00281                 end = cur;
00282                 return true;
00283             }
00284             // check if the next character is escaped
00285             escape = (*cur == '\\' && !escape);
00286             ++cur;
00287         }
00288         return false;
00289     }
00290 
00291     static bool parse_number(Iterator& begin, Iterator& end)
00292     {
00293         if(begin == end) return false;
00294         // current char iterator
00295         Iterator cur = begin;
00296         // skip the optional minus sign
00297         if(*cur == '-') ++cur;
00298         if(cur != end)
00299         {
00300             if(!std::isdigit(*cur))
00301                 return false;
00302         }
00303         else return false;
00304         // the first sequence of digits
00305         while(cur != end)
00306         {
00307             if(std::isdigit(*cur)) ++cur;
00308             else if(*cur == '.') break;
00309             else if(*cur == 'e') break;
00310             else if(*cur == 'E') break;
00311             else if(is_trail_sep(*cur))
00312             {
00313                 end = cur;
00314                 return true;
00315             }
00316             else return false;
00317         }
00318         if(cur == end) return true;
00319         else if(*cur == '.')
00320         {
00321             ++cur;
00322             while(cur != end)
00323             {
00324                 if(std::isdigit(*cur)) ++cur;
00325                 else if(*cur == 'e') break;
00326                 else if(*cur == 'E') break;
00327                 else if(is_trail_sep(*cur))
00328                 {
00329                     end = cur;
00330                     return true;
00331                 }
00332                 else return false;
00333             }
00334         }
00335         if(cur == end) return true;
00336         else if(*cur == 'e' || *cur == 'E')
00337         {
00338             ++cur;
00339             if(cur == end) return false;
00340             else if(*cur == '+' || *cur == '-') ++cur;
00341             if(cur == end) return false;
00342             else while(cur != end)
00343             {
00344                 if(std::isdigit(*cur)) ++cur;
00345                 else if(is_trail_sep(*cur)) break;
00346                 else return false;
00347             }
00348         }
00349         end = cur;
00350         return true;
00351     }
00352 
00353     static bool parse_keyword(Iterator& begin, Iterator& end)
00354     {
00355         if(begin == end) return false;
00356         Iterator cur = begin;
00357         if(*cur == 'f' || *cur == 't' || *cur == 'n') ++cur;
00358         else return false;
00359         if(*cur == 'a' || *cur == 'r' || *cur == 'u') ++cur;
00360         else return false;
00361         if(*cur == 'l' || *cur == 'u' || *cur == 'l') ++cur;
00362         else return false;
00363         if(*cur == 's' || *cur == 'e' || *cur == 'l') ++cur;
00364         else return false;
00365         if(*cur == 'e') ++cur;
00366         if(is_trail_sep(*cur))
00367         {
00368             end = cur;
00369             return true;
00370         }
00371         return false;
00372     }
00373 
00374     static bool parse_range(
00375         Iterator& begin,
00376         Iterator& end,
00377         element_list& elements,
00378         char lt,
00379         char rt
00380     )
00381     {
00382         if(begin == end) return false;
00383         Iterator cur = begin;
00384         if(*cur != lt) return false;
00385         else ++cur;
00386         skip_space(cur, end);
00387         if(cur == end) return false;
00388         if(*cur != rt)
00389         {
00390             while(cur != end)
00391             {
00392                 elements.push_back(std::move(parse(cur, end)));
00393                 skip_trail_space(cur, end);
00394                 if(*cur == rt)
00395                 {
00396                     ++cur;
00397                     break;
00398                 }
00399                 if(*cur != ',') return false;
00400                 skip_trail_space(++cur, end);
00401             }
00402         }
00403         else ++cur;
00404         skip_trail_space(cur, end);
00405         end = cur;
00406         return true;
00407     }
00408 
00409     static element parse(Iterator& cur, Iterator end)
00410     {
00411         skip_space(cur, end);
00412         Iterator i = cur, e = end;
00413         bool parsed_string = parse_string(i, e);
00414         element_list elements;
00415         // if we parsed a string
00416         if(parsed_string)
00417         {
00418             cur = e;
00419             skip_trail_space(cur, end);
00420             // and that's all
00421             if((cur == end) || is_trail_sep(*cur))
00422             {
00423                 // return the element
00424                 return element(
00425                     element::element_type::json_string,
00426                     i, e, elements
00427                 );
00428             }
00429             // if there is the separator, skip it
00430             else if(*cur == ':')
00431             {
00432                 ++cur;
00433                 skip_space(cur, end);
00434             }
00435         }
00436         typename element::element_type type =
00437             element::element_type::json_unknown;
00438         Iterator
00439             j = parsed_string ? cur : i,
00440             f = parsed_string ? end : e;
00441         if(parse_string(j, f))
00442             type = element::element_type::json_string;
00443         else if(parse_number(j, f))
00444             type = element::element_type::json_number;
00445         else if(parse_keyword(j, f))
00446             type = element::element_type::json_keyword;
00447         else if(parse_range(j, f, elements, '[', ']'))
00448             type = element::element_type::json_array;
00449         else if(parse_range(j, f, elements, '{', '}'))
00450             type = element::element_type::json_object;
00451         else throw std::runtime_error("Parse error");
00452         cur = f;
00453         if(parsed_string) return element(type, i, e, j, f, elements);
00454         else return element(type, i, e, elements);
00455     }
00456 public:
00457     mijson_fragment(
00458         Iterator input_begin,
00459         Iterator input_end
00460     ): mijson_element<Iterator>(std::move(parse(input_begin, input_end)))
00461     { }
00462 };
00463 
00464 MIRROR_NAMESPACE_END
00465 
00466 #endif //include guard
00467 

Copyright © 2006-2011 Matus Chochlik, University of Zilina, Zilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Fri Dec 16 2011 by Doxygen (version 1.7.3).
Important note: Although the 'boostified' version of Mirror uses the Boost C++ libraries Coding Guidelines and is implemented inside of the boost namespace, it IS NOT an officially reviewed and accepted Boost library. Mirror is being developed with the intention to be submitted for review for inclusion to the Boost C++ libraries.