CppCMS
cppcms/json.h
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