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