00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef __XML_RPC__SERIALIZABLE_H
00034 #define __XML_RPC__SERIALIZABLE_H
00035
00036 #include "m_net.h"
00037 #include <string>
00038 #include <sstream>
00039 #include <iostream>
00040 #include <typeinfo>
00041 #include <ctype.h>
00042 #include "Exception.h"
00043 #include "massert.h"
00044 #include "Serializable.h"
00045 #include "mstring.h"
00046
00052 using std::istream;
00053 using std::istringstream;
00054
00055
00056
00057 namespace mace {
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00072
00075 template<typename S>
00076 void serializeXML_RPC(std::string& str, const void* pitem, const S& item)
00077 throw(SerializationException) {
00078
00079 string s;
00080 serialize(s, &item);
00081
00082 serializeXML_RPC(str, &s, s);
00083 }
00084
00086 template<typename S>
00087 void serializeXML_RPC(std::string& str, const std::string* pitem, const S& item) throw(SerializationException) {
00088 if (Base64::isPrintable(item)) {
00089 str.append("<string>");
00090 for (size_t x = 0; x < item.size(); x++) {
00091 char c = item[x];
00092 switch(c) {
00093 case '<':
00094 str.append("<");
00095 break;
00096 case '>':
00097 str.append(">");
00098 break;
00099 case '&':
00100 str.append("&");
00101 break;
00102 default:
00103 str.push_back(c);
00104 }
00105 }
00106 str.append("</string>");
00107 }
00108 else {
00109 str.append("<base64>");
00110 str.append(Base64::encode(item));
00111 str.append("</base64>");
00112 }
00113 }
00114
00116 template<typename S>
00117 void serializeXML_RPC(std::string& str, const Serializable* pitem, const S& item) throw(SerializationException) {
00118 item.serializeXML_RPC(str);
00119 }
00120
00122 template<typename S>
00123 void serializeXML_RPC(std::string& str, const int* pitem,
00124 const S& item) {
00125 char buf[30];
00126 sprintf(buf, "%d", *pitem);
00127
00128 str.append("<i4>");
00129 str.append(buf);
00130 str.append("</i4>");
00131 }
00132
00134 template<typename S>
00135 void serializeXML_RPC(std::string& str, const bool* pitem,
00136 const S& item) {
00137 str.append("<boolean>");
00138 if(*pitem)
00139 str.append("1");
00140 else
00141 str.append("0");
00142 str.append("</boolean>");
00143 }
00144
00146 template<typename S>
00147 void serializeXML_RPC(std::string& str, const double* pitem,
00148 const S& item) {
00149 char buf[30];
00150 snprintf(buf, 30, "%f", *pitem);
00151 str.append("<double>");
00152 str.append(buf);
00153 str.append("</double>");
00154 }
00155
00157 template<typename S>
00158 int deserializeXML_RPC(std::istream& in, void* pitem, S& item)
00159 throw(SerializationException) {
00160
00161 string s;
00162
00163 int r = deserializeXML_RPC(in, &s, s);
00164 istringstream is(s);
00165 deserialize(is, &item);
00166 return r;
00167 }
00168
00170 template<typename S>
00171 int deserializeXML_RPC(std::istream& in, Serializable* pitem, S& item)
00172 throw(SerializationException) {
00173 return item.deserializeXML_RPC(in);
00174 }
00175
00177 template<typename S>
00178 int deserializeXML_RPC(std::istream& in, std::string* pitem, S& item) throw(SerializationException) {
00179 long offset = in.tellg();
00180 char ch, ch1, ch2, ch3, ch4;
00181 std::string tag;
00182 bool dhack = false;
00183
00184 item.clear();
00185 in >> std::skipws;
00186
00187 ch = in.peek();
00188 if (ch != '<') {
00189
00190 dhack = true;
00191 }
00192 else {
00193 long dsp = in.tellg();
00194 in >> ch >> ch1 >> ch2 >> ch3 >> ch4;
00195 in.seekg(dsp);
00196 if (ch1 == '/' && ch2 == 'v' && ch3 == 'a' && ch4 == 'l') {
00197
00198 return (long)in.tellg() - offset;
00199 }
00200 else {
00201 dhack = false;
00202 }
00203 }
00204
00205 if (!dhack) {
00206 tag = SerializationUtil::getTag(in);
00207
00208 }
00209 if (dhack || tag == "<string>") {
00210 in >> std::noskipws >> ch;
00211 while (ch != '<') {
00212 switch (ch) {
00213 case '&':
00214 in >> ch1 >> ch2 >> ch3;
00215
00216 if (!in) {
00217 throw SerializationException("String not long enough to deserialize");
00218 }
00219 if (ch2 == 't' && ch3 == ';') {
00220 if (ch1 == 'l') {
00221 item.push_back('<');
00222 }
00223 else if (ch1 == 'g') {
00224 item.push_back('>');
00225 }
00226 else {
00227 throw SerializationException("Unrecognizable escape sequence while deserializing string");
00228 }
00229 }
00230 else {
00231 in >> ch4;
00232 if (!in) {
00233 throw SerializationException("String not long enough to deserialize");
00234 }
00235 if (ch1 != 'a' || ch2 != 'm' || ch3 != 'p'|| ch4 != ';') {
00236 throw SerializationException("Unrecognizable escape sequence while deserializing string");
00237 }
00238 else {
00239 item.push_back('&');
00240 }
00241 }
00242 break;
00243 default:
00244 item.push_back(ch);
00245 }
00246 in >> ch;
00247 if (!in) {
00248 throw SerializationException("String not long enough to deserialize");
00249 }
00250 }
00251 if (!dhack) {
00252 SerializationUtil::expect(in, "/string>");
00253 in >> std::skipws;
00254 }
00255 else {
00256 in.putback('<');
00257 }
00258 }
00259 else if (tag == "<base64>") {
00260 std::string buf;
00261 std::istringstream* is = dynamic_cast<std::istringstream*>(&in);
00262 if (is) {
00263 std::string ibuf = is->str();
00264 long ioff = is->tellg();
00265 size_t i = ibuf.find('<', ioff);
00266 if (i == std::string::npos) {
00267 throw SerializationException("String not long enough to deserialize");
00268 }
00269 buf = ibuf.substr(ioff, i - ioff);
00270 in.seekg(i + 1, std::ios::beg);
00271 }
00272 else {
00273 in >> ch;
00274 while (ch != '<') {
00275 buf.push_back(ch);
00276 in >> ch;
00277 if (!in) {
00278 throw SerializationException("String not long enough to deserialize");
00279 }
00280 }
00281 }
00282 SerializationUtil::expect(in, "/base64>");
00283 item.append(Base64::decode(buf));
00284 }
00285 else {
00286 throw SerializationException("Bad tag for string: " + tag);
00287 }
00288 return (long)in.tellg() - offset;
00289 }
00290
00292 template<typename S>
00293 int deserializeXML_RPC(std::istream& in, int* pitem, S& item)
00294 throw(SerializationException) {
00295 std::istream::pos_type offset = in.tellg();
00296 std::string tag;
00297
00298 tag = SerializationUtil::getTag(in);
00299 if(tag == "<i4>" || tag == "<int>") {
00300 SerializationUtil::getToken(in, *pitem);
00301 if(tag == "<i4>") {
00302 SerializationUtil::expectTag(in, "</i4>");
00303 }
00304 else {
00305 SerializationUtil::expectTag(in, "</int>");
00306 }
00307 }
00308 else
00309 throw SerializationException("error parsing integer tag: " + tag);
00310 return in.tellg() - offset;
00311 }
00312
00314 template<typename S>
00315 int deserializeXML_RPC(std::istream& in, bool* pitem, S& item)
00316 throw(SerializationException) {
00317 std::istream::pos_type offset = in.tellg();
00318 char c;
00319
00320 SerializationUtil::expectTag(in, "<boolean>");
00321 SerializationUtil::getToken(in, c);
00322 if(c == 1) {
00323 *pitem = true;
00324 }
00325 else if(c == 0) {
00326 *pitem = false;
00327 }
00328 else {
00329 throw SerializationException("Invalid value for boolean variable: " + c);
00330 }
00331 SerializationUtil::expectTag(in, "</boolean>");
00332
00333 return in.tellg() - offset;
00334 }
00335
00337 template<typename S>
00338 int deserializeXML_RPC(std::istream& in, double* pitem, S& item)
00339 throw(SerializationException) {
00340 std::istream::pos_type offset = in.tellg();
00341
00342 SerializationUtil::expectTag(in, "<double>");
00343 SerializationUtil::getToken(in, *pitem);
00344 SerializationUtil::expectTag(in, "</double>");
00345
00346 return in.tellg() - offset;
00347 }
00348
00350 template<typename S>
00351 int deserializeXML_RPCParam(std::istream& in, S* pitem, S& item)
00352 throw(SerializationException) {
00353 std::istream::pos_type offset = in.tellg();
00354
00355 SerializationUtil::expectTag(in, "<param>");
00356 SerializationUtil::expectTag(in, "<value>");
00357 mace::deserializeXML_RPC(in, pitem, item);
00358 SerializationUtil::expectTag(in, "</value>");
00359 SerializationUtil::expectTag(in, "</param>");
00360
00361 return in.tellg() - offset;
00362 }
00363
00365 template<typename S>
00366 std::string serializeXML_RPC(const S* pitem, const S& item)
00367 throw(SerializationException) {
00368 std::string s;
00369 mace::serializeXML_RPC(s, &item, item);
00370 return s;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00381 template<typename S>
00382 int deserializeXML_RPCStr(const std::string& str, void* pitem, S& item)
00383 throw(SerializationException) {
00384 std::istringstream in(str);
00385 return mace::deserializeXML_RPC(in, pitem, item);
00386 }
00387 }
00388 #endif