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