00001 #include "plistPrimitives.h"
00002
00003 namespace plist {
00004
00005 void Primitive<bool>::loadXML(xmlNode* node) {
00006 if(node==NULL)
00007 return;
00008 if(xNodeHasName(node,"true")) {
00009 val=true;
00010 fireValueChanged();
00011 } else if(xNodeHasName(node,"false")) {
00012 val=false;
00013 fireValueChanged();
00014 } else if(xNodeHasName(node,"integer") || xNodeHasName(node,"real")) {
00015 xmlChar * cont=xmlNodeGetContent(node);
00016 std::stringstream str((char*)cont);
00017 str >> val;
00018 xmlFree(cont);
00019 fireValueChanged();
00020 } else if(xNodeHasName(node,"string")) {
00021 xmlChar * cont=xmlNodeGetContent(node);
00022 try {
00023 set((char*)cont);
00024 std::cerr << "Warning: plist boolean expects value of '<true/>', '<false/>', or numeric. String value of '" << (char*)cont << "' is not recommended." << std::endl;
00025 } catch(const bad_format& err) {
00026 xmlFree(cont);
00027 throw bad_format(node,err.what());
00028 } catch(...) {
00029 xmlFree(cont);
00030 throw;
00031 }
00032 xmlFree(cont);
00033 } else
00034 throw bad_format(node,"Error: plist boolean must be 'true', 'false', or numeric type");
00035 }
00036 void Primitive<bool>::saveXML(xmlNode* node) const {
00037 if(node==NULL)
00038 return;
00039 xmlNodeSetName(node,(const xmlChar*)(val?"true":"false"));
00040 xmlNodeSetContent(node,NULL);
00041 }
00042 void Primitive<bool>::set(const std::string& str) {
00043 if(matchTrue(str))
00044 val=true;
00045 else if(matchFalse(str))
00046 val=false;
00047 else {
00048 float t;
00049 if(sscanf(str.c_str(),"%g",&t)==0)
00050 throw bad_format(NULL,"Error: plist boolean must be 'true', 'false', or numeric type");
00051 val=t;
00052 }
00053 fireValueChanged();
00054 }
00055
00056 PLIST_CLONE_IMP(Primitive<bool>,new Primitive<bool>(val));
00057
00058
00059 void Primitive<char>::loadXML(xmlNode* node) {
00060 if(node==NULL)
00061 return;
00062 xmlChar* cont=xmlNodeGetContent(node);
00063 try {
00064 if(xNodeHasName(node,"string")) {
00065 set((char*)cont);
00066 } else if(xNodeHasName(node,"integer")) {
00067 val=strtol((const char*)cont,NULL,0);
00068 fireValueChanged();
00069 } else if(xNodeHasName(node,"real")) {
00070 val=(char)strtod((const char*)cont,NULL);
00071 fireValueChanged();
00072 } else if(xNodeHasName(node,"true")) {
00073 val=true;
00074 fireValueChanged();
00075 } else if(xNodeHasName(node,"false")) {
00076 val=false;
00077 fireValueChanged();
00078 } else {
00079 throw bad_format(node,"Error: plist char must be either a string or integer");
00080 }
00081 } catch(const bad_format& err) {
00082 xmlFree(cont);
00083 throw bad_format(node,err.what());
00084 } catch(...) {
00085 xmlFree(cont);
00086 throw;
00087 }
00088 xmlFree(cont);
00089 }
00090 void Primitive<char>::saveXML(xmlNode* node) const {
00091 if(node==NULL)
00092 return;
00093 if(numeric) {
00094 xmlNodeSetName(node,(const xmlChar*)"integer");
00095 std::stringstream str;
00096 str << (int)val;
00097 xmlNodeSetContent(node,(const xmlChar*)str.str().c_str());
00098 } else {
00099 xmlNodeSetName(node,(const xmlChar*)"string");
00100 xmlChar str[2] = {val,'\0'};
00101 xmlNodeSetContent(node,(const xmlChar*)str);
00102 }
00103 }
00104 void Primitive<char>::set(const std::string& str) {
00105 if(str.size()==0)
00106 throw bad_format(NULL,"Error: plist char must have non-empty content");
00107 val=str[0];
00108 if(str.size()>1) {
00109 std::cerr << "Warning: plist expected single char, found multi-char string '" << str << "'";
00110 if(matchTrue(str))
00111 val=true;
00112 else if(matchFalse(str))
00113 val=false;
00114 else {
00115 std::cerr << " (using first character '" << val << "')" << std::endl;
00116 return;
00117 }
00118 std::cerr << " (interpreted as boolean " << (bool)val << ")" << std::endl;
00119 }
00120 fireValueChanged();
00121 }
00122
00123 PLIST_CLONE_IMP(Primitive<char>,new Primitive<char>(val));
00124
00125 void Primitive<unsigned char>::loadXML(xmlNode* node) {
00126 if(node==NULL)
00127 return;
00128 xmlChar* cont=xmlNodeGetContent(node);
00129 try {
00130 if(xNodeHasName(node,"string")) {
00131 set((char*)cont);
00132 } else if(xNodeHasName(node,"integer")) {
00133 val=strtol((const char*)cont,NULL,0);
00134 fireValueChanged();
00135 } else if(xNodeHasName(node,"real")) {
00136 val=(char)strtod((const char*)cont,NULL);
00137 fireValueChanged();
00138 } else if(xNodeHasName(node,"true")) {
00139 val=true;
00140 fireValueChanged();
00141 } else if(xNodeHasName(node,"false")) {
00142 val=false;
00143 fireValueChanged();
00144 } else {
00145 throw bad_format(node,"Error: plist unsigned char must be either a string or integer");
00146 }
00147 } catch(const bad_format& err) {
00148 xmlFree(cont);
00149 throw bad_format(node,err.what());
00150 } catch(...) {
00151 xmlFree(cont);
00152 throw;
00153 }
00154 xmlFree(cont);
00155 }
00156 void Primitive<unsigned char>::saveXML(xmlNode* node) const {
00157 if(node==NULL)
00158 return;
00159 if(numeric) {
00160 xmlNodeSetName(node,(const xmlChar*)"integer");
00161 std::stringstream str;
00162 str << (int)val;
00163 xmlNodeSetContent(node,(const xmlChar*)str.str().c_str());
00164 } else {
00165 xmlNodeSetName(node,(const xmlChar*)"string");
00166 xmlChar str[2] = {val,'\0'};
00167 xmlNodeSetContent(node,(const xmlChar*)str);
00168 }
00169 }
00170 void Primitive<unsigned char>::set(const std::string& str) {
00171 if(str.size()==0)
00172 throw bad_format(NULL,"Error: plist char must have non-empty content");
00173 val=str[0];
00174 if(str.size()>1) {
00175 std::cerr << "Warning: plist expected single char, found multi-char string '" << str << "'";
00176 if(matchTrue(str))
00177 val=true;
00178 else if(matchFalse(str))
00179 val=false;
00180 else {
00181 std::cerr << " (using first character '" << val << "')" << std::endl;
00182 return;
00183 }
00184 std::cerr << " (interpreted as boolean " << (bool)val << ")" << std::endl;
00185 }
00186 fireValueChanged();
00187 }
00188
00189 PLIST_CLONE_IMP(Primitive<unsigned char>,new Primitive<unsigned char>(val));
00190
00191
00192 #define PLIST_OBJECT_SPECIALIZATION(T,PRIM) \
00193 void Primitive<T>::loadXML(xmlNode* node) { \
00194 if(node==NULL) \
00195 return; \
00196 bool bt=xNodeHasName(node,"true"); \
00197 bool bf=xNodeHasName(node,"false"); \
00198 if(!bt && !bf && !xNodeHasName(node,"integer") && !xNodeHasName(node,"real") && !xNodeHasName(node,"string")) \
00199 throw bad_format(node,"Error: plist "#T" expects "PRIM" type"); \
00200 if(!xNodeHasName(node,PRIM)) \
00201 std::cerr << "Warning: plist expected "PRIM" got " << (const char*)xNodeGetName(node) << ", trying to convert. (line " << xmlGetLineNo(node) << ")" << std::endl; \
00202 if(bt) \
00203 val = true; \
00204 else if(bf) \
00205 val = false; \
00206 else { \
00207 xmlChar * cont=xmlNodeGetContent(node); \
00208 std::stringstream str((const char*)cont); \
00209 str >> val; \
00210 xmlFree(cont); \
00211 } \
00212 fireValueChanged(); \
00213 } \
00214 void Primitive<T>::saveXML(xmlNode* node) const { \
00215 if(node==NULL) \
00216 return; \
00217 xmlNodeSetName(node,(const xmlChar*)PRIM); \
00218 std::stringstream str; \
00219 str <<std::setprecision(128)<< val; \
00220 xmlNodeSetContent(node,(const xmlChar*)str.str().c_str()); \
00221 } \
00222 void Primitive<T>::set(const std::string& str) { \
00223 std::stringstream sstr(str); \
00224 sstr >> val; \
00225 while(sstr.good() && isspace(sstr.peek())) \
00226 sstr.get(); \
00227 if(sstr.fail()) { \
00228 if(matchTrue(str)) \
00229 val=true; \
00230 else if(matchFalse(str)) \
00231 val=false; \
00232 else { \
00233 std::string err="Expected "; err+=PRIM; err+=" value, got '"+str+"'"; \
00234 throw bad_format(NULL,err); \
00235 } \
00236 std::cerr << "Warning: expected " << PRIM << " value, interpreting '" << str << "' as boolean (value of " << val << ")" << std::endl; \
00237 } \
00238 if(sstr.good()) { \
00239 std::cerr << "Warning: expected " << PRIM << " value, truncating remainder '"; \
00240 char c=sstr.get(); \
00241 while(sstr) { std::cerr << c; c=sstr.get(); } \
00242 std::cerr << "'" << std::endl; \
00243 } \
00244 fireValueChanged(); \
00245 } \
00246 PLIST_CLONE_IMP(Primitive<T>,new Primitive<T>(val));
00247
00248 PLIST_OBJECT_SPECIALIZATION(short,"integer");
00249 PLIST_OBJECT_SPECIALIZATION(unsigned short,"integer");
00250 PLIST_OBJECT_SPECIALIZATION(int,"integer");
00251 PLIST_OBJECT_SPECIALIZATION(unsigned int,"integer");
00252 PLIST_OBJECT_SPECIALIZATION(long,"integer");
00253 PLIST_OBJECT_SPECIALIZATION(unsigned long,"integer");
00254 PLIST_OBJECT_SPECIALIZATION(long long,"integer");
00255 PLIST_OBJECT_SPECIALIZATION(unsigned long long,"integer");
00256 PLIST_OBJECT_SPECIALIZATION(float,"real");
00257 PLIST_OBJECT_SPECIALIZATION(double,"real");
00258
00259 #undef PLIST_OBJECT_SPECIALIZATION
00260
00261
00262 void Primitive<std::string>::loadXML(xmlNode* node) {
00263 if(node==NULL)
00264 return;
00265 if(xNodeHasName(node,"string")) {
00266 xmlChar * cont=xmlNodeGetContent(node);
00267 *this=(char*)cont;
00268 xmlFree(cont);
00269 } else {
00270 if(xNodeHasName(node,"integer") || xNodeHasName(node,"real")) {
00271 xmlChar * cont=xmlNodeGetContent(node);
00272 *this=(char*)cont;
00273 xmlFree(cont);
00274 } else if(xNodeHasName(node,"true"))
00275 *this="true";
00276 else if(xNodeHasName(node,"false"))
00277 *this="false";
00278 else
00279 throw bad_format(node,"Error: plist string must be 'true', 'false', or numeric type");
00280 std::cerr << "Warning: plist string expected, found " << (const char*)xNodeGetName(node) << " on line " << xmlGetLineNo(node) << std::endl;
00281 fireValueChanged();
00282 }
00283 }
00284 void Primitive<std::string>::saveXML(xmlNode* node) const {
00285 if(node==NULL)
00286 return;
00287 xmlNodeSetName(node,(const xmlChar*)"string");
00288 xmlNodeSetContent(node,(const xmlChar*)c_str());
00289 }
00290
00291 PLIST_CLONE_IMP(Primitive<std::string>,new Primitive<std::string>(get()));
00292
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305