Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

plistPrimitives.cc

Go to the documentation of this file.
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   //! implements the clone function for Primitive<bool>
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   //! implements the clone function for Primitive<char>
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   //! implements the clone function for Primitive<unsigned char>
00189   PLIST_CLONE_IMP(Primitive<unsigned char>,new Primitive<unsigned char>(val));
00190   
00191 //! a macro to provide template specializations for the numeric primitives, which only need to vary their string name
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   //! implements the clone function for Primitive<std::string>
00291   PLIST_CLONE_IMP(Primitive<std::string>,new Primitive<std::string>(get()));
00292 
00293 } //namespace plist
00294 
00295 /*! @file
00296 * @brief 
00297 * @author Ethan Tira-Thompson (ejt) (Creator)
00298 *
00299 * $Author: ejt $
00300 * $Name: tekkotsu-3_0 $
00301 * $Revision: 1.10 $
00302 * $State: Exp $
00303 * $Date: 2006/09/16 17:32:40 $
00304 */
00305 

Tekkotsu v3.0
Generated Wed Oct 4 00:03:45 2006 by Doxygen 1.4.7