Mirror reflection library 0.5.13
|
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