CppCMS
|
00001 00002 // 00003 // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> 00004 // 00005 // See accompanying file COPYING.TXT file for licensing details. 00006 // 00008 #ifndef CPPCMS_JSON_H 00009 #define CPPCMS_JSON_H 00010 00011 #include <cppcms/defs.h> 00012 #include <cppcms/string_key.h> 00013 #include <booster/copy_ptr.h> 00014 #include <booster/backtrace.h> 00015 #include <vector> 00016 #include <map> 00017 #include <string> 00018 #include <iostream> 00019 #include <limits> 00020 00021 namespace cppcms { 00025 namespace json { 00026 00027 00028 00029 00030 class value; 00031 00035 struct null {}; 00039 struct undefined {}; 00040 00041 inline bool operator==(undefined const &/*l*/,undefined const &/*r*/) {return true;} 00042 inline bool operator!=(undefined const &/*l*/,undefined const &/*r*/) {return false;} 00043 inline bool operator==(null const &/*l*/,null const &/*r*/) {return true;} 00044 inline bool operator!=(null const &/*l*/,null const &/*r*/) {return false;} 00045 00049 typedef std::vector<value> array; 00053 typedef std::map<string_key,value> object; 00054 00055 #ifdef CPPCMS_DOXYGEN_DOCS 00056 00061 template<typename T> 00062 struct traits { 00066 static T get(value const &v); 00070 static void set(value &v,T const &in); 00071 }; 00072 00073 #else 00074 00075 template<typename T> 00076 struct traits; 00077 00078 #endif 00079 00080 00084 typedef enum { 00085 is_undefined, 00086 is_null, 00087 is_boolean, 00088 is_number, 00089 is_string, 00090 is_object, 00091 is_array 00092 } json_type; 00093 00094 00095 enum { 00096 compact = 0, 00097 readable = 1 00098 }; 00099 00106 class CPPCMS_API bad_value_cast : public booster::bad_cast { 00107 public: 00108 bad_value_cast(); 00109 bad_value_cast(std::string const &s); 00110 bad_value_cast(std::string const &s,json_type actual); 00111 bad_value_cast(std::string const &s,json_type expected, json_type actual); 00112 00113 virtual ~bad_value_cast() throw(); 00114 virtual const char* what() const throw(); 00115 private: 00116 std::string msg_; 00117 }; 00118 00119 class value; 00120 00124 std::istream CPPCMS_API &operator>>(std::istream &in,value &v); 00125 00129 std::ostream CPPCMS_API &operator<<(std::ostream &out,value const &v); 00130 00134 std::ostream CPPCMS_API &operator<<(std::ostream &out,json_type); 00135 00142 class CPPCMS_API value { 00143 public: 00144 00148 json_type type() const; 00149 00153 bool is_undefined() const; 00157 bool is_null() const; 00158 00162 bool const &boolean() const; 00166 double const &number() const; 00170 std::string const &str() const; 00174 json::object const &object() const; 00178 json::array const &array() const; 00179 00183 bool &boolean(); 00187 double &number(); 00191 std::string &str(); 00195 json::object &object(); 00199 json::array &array(); 00200 00204 void undefined(); 00208 void null(); 00209 00213 void boolean(bool); 00217 void number(double ); 00221 void str(std::string const &); 00225 void object(json::object const &); 00229 void array(json::array const &); 00230 00231 00235 template<typename T> 00236 T get_value() const 00237 { 00238 return traits<T>::get(*this); 00239 } 00240 00244 template<typename T> 00245 void set_value(T const &v) 00246 { 00247 traits<T>::set(*this,v); 00248 } 00249 00257 value const &find(std::string const &path) const; 00265 value const &find(char const *path) const; 00266 00274 value const &at(std::string const &path) const; 00282 value const &at(char const *path) const; 00290 value &at(std::string const &path); 00298 value &at(char const *path); 00299 00303 void at(std::string const &path,value const &v); 00307 void at(char const *path,value const &v); 00308 00309 00313 template<typename T> 00314 value(T const &v) 00315 { 00316 set_value(v); 00317 } 00318 00324 json_type type(std::string const &path) const 00325 { 00326 return find(path).type(); 00327 } 00333 json_type type(char const *path) const 00334 { 00335 return find(path).type(); 00336 } 00337 00341 template<typename T> 00342 void set(std::string const &path,T const &v) 00343 { 00344 at(path,value(v)); 00345 } 00349 template<typename T> 00350 void set(char const *path,T const &v) 00351 { 00352 at(path,value(v)); 00353 } 00354 00359 std::string get(std::string const &path,char const *def) const 00360 { 00361 value const &v=find(path); 00362 if(v.is_undefined()) 00363 return def; 00364 try { 00365 return v.get_value<std::string>(); 00366 } 00367 catch(std::bad_cast const &e) { 00368 return def; 00369 } 00370 } 00375 std::string get(char const *path,char const *def) const 00376 { 00377 value const &v=find(path); 00378 if(v.is_undefined()) 00379 return def; 00380 try { 00381 return v.get_value<std::string>(); 00382 } 00383 catch(std::bad_cast const &e) { 00384 return def; 00385 } 00386 } 00387 00392 template<typename T> 00393 T get(std::string const &path) const 00394 { 00395 return at(path).get_value<T>(); 00396 } 00401 template<typename T> 00402 T get(char const *path) const 00403 { 00404 return at(path).get_value<T>(); 00405 } 00406 00411 template<typename T> 00412 T get(char const *path,T const &def) const 00413 { 00414 value const &v=find(path); 00415 if(v.is_undefined()) 00416 return def; 00417 try { 00418 return v.get_value<T>(); 00419 } 00420 catch(std::bad_cast const &e) { 00421 return def; 00422 } 00423 } 00428 template<typename T> 00429 T get(std::string const &path,T const &def) const 00430 { 00431 value const &v=find(path); 00432 if(v.is_undefined()) 00433 return def; 00434 try { 00435 return v.get_value<T>(); 00436 } 00437 catch(std::bad_cast const &e) { 00438 return def; 00439 } 00440 } 00441 00449 value &operator[](std::string const &name); 00450 00457 value const &operator[](std::string const &name) const; 00458 00463 value &operator[](size_t n); 00468 value const &operator[](size_t n) const; 00469 00473 std::string save(int how=compact) const; 00477 void save(std::ostream &out,int how=compact) const; 00488 bool load(std::istream &in,bool full,int *line_number=0); 00489 00493 bool operator==(value const &other) const; 00497 bool operator!=(value const &other) const; 00498 00502 value(value const &other) : 00503 d(other.d) 00504 { 00505 } 00509 value const &operator=(value const &other) 00510 { 00511 d=other.d; 00512 return *this; 00513 } 00517 value() 00518 { 00519 } 00520 00524 00525 ~value() 00526 { 00527 } 00528 00532 void swap(value &other) 00533 { 00534 d.swap(other.d); 00535 } 00536 00537 private: 00538 00539 void write(std::ostream &out,int tabs) const; 00540 void write_value(std::ostream &out,int tabs) const; 00541 00542 struct _data; 00543 struct CPPCMS_API copyable { 00544 00545 _data *operator->() { return &*d; } 00546 _data &operator*() { return *d; } 00547 _data const *operator->() const { return &*d; } 00548 _data const &operator*() const { return *d; } 00549 00550 copyable(); 00551 copyable(copyable const &r); 00552 copyable const &operator=(copyable const &r); 00553 ~copyable(); 00554 00555 void swap(copyable &other) 00556 { 00557 d.swap(other.d); 00558 } 00559 private: 00560 booster::copy_ptr<_data> d; 00561 } d; 00562 00563 friend struct copyable; 00564 }; 00565 00566 00567 00569 00570 template<typename T1,typename T2> 00571 struct traits<std::pair<T1,T2> > { 00572 static std::pair<T1,T2> get(value const &v) 00573 { 00574 if(v.object().size()!=2) 00575 throw bad_value_cast("Object with two members expected"); 00576 std::pair<T1,T2> pair(v.get_value<T1>("first"),v.get_value<T2>("second")); 00577 return pair; 00578 } 00579 static void set(value &v,std::pair<T1,T2> const &in) 00580 { 00581 v=json::object(); 00582 v.set_value("first",in.first); 00583 v.set_value("second",in.second); 00584 } 00585 }; 00586 00587 template<typename T> 00588 struct traits<std::vector<T> > { 00589 static std::vector<T> get(value const &v) 00590 { 00591 std::vector<T> result; 00592 json::array const &a=v.array(); 00593 result.resize(a.size()); 00594 for(unsigned i=0;i<a.size();i++) 00595 result[i]=a[i].get_value<T>(); 00596 return result; 00597 } 00598 static void set(value &v,std::vector<T> const &in) 00599 { 00600 v=json::array(); 00601 json::array &a=v.array(); 00602 a.resize(in.size()); 00603 for(unsigned i=0;i<in.size();i++) 00604 a[i].set_value(in[i]); 00605 } 00606 }; 00607 00608 00609 #define CPPCMS_JSON_SPECIALIZE(type,method) \ 00610 template<> \ 00611 struct traits<type> { \ 00612 static type get(value const &v) \ 00613 { \ 00614 return v.method(); \ 00615 } \ 00616 static void set(value &v,type const &in)\ 00617 { \ 00618 v.method(in); \ 00619 } \ 00620 }; 00621 00622 CPPCMS_JSON_SPECIALIZE(bool,boolean); 00623 CPPCMS_JSON_SPECIALIZE(double,number); 00624 CPPCMS_JSON_SPECIALIZE(std::string,str); 00625 CPPCMS_JSON_SPECIALIZE(json::object,object); 00626 CPPCMS_JSON_SPECIALIZE(json::array,array); 00627 00628 #undef CPPCMS_JSON_SPECIALIZE 00629 00630 #define CPPCMS_JSON_SPECIALIZE_INT(type) \ 00631 template<> \ 00632 struct traits<type> { \ 00633 static type get(value const &v) \ 00634 { \ 00635 type res=static_cast<type>(v.number()); \ 00636 if(res!=v.number()) \ 00637 throw bad_value_cast(); \ 00638 return res; \ 00639 } \ 00640 static void set(value &v,type const &in) \ 00641 { \ 00642 if(std::numeric_limits<type>::digits > \ 00643 std::numeric_limits<double>::digits \ 00644 && static_cast<double>(in)!=in) \ 00645 { \ 00646 throw bad_value_cast(); \ 00647 } \ 00648 v.number(static_cast<double>(in)); \ 00649 } \ 00650 }; 00651 00652 CPPCMS_JSON_SPECIALIZE_INT(char) 00653 CPPCMS_JSON_SPECIALIZE_INT(unsigned char) 00654 CPPCMS_JSON_SPECIALIZE_INT(signed char) 00655 CPPCMS_JSON_SPECIALIZE_INT(wchar_t) 00656 CPPCMS_JSON_SPECIALIZE_INT(short) 00657 CPPCMS_JSON_SPECIALIZE_INT(unsigned short) 00658 CPPCMS_JSON_SPECIALIZE_INT(int) 00659 CPPCMS_JSON_SPECIALIZE_INT(unsigned int) 00660 CPPCMS_JSON_SPECIALIZE_INT(long) 00661 CPPCMS_JSON_SPECIALIZE_INT(unsigned long) 00662 CPPCMS_JSON_SPECIALIZE_INT(long long) 00663 CPPCMS_JSON_SPECIALIZE_INT(unsigned long long) 00664 00665 #undef CPPCMS_JSON_SPECIALIZE_INT 00666 00667 template<> 00668 struct traits<float> { 00669 static float get(value const &v) 00670 { 00671 double r=v.number(); 00672 if( r < std::numeric_limits<float>::min() 00673 || std::numeric_limits<float>::max() < r ) 00674 { 00675 throw bad_value_cast(); 00676 } 00677 return static_cast<float>(r); 00678 } 00679 static void set(value &v,float const &in) 00680 { 00681 v.number(in); 00682 } 00683 }; 00684 00685 template<> 00686 struct traits<long double> { 00687 static long double get(value const &v) 00688 { 00689 return v.number(); 00690 } 00691 static void set(value &v,long double const &in) 00692 { 00693 if( in < std::numeric_limits<double>::min() 00694 || std::numeric_limits<double>::max() < in ) 00695 { 00696 throw bad_value_cast(); 00697 } 00698 v.number(static_cast<double>(in)); 00699 } 00700 }; 00701 00702 template<> 00703 struct traits<json::null> { 00704 static void set(value &v,json::null const &/*in*/) 00705 { 00706 v.null(); 00707 } 00708 }; 00709 00710 template<int n> 00711 struct traits<char[n]> { 00712 typedef char vtype[n]; 00713 static void set(value &v,vtype const &in) 00714 { 00715 v.str(in); 00716 } 00717 }; 00718 template<int n> 00719 struct traits<char const [n]> { 00720 typedef char const vtype[n]; 00721 static void set(value &v,vtype const &in) 00722 { 00723 v.str(in); 00724 } 00725 }; 00726 00727 00728 template<> 00729 struct traits<char const *> { 00730 static void set(value &v,char const * const &in) 00731 { 00732 v.str(in); 00733 } 00734 }; 00735 00737 00738 00739 } // json 00740 } // cppcms 00741 00742 #endif