00001
00002 #ifndef INCLUDED_plistPrimitives_h_
00003 #define INCLUDED_plistPrimitives_h_
00004
00005 #include "plistBase.h"
00006
00007
00008
00009 extern "C" {
00010 xmlNode* xmlAddPrevSibling(xmlNode* node, xmlNode* sibling);
00011 xmlNode* xmlNewText(const xmlChar* s);
00012 xmlNode* xmlNewComment(const xmlChar* s);
00013 xmlNode* xmlAddChild(xmlNode * parent, xmlNode* child);
00014 xmlNode* xmlNewChild(xmlNode* parent, xmlNs* ns, const xmlChar * name, const xmlChar * content);
00015 int xmlStrEqual(const xmlChar* a, const xmlChar* b);
00016 xmlChar* xmlNodeGetContent(xmlNode* node);
00017 void xmlNodeSetContent(xmlNode* node, const xmlChar* content);
00018 xmlAttr* xmlHasProperty(xmlNode* node, const xmlChar* name);
00019 xmlChar* xmlGetProperty(xmlNode* node, const xmlChar* name);
00020 long xmlGetLineNo(xmlNode* node);
00021 extern void (*xmlFree)(void* ptr);
00022 void xmlNodeSetName(xmlNode* node, const xmlChar* name);
00023 void xmlFreeNode(xmlNode* node);
00024 void xmlUnlinkNode(xmlNode* node);
00025 }
00026
00027 namespace plist {
00028
00029
00030
00031
00032
00033
00034 template<typename T>
00035 class Primitive : public PrimitiveBase {
00036 public:
00037
00038 Primitive() : ObjectBase(), val() {}
00039
00040 Primitive(const T& v) : ObjectBase(), val(v) {}
00041
00042 Primitive& operator=(const T& v) { val=v; fireValueChanged(); return *this; }
00043
00044 Primitive& operator+=(const T& v) { val+=v; fireValueChanged(); return *this; }
00045 Primitive& operator-=(const T& v) { val-=v; fireValueChanged(); return *this; }
00046 Primitive& operator*=(const T& v) { val*=v; fireValueChanged(); return *this; }
00047 Primitive& operator/=(const T& v) { val/=v; fireValueChanged(); return *this; }
00048
00049
00050 const T& operator*() const { return val; }
00051
00052 const T* operator->() const { return &val; }
00053
00054
00055 operator T() const { return val; }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 PLIST_CLONE_DEF(Primitive<T>,new Primitive<T>(val));
00077
00078 protected:
00079 T val;
00080 };
00081
00082 PLIST_CLONE_IMPT(class T,Primitive<T>,new Primitive<T>(val));
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 template<>
00093 class Primitive<bool> : public PrimitiveBase {
00094 public:
00095 Primitive() : PrimitiveBase(), val() {}
00096 Primitive(const bool& v) : PrimitiveBase(), val(v) {}
00097 Primitive& operator=(const bool& v) { val=v; fireValueChanged(); return *this; }
00098
00099 const bool& operator*() const { return val; }
00100
00101 const bool* operator->() const { return &val; }
00102 operator bool() const { return val; }
00103
00104 void loadXML(xmlNode* node);
00105 void saveXML(xmlNode* node) const;
00106 void set(const std::string& str);
00107 std::string get() const {
00108 return val?"true":"false";
00109 }
00110
00111 PLIST_CLONE_DEF(Primitive<bool>,new Primitive<bool>(val));
00112
00113 protected:
00114 bool val;
00115 };
00116
00117
00118
00119
00120
00121
00122 template<>
00123 class Primitive<char> : public PrimitiveBase {
00124 public:
00125 Primitive() : PrimitiveBase(), val(), numeric(false) {}
00126 Primitive(const char& v, bool isNum=false) : PrimitiveBase(), val(v), numeric(isNum) {}
00127 Primitive& operator=(const char& v) { val=v; fireValueChanged(); return *this; }
00128 Primitive& operator+=(const char& v) { val+=v; fireValueChanged(); return *this; }
00129 Primitive& operator-=(const char& v) { val-=v; fireValueChanged(); return *this; }
00130 Primitive& operator*=(const char& v) { val*=v; fireValueChanged(); return *this; }
00131 Primitive& operator/=(const char& v) { val/=v; fireValueChanged(); return *this; }
00132
00133 const char& operator*() const { return val; }
00134
00135 const char* operator->() const { return &val; }
00136 operator char() const { return val; }
00137
00138 void setNumeric(bool isNum) { numeric=isNum; }
00139 bool getNumeric() const { return numeric; }
00140
00141 void loadXML(xmlNode* node);
00142 void saveXML(xmlNode* node) const;
00143 void set(const std::string& str);
00144 std::string get() const {
00145 if(numeric) {
00146 std::stringstream sstr;
00147 sstr << (int)val;
00148 return sstr.str();
00149 } else
00150 return std::string(1,val);
00151 }
00152
00153 PLIST_CLONE_DEF(Primitive<char>,new Primitive<char>(val));
00154
00155 protected:
00156 char val;
00157 bool numeric;
00158 };
00159
00160
00161
00162
00163 template<>
00164 class Primitive<unsigned char> : public PrimitiveBase {
00165 public:
00166 Primitive() : PrimitiveBase(), val(), numeric(false) {}
00167 Primitive(const unsigned char& v, bool isNum=false) : PrimitiveBase(), val(v), numeric(isNum) {}
00168 Primitive& operator=(const unsigned char& v) { val=v; fireValueChanged(); return *this; }
00169 Primitive& operator+=(const unsigned char& v) { val+=v; fireValueChanged(); return *this; }
00170 Primitive& operator-=(const unsigned char& v) { val-=v; fireValueChanged(); return *this; }
00171 Primitive& operator*=(const unsigned char& v) { val*=v; fireValueChanged(); return *this; }
00172 Primitive& operator/=(const unsigned char& v) { val/=v; fireValueChanged(); return *this; }
00173
00174 const unsigned char& operator*() const { return val; }
00175
00176 const unsigned char* operator->() const { return &val; }
00177 operator unsigned char() const { return val; }
00178
00179 void setNumeric(bool isNum) { numeric=isNum; }
00180 bool getNumeric() const { return numeric; }
00181
00182 void loadXML(xmlNode* node);
00183 void saveXML(xmlNode* node) const;
00184 void set(const std::string& str);
00185 std::string get() const {
00186 if(numeric) {
00187 std::stringstream sstr;
00188 sstr << (int)val;
00189 return sstr.str();
00190 } else
00191 return std::string(1,val);
00192 }
00193
00194 PLIST_CLONE_DEF(Primitive<unsigned char>,new Primitive<unsigned char>(val));
00195
00196 protected:
00197 unsigned char val;
00198 bool numeric;
00199 };
00200
00201
00202
00203
00204 #define PLIST_OBJECT_SPECIALIZATION(T,PRIM) \
00205 template<> \
00206 class Primitive<T> : public PrimitiveBase { \
00207 public: \
00208 \
00209 Primitive() : PrimitiveBase(), val() {} \
00210 \
00211 Primitive(const T& v) : PrimitiveBase(), val(v) {} \
00212 \
00213 Primitive& operator=(const T& v) { val=v; fireValueChanged(); return *this; } \
00214 Primitive& operator+=(const T& v) { val+=v; fireValueChanged(); return *this; } \
00215 Primitive& operator-=(const T& v) { val-=v; fireValueChanged(); return *this; } \
00216 Primitive& operator*=(const T& v) { val*=v; fireValueChanged(); return *this; } \
00217 Primitive& operator/=(const T& v) { val/=v; fireValueChanged(); return *this; } \
00218 \
00219 const T& operator*() const { return val; } \
00220 \
00221 const T* operator->() const { return &val; } \
00222 \
00223 operator T() const { return val; } \
00224 \
00225 void loadXML(xmlNode* node); \
00226 \
00227 void saveXML(xmlNode* node) const; \
00228 void set(const std::string& str); \
00229 std::string get() const { \
00230 std::stringstream sstr; \
00231 sstr <<std::setprecision(64)<< val; \
00232 return sstr.str(); \
00233 } \
00234 PLIST_CLONE_DEF(Primitive<T>,new Primitive<T>(val)); \
00235 protected: \
00236 \
00237 T val; \
00238 }
00239
00240 PLIST_OBJECT_SPECIALIZATION(short,"integer");
00241 PLIST_OBJECT_SPECIALIZATION(unsigned short,"integer");
00242 PLIST_OBJECT_SPECIALIZATION(int,"integer");
00243 PLIST_OBJECT_SPECIALIZATION(unsigned int,"integer");
00244 PLIST_OBJECT_SPECIALIZATION(long,"integer");
00245 PLIST_OBJECT_SPECIALIZATION(unsigned long,"integer");
00246 PLIST_OBJECT_SPECIALIZATION(long long,"integer");
00247 PLIST_OBJECT_SPECIALIZATION(unsigned long long,"integer");
00248 PLIST_OBJECT_SPECIALIZATION(float,"real");
00249 PLIST_OBJECT_SPECIALIZATION(double,"real");
00250
00251 #undef PLIST_OBJECT_SPECIALIZATION
00252
00253
00254
00255
00256 template<>
00257 class Primitive<std::string> : public PrimitiveBase, public std::string {
00258 public:
00259 Primitive() : PrimitiveBase(), std::string() {}
00260 Primitive(const std::string& v) : PrimitiveBase(), std::string(v) {}
00261 Primitive(const std::string& v, size_type off, size_type count=npos) : PrimitiveBase(), std::string(v,off,count) {}
00262 Primitive(const char* v, size_type count) : PrimitiveBase(), std::string(v,count) {}
00263 Primitive(const char* v) : PrimitiveBase(), std::string(v) {}
00264 Primitive(size_type count, char v) : PrimitiveBase(), std::string(count,v) {}
00265 Primitive& operator=(const std::string& v) { std::string::operator=(v); fireValueChanged(); return *this; }
00266 Primitive& operator=(const char* v) { std::string::operator=(v); fireValueChanged(); return *this; }
00267 Primitive& operator=(char v) { std::string::operator=(v); fireValueChanged(); return *this; }
00268
00269 const std::string& operator*() const { return *this; }
00270
00271 const std::string* operator->() const { return this; }
00272
00273
00274 void loadXML(xmlNode* node);
00275 void saveXML(xmlNode* node) const;
00276 void set(const std::string& str) { operator=(str); }
00277 std::string get() const { return *this; }
00278
00279 PLIST_CLONE_DEF(Primitive<std::string>,new Primitive<std::string>(get()));
00280 };
00281
00282
00283
00284
00285
00286
00287
00288 template<typename T>
00289 class NamedEnumeration : public PrimitiveBase {
00290 public:
00291 NamedEnumeration() : PrimitiveBase(), val(), names(NULL), max(0) {}
00292 NamedEnumeration(const NamedEnumeration& ne) : PrimitiveBase(ne), val(ne.val), names(ne.names), max(ne.max) {}
00293 NamedEnumeration(const T& v, const char * const* enumnames, unsigned int maxval) : PrimitiveBase(), val(v), names(enumnames), max(maxval) {}
00294 NamedEnumeration(const T& v) : PrimitiveBase(), val(v), names(NULL), max(0) {}
00295 NamedEnumeration& operator=(const T& v) { val=v; fireValueChanged(); return *this; }
00296 NamedEnumeration& operator=(const std::string& v) { set(v); return *this; }
00297 NamedEnumeration& operator=(const NamedEnumeration<T>& ne) { val=ne.val; names=ne.names; max=ne.max; return PrimitiveBase::operator=(ne); }
00298
00299 const T& operator*() const { return val; }
00300 operator T() const { return val; }
00301 void setNames(const char * const* enumnames, unsigned int maxval) { names=enumnames; max=maxval; }
00302 const char* const* getNames() const { return names; }
00303 const char* getName(unsigned int i) const { return names[i]; }
00304 unsigned int getMax() const { return max; }
00305
00306
00307 void loadXML(xmlNode* node) {
00308 if(node==NULL)
00309 return;
00310 if(xNodeHasName(node,"true") || xNodeHasName(node,"false")) {
00311 std::string name=(const char*)xNodeGetName(node);
00312 unsigned int i=findName(name.c_str());
00313 if(i==-1U)
00314 throw bad_format(node,("Error: plist NamedEnumeration cannot be '"+name+"'").c_str());
00315 val=static_cast<T>(i);
00316 std::cerr << "Warning: plist NamedEnumeration should use <string>" << name << "</string>, not <" << name << "/>" << std::endl;
00317 } else if(xNodeHasName(node,"integer") || xNodeHasName(node,"real") || xNodeHasName(node,"string")) {
00318 xmlChar * cont=xmlNodeGetContent(node);
00319 try {
00320 set((char*)cont);
00321 } catch(const bad_format& err) {
00322 xmlFree(cont);
00323 throw bad_format(node,err.what());
00324 } catch(...) {
00325 xmlFree(cont);
00326 throw;
00327 }
00328 xmlFree(cont);
00329 } else
00330 throw bad_format(node,"Error: plist NamedEnumeration must be numeric or valid string");
00331 }
00332
00333 void saveXML(xmlNode* node) const {
00334 if(node==NULL)
00335 return;
00336 if(names!=NULL && names[val]!=NULL && val>0 && (unsigned int)val<max) {
00337 xmlNodeSetName(node,(const xmlChar*)"string");
00338 } else {
00339 xmlNodeSetName(node,(const xmlChar*)"integer");
00340 }
00341 xmlNodeSetContent(node,(const xmlChar*)get().c_str());
00342 }
00343 void set(const std::string& str) {
00344 unsigned int i=findName(str.c_str());
00345 if(i==-1U) {
00346 if(sscanf(str.c_str(),"%d",&i)==0)
00347 throw bad_format(NULL,"Error: plist NamedEnumeration must be numeric or valid string");
00348 }
00349 val=static_cast<T>(i);
00350 fireValueChanged();
00351 }
00352 std::string get() const {
00353 if(names!=NULL && names[val]!=NULL && val>=0 && (unsigned int)val<max)
00354 return names[val];
00355 std::stringstream str;
00356 str << val;
00357 return str.str();
00358 }
00359
00360 PLIST_CLONE_DEF(NamedEnumeration<T>,new NamedEnumeration<T>(*this));
00361
00362 protected:
00363
00364 unsigned int findName(const char* name) {
00365 if(name==NULL || names==NULL)
00366 return -1U;
00367
00368 for(unsigned int i=0; i<max; i++)
00369 if(names[i] && strcmp(name,names[i])==0)
00370 return i;
00371
00372 for(unsigned int i=0; i<max; i++)
00373 if(names[i] && strcasecmp(name,names[i])==0)
00374 return i;
00375 return -1U;
00376 }
00377 T val;
00378 const char * const* names;
00379 unsigned int max;
00380 };
00381
00382 PLIST_CLONE_IMPT(class T,NamedEnumeration<T>,new NamedEnumeration<T>(*this));
00383
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 #endif