00001
00002 #ifndef INCLUDED_plistPrimitives_h_
00003 #define INCLUDED_plistPrimitives_h_
00004
00005 #include "plistBase.h"
00006 #include <map>
00007
00008 extern "C" {
00009
00010
00011 xmlNode* xmlAddPrevSibling(xmlNode* node, xmlNode* sibling);
00012 xmlNode* xmlNewText(const xmlChar* s);
00013 xmlNode* xmlNewComment(const xmlChar* s);
00014 xmlNode* xmlAddChild(xmlNode * parent, xmlNode* child);
00015 xmlNode* xmlNewChild(xmlNode* parent, xmlNs* ns, const xmlChar * name, const xmlChar * content);
00016 int xmlStrEqual(const xmlChar* a, const xmlChar* b);
00017 xmlChar* xmlNodeGetContent(xmlNode* node);
00018 void xmlNodeSetContent(xmlNode* node, const xmlChar* content);
00019 xmlAttr* xmlHasProperty(xmlNode* node, const xmlChar* name);
00020 xmlChar* xmlGetProperty(xmlNode* node, const xmlChar* name);
00021 long xmlGetLineNo(xmlNode* node);
00022 extern void (*xmlFree)(void* ptr);
00023 void xmlNodeSetName(xmlNode* node, const xmlChar* name);
00024 void xmlFreeNode(xmlNode* node);
00025 void xmlUnlinkNode(xmlNode* node);
00026
00027 }
00028
00029 namespace plist {
00030
00031
00032
00033
00034
00035 template<typename T> const char* getTypeName();
00036
00037 template<> inline const char* getTypeName<short>() { return "integer"; }
00038 template<> inline const char* getTypeName<unsigned short>() { return "integer"; }
00039 template<> inline const char* getTypeName<int>() { return "integer"; }
00040 template<> inline const char* getTypeName<unsigned int>() { return "integer"; }
00041 template<> inline const char* getTypeName<long>() { return "integer"; }
00042 template<> inline const char* getTypeName<unsigned long>() { return "integer"; }
00043 template<> inline const char* getTypeName<long long>() { return "integer"; }
00044 template<> inline const char* getTypeName<unsigned long long>() { return "integer"; }
00045 template<> inline const char* getTypeName<float>() { return "real"; }
00046 template<> inline const char* getTypeName<double>() { return "real"; }
00047
00048
00049
00050
00051
00052
00053
00054 template<typename T>
00055 class Primitive : public PrimitiveBase {
00056 public:
00057 template<typename U, typename V> struct conversion_policy { typedef typename U::template ConversionTo<V> value_conversion; };
00058
00059
00060 Primitive() : PrimitiveBase(), val(), prevVal() {}
00061
00062 Primitive(const T& v) : PrimitiveBase(), val(v), prevVal() {}
00063
00064 Primitive& operator=(const T& v) { if(&v==&prevVal) std::swap(val,prevVal); else { prevVal=val; val=v; } fireValueChanged(prevVal==val); return *this; }
00065 virtual Primitive& operator=(const PrimitiveBase& pb) { if(dynamic_cast<const Primitive*>(&pb)!=this) operator=(pb.to<T>()); return *this; }
00066
00067 Primitive& operator=(const Primitive& p) { operator=(p.val); return *this; }
00068
00069 Primitive& operator+=(const T& v) { prevVal=val; val+=v; fireValueChanged(prevVal==val); return *this; }
00070 Primitive& operator-=(const T& v) { prevVal=val; val-=v; fireValueChanged(prevVal==val); return *this; }
00071 Primitive& operator*=(const T& v) { prevVal=val; val*=v; fireValueChanged(prevVal==val); return *this; }
00072 Primitive& operator/=(const T& v) { prevVal=val; val/=v; fireValueChanged(prevVal==val); return *this; }
00073
00074
00075 const T& operator*() const { return val; }
00076
00077 const T* operator->() const { return &val; }
00078
00079
00080 operator T() const { return val; }
00081
00082
00083 void loadXML(xmlNode* node);
00084
00085 void saveXML(xmlNode* node) const;
00086 void set(const std::string& str);
00087 using PrimitiveBase::set;
00088 std::string get() const {
00089 std::stringstream sstr;
00090 sstr <<std::setprecision(std::numeric_limits<T>::digits10)<< val;
00091 return sstr.str();
00092 }
00093
00094 virtual long toLong() const { return static_cast<long>(val); }
00095 virtual double toDouble() const { return static_cast<double>(val); }
00096
00097
00098 PLIST_CLONE_DEF(Primitive<T>,new Primitive<T>(val));
00099
00100 const T& getPreviousValue() const { return prevVal; }
00101
00102 protected:
00103 T val;
00104 T prevVal;
00105 };
00106
00107 template<typename T>
00108 void Primitive<T>::loadXML(xmlNode* node) {
00109 if(node==NULL)
00110 return;
00111 prevVal=val;
00112 bool bt=xNodeHasName(node,"true");
00113 bool bf=xNodeHasName(node,"false");
00114 if(!bt && !bf && !xNodeHasName(node,"integer") && !xNodeHasName(node,"real") && !xNodeHasName(node,"string")) {
00115 std::stringstream errstr;
00116 errstr << "Error: plist::Primitive<" << typeid(T).name() << "> expects " << getTypeName<T>() << ", got unknown type " << (const char*)xNodeGetName(node);
00117 throw bad_format(node,errstr.str());
00118 }
00119 if(!xNodeHasName(node,getTypeName<T>()))
00120 std::cerr << "Warning: plist expected " << getTypeName<T>() << " got " << (const char*)xNodeGetName(node) << ", trying to convert. (line " << xmlGetLineNo(node) << ")" << std::endl;
00121 if(bt)
00122 val = true;
00123 else if(bf)
00124 val = false;
00125 else {
00126 xmlChar * cont=xmlNodeGetContent(node);
00127 std::stringstream str((const char*)cont);
00128 str >> val;
00129 xmlFree(cont);
00130 }
00131 fireValueChanged(prevVal==val);
00132 }
00133 template<typename T>
00134 void Primitive<T>::saveXML(xmlNode* node) const {
00135 if(node==NULL)
00136 return;
00137 xmlNodeSetName(node,(const xmlChar*)getTypeName<T>());
00138 std::stringstream str;
00139 str <<std::setprecision(std::numeric_limits<T>::digits10)<< val;
00140 xmlNodeSetContent(node,(const xmlChar*)str.str().c_str());
00141 }
00142 template<typename T>
00143 void Primitive<T>::set(const std::string& str) {
00144 prevVal=val;
00145 std::stringstream sstr(str);
00146 sstr >> val;
00147 while(sstr.good() && isspace(sstr.peek()))
00148 sstr.get();
00149 if(sstr.fail()) {
00150 if(matchTrue(str))
00151 val=true;
00152 else if(matchFalse(str))
00153 val=false;
00154 else {
00155 std::string err="Expected "; err+=getTypeName<T>(); err+=" value, got '"+str+"'";
00156 throw bad_format(NULL,err);
00157 }
00158 std::cerr << "Warning: expected " << getTypeName<T>() << " value, interpreting '" << str << "' as boolean (value of " << val << ")" << std::endl;
00159 }
00160 if(sstr.good()) {
00161 std::cerr << "Warning: expected " << getTypeName<T>() << " value, truncating remainder '";
00162 char c=sstr.get();
00163 while(sstr) { std::cerr << c; c=sstr.get(); }
00164 std::cerr << "'" << std::endl;
00165 }
00166 fireValueChanged(prevVal==val);
00167 }
00168
00169
00170 PLIST_CLONE_IMPT(T,Primitive,new Primitive<T>(val));
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 template<>
00181 class Primitive<bool> : public PrimitiveBase {
00182 public:
00183 template<typename U, typename V> struct conversion_policy { typedef typename U::template ConversionTo<V> value_conversion; };
00184 Primitive() : PrimitiveBase(), val(), prevVal() {}
00185 Primitive(const bool& v) : PrimitiveBase(), val(v), prevVal() {}
00186 Primitive& operator=(const bool& v) { if(&v==&prevVal) std::swap(val,prevVal); else { prevVal=val; val=v; } fireValueChanged(prevVal==val); return *this; }
00187 virtual Primitive& operator=(const PrimitiveBase& pb) { if(dynamic_cast<const Primitive*>(&pb)!=this) operator=(pb.to<bool>()); return *this; }
00188 Primitive& operator=(const Primitive& p) { operator=(p.val); return *this; }
00189
00190 const bool& operator*() const { return val; }
00191
00192 const bool* operator->() const { return &val; }
00193 operator bool() const { return val; }
00194
00195 void loadXML(xmlNode* node);
00196 void saveXML(xmlNode* node) const;
00197 void set(const std::string& str);
00198 using PrimitiveBase::set;
00199 std::string get() const {
00200 return val?"true":"false";
00201 }
00202 virtual long toLong() const { return static_cast<long>(val); }
00203 virtual double toDouble() const { return static_cast<double>(val); }
00204
00205
00206 PLIST_CLONE_DEF(Primitive<bool>,new Primitive<bool>(val));
00207
00208 const bool& getPreviousValue() const { return prevVal; }
00209
00210 protected:
00211 bool val;
00212 bool prevVal;
00213 };
00214
00215
00216
00217
00218
00219
00220 template<>
00221 class Primitive<char> : public PrimitiveBase {
00222 public:
00223 template<typename U, typename V> struct conversion_policy { typedef typename U::template ConversionTo<V> value_conversion; };
00224 Primitive() : PrimitiveBase(), val(), prevVal(), numeric(false) {}
00225 Primitive(const char& v, bool isNum=false) : PrimitiveBase(), val(v), prevVal(), numeric(isNum) {}
00226 Primitive& operator=(char v) { if(&v==&prevVal) std::swap(val,prevVal); else { prevVal=val; val=v; } fireValueChanged(prevVal==val); return *this; }
00227 virtual Primitive& operator=(const PrimitiveBase& pb) { if(dynamic_cast<const Primitive*>(&pb)!=this) operator=(pb.to<char>()); return *this; }
00228
00229 Primitive& operator=(const Primitive& p) { operator=(p.val); return *this; }
00230 Primitive& operator+=(char v) { prevVal=val; val+=v; fireValueChanged(prevVal==val); return *this; }
00231 Primitive& operator-=(char v) { prevVal=val; val-=v; fireValueChanged(prevVal==val); return *this; }
00232 Primitive& operator*=(char v) { prevVal=val; val*=v; fireValueChanged(prevVal==val); return *this; }
00233 Primitive& operator/=(char v) { prevVal=val; val/=v; fireValueChanged(prevVal==val); return *this; }
00234
00235 const char& operator*() const { return val; }
00236
00237 const char* operator->() const { return &val; }
00238 operator char() const { return val; }
00239
00240 void setNumeric(bool isNum) { numeric=isNum; }
00241 bool getNumeric() const { return numeric; }
00242
00243 void loadXML(xmlNode* node);
00244 void saveXML(xmlNode* node) const;
00245 void set(const std::string& str);
00246 using PrimitiveBase::set;
00247 std::string get() const {
00248 if(numeric) {
00249 std::stringstream sstr;
00250 sstr << (int)val;
00251 return sstr.str();
00252 } else
00253 return std::string(1,val);
00254 }
00255 virtual long toLong() const { return static_cast<long>(val); }
00256 virtual double toDouble() const { return static_cast<double>(val); }
00257
00258
00259 PLIST_CLONE_DEF(Primitive<char>,new Primitive<char>(val));
00260
00261 const char& getPreviousValue() const { return prevVal; }
00262
00263 protected:
00264 char val;
00265 char prevVal;
00266 bool numeric;
00267 };
00268
00269
00270
00271
00272 template<>
00273 class Primitive<unsigned char> : public PrimitiveBase {
00274 public:
00275 template<typename U, typename V> struct conversion_policy { typedef typename U::template ConversionTo<V> value_conversion; };
00276 Primitive() : PrimitiveBase(), val(), prevVal(), numeric(false) {}
00277 Primitive(const unsigned char& v, bool isNum=false) : PrimitiveBase(), val(v), prevVal(), numeric(isNum) {}
00278 Primitive& operator=(unsigned char v) { prevVal=val; val=v; fireValueChanged(prevVal==val); return *this; }
00279 virtual Primitive& operator=(const PrimitiveBase& pb) { if(dynamic_cast<const Primitive*>(&pb)!=this) operator=(pb.to<unsigned char>()); return *this; }
00280
00281 Primitive& operator=(const Primitive& p) { operator=(p.val); return *this; }
00282 Primitive& operator+=(unsigned char v) { prevVal=val; val+=v; fireValueChanged(prevVal==val); return *this; }
00283 Primitive& operator-=(unsigned char v) { prevVal=val; val-=v; fireValueChanged(prevVal==val); return *this; }
00284 Primitive& operator*=(unsigned char v) { prevVal=val; val*=v; fireValueChanged(prevVal==val); return *this; }
00285 Primitive& operator/=(unsigned char v) { prevVal=val; val/=v; fireValueChanged(prevVal==val); return *this; }
00286
00287 const unsigned char& operator*() const { return val; }
00288
00289 const unsigned char* operator->() const { return &val; }
00290 operator unsigned char() const { return val; }
00291
00292 void setNumeric(bool isNum) { numeric=isNum; }
00293 bool getNumeric() const { return numeric; }
00294
00295 void loadXML(xmlNode* node);
00296 void saveXML(xmlNode* node) const;
00297 void set(const std::string& str);
00298 using PrimitiveBase::set;
00299 std::string get() const {
00300 if(numeric) {
00301 std::stringstream sstr;
00302 sstr << (int)val;
00303 return sstr.str();
00304 } else
00305 return std::string(1,val);
00306 }
00307 virtual long toLong() const { return static_cast<long>(val); }
00308 virtual double toDouble() const { return static_cast<double>(val); }
00309
00310
00311 PLIST_CLONE_DEF(Primitive<unsigned char>,new Primitive<unsigned char>(val));
00312
00313 const unsigned char& getPreviousValue() const { return prevVal; }
00314
00315 protected:
00316 unsigned char val;
00317 unsigned char prevVal;
00318 bool numeric;
00319 };
00320
00321
00322
00323
00324 template<>
00325 class Primitive<std::string> : public PrimitiveBase, public std::string {
00326 public:
00327 template<typename U, typename V> struct conversion_policy { typedef typename U::template ConversionTo<V> value_conversion; };
00328 Primitive() : PrimitiveBase(), std::string(), prevVal() {}
00329 Primitive(const std::string& v) : PrimitiveBase(), std::string(v), prevVal() {}
00330 Primitive(const std::string& v, size_type off, size_type count=npos) : PrimitiveBase(), std::string(v,off,count), prevVal() {}
00331 Primitive(const char* v, size_type count) : PrimitiveBase(), std::string(v,count), prevVal() {}
00332 Primitive(const char* v) : PrimitiveBase(), std::string(v), prevVal() {}
00333 Primitive(size_type count, char v) : PrimitiveBase(), std::string(count,v), prevVal() {}
00334 Primitive& operator=(const std::string& v) { if(&v==&prevVal) std::string::swap(prevVal); else { prevVal=*this; std::string::operator=(v); } fireValueChanged(prevVal==*this); return *this; }
00335 Primitive& operator=(const char* v) { prevVal=*this; std::string::operator=(v); fireValueChanged(prevVal==*this); return *this; }
00336 Primitive& operator=(char v) { prevVal=*this; std::string::operator=(v); fireValueChanged(prevVal==*this); return *this; }