00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <arpa/inet.h>
00021 #include <libxml/tree.h>
00022 #include <libxml/encoding.h>
00023 #include <libxml/xmlwriter.h>
00024 #include <libxml/xmlsave.h>
00025 #include <libxml/xmlschemas.h>
00026 #include <sstream>
00027 #include <wchar.h>
00028 #include <iconv.h>
00029 #define _LIBXML_ALREADY_INCLUDED
00030 #include "secstwo_internal.hpp"
00031 #include "secstwo_serialize.h"
00032
00033 using namespace freesecs::secstwo;
00034
00035 #define SCHEMA_URI "http:\/\/freesecs.sourceforge.net/xsd/e5"
00036 #define ENCODING "UTF-8"
00037 #define ASSERT_THROW(expr, fmt...) {if(expr){fprintf(stderr, fmt); throw;}}
00038 #define ASSERT_RETURN(expr, fmt...) {if(expr){fprintf(stderr, fmt); return -1;}}
00039 #define ASSERT_FREE(xml_val) {if(NULL != xml_val) xmlFree(xml_val);}
00040 #define XMLCHAR_CAST (xmlChar*)
00041
00042 #define MOVE_TO_NEXT_NODE(pnode) while(pnode && XML_ELEMENT_NODE != pnode->type) {pnode = pnode->next;}
00043
00044 uint64_t ntohll(uint64_t n)
00045 {
00046 #if __BYTE_ORDER == __BIG_ENDIAN
00047 return n;
00048 #else
00049 return ( htonl( (n >> 32) & 0xFFFFFFFF) |
00050 ((uint64_t) (htonl(n & 0xFFFFFFFF)) << 32));
00051 #endif
00052 };
00053 uint64_t htonll(uint64_t n)
00054 {
00055 #if __BYTE_ORDER == __BIG_ENDIAN
00056 return n;
00057 #else
00058 return ( htonl( (n >> 32) & 0xFFFFFFFF) |
00059 ((uint64_t) (htonl(n & 0xFFFFFFFF)) << 32));
00060 #endif
00061 };
00062
00063 inline xmlNode* move_to_next(xmlNode *pnode)
00064 {
00065 while(pnode && XML_ELEMENT_NODE != pnode->type) pnode = pnode->next;
00066
00067 return pnode && XML_ELEMENT_NODE == pnode->type ? pnode : NULL;
00068 }
00069
00070 template<typename type> type ntoh (const type& t) {return t; }
00071 template<> uint16_t ntoh<uint16_t> (const uint16_t &t) { return ntohs(t); }
00072 template<> uint32_t ntoh<uint32_t> (const uint32_t &t) { return ntohl(t); }
00073 template<> int16_t ntoh<int16_t> (const int16_t &t) { return ntohs(t); }
00074 template<> int32_t ntoh<int32_t> (const int32_t &t) { return ntohl(t); }
00075 template<> uint64_t ntoh<uint64_t> (const uint64_t &t) { return ntohll(t);}
00076 template<> int64_t ntoh<int64_t> (const int64_t &t) { return ntohll(t);}
00077
00078 template<typename type> type hton (const type& t) {return t; }
00079 template<> uint16_t hton<uint16_t> (const uint16_t &t) { return htons(t); }
00080 template<> uint32_t hton<uint32_t> (const uint32_t &t) { return htonl(t); }
00081 template<> int16_t hton<int16_t> (const int16_t &t) { return htons(t); }
00082 template<> int32_t hton<int32_t> (const int32_t &t) { return htonl(t); }
00083 template<> uint64_t hton<uint64_t> (const uint64_t &t) { return htonll(t);}
00084 template<> int64_t hton<int64_t> (const int64_t &t) { return htonll(t);}
00085
00086 binary_deserializer_t::binary_deserializer_t(data_t *begin, data_t *end)
00087 :_begin(begin), _end(end), _data_len(0), _type(e_none_t)
00088 {
00089 uint8_t *byte_start;
00090 size_t num_len_bytes, len_bytes;
00091 size_t ix;
00092
00093 if(begin == end)
00094 {
00095 throw;
00096 }
00097 else if(NULL == begin)
00098 {
00099 throw;
00100 }
00101 else if(NULL == end)
00102 {
00103 throw;
00104 }
00105
00106 _type = (data_type_t) ((*begin >> 2) & 0x3f);
00107
00108 if(_type > e_none_t)
00109 {
00110 throw;
00111 }
00112
00113 num_len_bytes = *begin & 0x3;
00114
00115 if(num_len_bytes > 3)
00116 {
00117 throw;
00118 }
00119
00120 memcpy(&len_bytes, begin+1, num_len_bytes);
00121 byte_start = (uint8_t*)(&len_bytes);
00122 for(ix = 0; ix < num_len_bytes; ++ix)
00123 {
00124 _data_len += byte_start[ix] << (num_len_bytes - ix - 1);
00125 }
00126
00127 _sod = begin + num_len_bytes + 1;
00128 _eod = _sod + _data_len;
00129
00130 if(_eod > end)
00131 {
00132 throw;
00133 }
00134 }
00135
00136 template<typename simple_t>
00137 pdata_item_t bdeserialize_simple_type(uint8_t *begin, uint8_t *end)
00138 {
00139 typename simple_t::data_t *b, *e, *it;
00140 typename simple_t::container_t data;
00141
00142 b = (typename simple_t::data_t*)begin;
00143 e = (typename simple_t::data_t*)end;
00144
00145 data.reserve(e - b);
00146
00147 for(it = b; it < e; ++it)
00148 {
00149 data.push_back(ntoh((typename simple_t::data_t)*it));
00150 }
00151
00152 simple_t *t = new simple_t("", data);
00153 return (data_item_t*)t;
00154 };
00155
00156 template<typename st>
00157 pdata_item_t bdeserialize_string_type(uint8_t *begin, uint8_t *end)
00158 {
00159 return (data_item_t*) new st("", begin, end - begin);
00160 }
00161
00162 pdata_item_t
00163 binary_deserializer_t::operator()(data_t **next_item)
00164 {
00165 uint32_t ix;
00166 data_t *next;
00167 list_item_t *plist;
00168 pdata_item_t r;
00169
00170 typedef pdata_item_t (*bdeserialize_fn)(data_t*, data_t*);
00171 static bdeserialize_fn dfuncs[e_none_t] =
00172 {
00173 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00174 bdeserialize_simple_type<binary_item_t>,
00175 bdeserialize_simple_type<bool_item_t>,
00176 NULL, NULL, NULL, NULL, NULL, NULL,
00177 bdeserialize_string_type<ascii_item_t>,
00178 bdeserialize_string_type<jis8_item_t>,
00179 bdeserialize_string_type<wchar_item_t>,
00180 NULL, NULL, NULL, NULL, NULL,
00181 bdeserialize_simple_type<int64_item_t>,
00182 bdeserialize_simple_type<int8_item_t>,
00183 bdeserialize_simple_type<int16_item_t>,
00184 NULL,
00185 bdeserialize_simple_type<int32_item_t>,
00186 NULL, NULL, NULL,
00187 bdeserialize_simple_type<double_item_t>,
00188 NULL, NULL, NULL,
00189 bdeserialize_simple_type<float_item_t>,
00190 NULL, NULL, NULL,
00191 bdeserialize_simple_type<uint64_item_t>,
00192 bdeserialize_simple_type<uint8_item_t>,
00193 bdeserialize_simple_type<uint16_item_t>,
00194 NULL,
00195 bdeserialize_simple_type<uint32_item_t>
00196 };
00197
00198 if(e_list_t == _type)
00199 {
00200 plist = new list_item_t("");
00201 next = _sod;
00202 for(ix = 0; ix < _data_len; ++ix)
00203 {
00204 binary_deserializer_t d(next, _end);
00205 plist->_data.push_back(d(&next));
00206 }
00207 r = plist;
00208 }
00209 else
00210 {
00211 r = dfuncs[_type](_sod, _eod);
00212 next = _eod;
00213 }
00214
00215 if(next_item)
00216 {
00217 *next_item = next;
00218 }
00219 return r;
00220 }
00221
00222
00223 template<data_type_t type>
00224 void bserialize_simple_type(pdata_item_t pit,
00225 binary_serializer_t::data_container_t &raw_data_container)
00226 {
00227 msg_item_impl_t<type> *pimpl = (msg_item_impl_t<type>*)pit.get();
00228 size_t raw_data_size = pimpl->size();
00229 binary_serializer_t::data_container_t::value_type *data_begin =
00230 (binary_serializer_t::data_container_t::value_type *)&pimpl->container()[0];
00231 binary_serializer_t::data_container_t::value_type *data_end =
00232 (binary_serializer_t::data_container_t::value_type *)(data_begin) + raw_data_size;
00233
00234 raw_data_container.insert(raw_data_container.end(), data_begin, data_end);
00235 }
00236
00237 template<>
00238 void bserialize_simple_type<e_ascii_t>(pdata_item_t pit,
00239 binary_serializer_t::data_container_t &raw_data_container)
00240 {
00241 string_data_item_t<e_ascii_t> *pstr_item = (string_data_item_t<e_ascii_t>*)pit.get();
00242 size_t raw_data_size = pstr_item->size();
00243
00244 binary_serializer_t::data_container_t::value_type *data_begin =
00245 (binary_serializer_t::data_container_t::value_type *)pstr_item->_data.c_str();
00246 binary_serializer_t::data_container_t::value_type *data_end = data_begin + raw_data_size;
00247
00248 raw_data_container.insert(raw_data_container.end(), data_begin, data_end);
00249 }
00250
00251 template<>
00252 void bserialize_simple_type<e_wchar_t>(pdata_item_t pit,
00253 binary_serializer_t::data_container_t &raw_data_container)
00254 {
00255 string_data_item_t<e_wchar_t> *pstr_item = (string_data_item_t<e_wchar_t>*)pit.get();
00256 size_t raw_data_size = pstr_item->size();
00257 size_t in_strlen = raw_data_size;
00258 size_t out_strlen = in_strlen;
00259 size_t converted;
00260 const char *pstr = pstr_item->_data.c_str();
00261
00262 iconv_t icd = iconv_open("WCHAR_T", "UTF-8");
00263
00264 if(-1 == (int)icd)
00265 {
00266 throw;
00267 }
00268
00269 wchar_t *out_str = new wchar_t[out_strlen];
00270 wchar_t *out_ptr = out_str;
00271 memset(out_str, 0, out_strlen*sizeof(wchar_t));
00272
00273 while(out_strlen && in_strlen)
00274 {
00275 converted = iconv(icd, (char**)&pstr, &in_strlen, (char**)&out_ptr, &out_strlen);
00276
00277 if(-1 == (int)converted)
00278 {
00279 delete out_str;
00280 throw;
00281 }
00282 }
00283 iconv_close(icd);
00284
00285 size_t actual_size = wcslen(out_str)*sizeof(wchar_t);
00286
00287 binary_serializer_t::data_container_t::value_type *data_begin =
00288 (binary_serializer_t::data_container_t::value_type *)out_str;
00289 binary_serializer_t::data_container_t::value_type *data_end = (unsigned char*)&out_str[0] + actual_size;
00290
00291 raw_data_container.insert(raw_data_container.end(), data_begin, data_end);
00292 delete out_str;
00293 }
00294
00295 typedef void (*bserialize_fn)(pdata_item_t, binary_serializer_t::data_container_t&);
00296 static bserialize_fn sfuncs[e_none_t] =
00297 {
00298 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00299 bserialize_simple_type<e_binary_t>,
00300 bserialize_simple_type<e_boolean_t>,
00301 NULL, NULL, NULL, NULL, NULL, NULL,
00302 bserialize_simple_type<e_ascii_t>,
00303 bserialize_simple_type<e_wchar_t>,
00304 bserialize_simple_type<e_wchar_t>,
00305 NULL, NULL, NULL, NULL, NULL,
00306 bserialize_simple_type<e_int64_t>,
00307 bserialize_simple_type<e_int8_t>,
00308 bserialize_simple_type<e_int16_t>,
00309 NULL,
00310 bserialize_simple_type<e_int32_t>,
00311 NULL, NULL, NULL,
00312 bserialize_simple_type<e_double_t>,
00313 NULL, NULL, NULL,
00314 bserialize_simple_type<e_float_t>,
00315 NULL, NULL, NULL,
00316 bserialize_simple_type<e_uint64_t>,
00317 bserialize_simple_type<e_uint8_t>,
00318 bserialize_simple_type<e_uint16_t>,
00319 NULL,
00320 bserialize_simple_type<e_uint32_t>
00321 };
00322
00323 binary_serializer_t::binary_serializer_t(pdata_item_t pit)
00324 :_pitem(pit)
00325 {
00326 uint64_t len_bytes = pit->size();
00327 uint8_t num_len_bytes = 1 + (len_bytes & 0x0000ff00 ? 1 : 0)
00328 + (len_bytes & 0x00ff0000 ? 1 : 0)
00329 + (len_bytes & 0xff000000 ? 1 : 0);
00330
00331
00332 _raw_data.reserve(1 + num_len_bytes + pit->raw_size());
00333 _raw_data.resize(1 + num_len_bytes);
00334
00335 _raw_data[0] = 0;
00336 _raw_data[0] |= num_len_bytes & 0x3;
00337 _raw_data[0] |= (uint8_t)(pit->type() << 2) & 0xfc;
00338
00339 for(int i = 0; i < num_len_bytes; ++i)
00340 {
00341 _raw_data[i+1] = (uint8_t)((len_bytes >> (num_len_bytes - i - 1)) & 0xff);
00342 }
00343
00344 if(e_list_t == pit->type())
00345 {
00346 list_item_t *plist = (list_item_t*)pit.get();
00347 list_item_t::container_t::const_iterator it;
00348 for(it = plist->_data.begin(); it < plist->_data.end(); ++it)
00349 {
00350 binary_serializer_t bs(*it);
00351 _raw_data.insert(_raw_data.end(), bs.begin(), bs.end());
00352 }
00353 }
00354 else
00355 {
00356 sfuncs[pit->type()](pit, _raw_data);
00357 }
00358 }
00359
00360 binary_serializer_t::data_container_t::const_iterator
00361 binary_serializer_t::begin() const
00362 {
00363 return _raw_data.begin();
00364 }
00365
00366 binary_serializer_t::data_container_t::const_iterator
00367 binary_serializer_t::end() const
00368 {
00369 return _raw_data.end();
00370 }
00371
00372 binary_serializer_t::operator
00373 const binary_serializer_t::data_container_t&()
00374 {
00375
00376 return _raw_data;
00377 }
00378
00379 static const char *type2str[46] = {
00380 "list",
00381 NULL,
00382 NULL,
00383 NULL,
00384 NULL,
00385 NULL,
00386 NULL,
00387 NULL,
00388 "binary",
00389 "boolean",
00390 NULL,
00391 NULL,
00392 NULL,
00393 NULL,
00394 NULL,
00395 NULL,
00396 "ascii",
00397 "jis8",
00398 "unicode",
00399 NULL,
00400 NULL,
00401 NULL,
00402 NULL,
00403 NULL,
00404 "int64",
00405 "int8",
00406 "int16",
00407 NULL,
00408 "int32",
00409 NULL,
00410 NULL,
00411 NULL,
00412 "double",
00413 NULL,
00414 NULL,
00415 NULL,
00416 "float",
00417 NULL,
00418 NULL,
00419 NULL,
00420 "uint64",
00421 "uint8",
00422 "uint16",
00423 NULL,
00424 "uint32",
00425 "****none****"
00426 };
00427
00428 template<typename t>
00429 int xml_serialize_simple_type(pdata_item_t pit, xmlTextWriter* pwriter)
00430 {
00431 std::ostringstream os;
00432 t *p_impl = (t*)pit.get();
00433
00434 for(typename t::container_t::const_iterator it = p_impl->container().begin();
00435 it != p_impl->container().end(); ++it)
00436 {
00437 os << (typename t::print_t)*it;
00438
00439 if(it != p_impl->container().end()-1)
00440 {
00441 os << " ";
00442 }
00443 }
00444 os.flush();
00445
00446
00447 return xmlTextWriterWriteString(pwriter, XMLCHAR_CAST os.str().c_str());
00448 }
00449
00450 template<typename t>
00451 int xml_serialize_string_type(pdata_item_t pit, xmlTextWriter* pwriter)
00452 {
00453 int rc;
00454 t *str_item = (t*) pit.get();
00455
00456 xmlChar *xml_str = XMLCHAR_CAST str_item->_data.c_str();
00457
00458
00459 rc = xmlTextWriterWriteString(pwriter, xml_str);
00460
00461 return rc;
00462 }
00463
00464 typedef int (*xserialize_fn)(pdata_item_t, xmlTextWriter*);
00465
00466 static xserialize_fn xfuncs[e_none_t] =
00467 {
00468 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00469 xml_serialize_simple_type<binary_item_t>,
00470 xml_serialize_simple_type<bool_item_t>,
00471 NULL, NULL, NULL, NULL, NULL, NULL,
00472 xml_serialize_string_type<ascii_item_t>,
00473 xml_serialize_string_type<jis8_item_t>,
00474 xml_serialize_string_type<wchar_item_t>,
00475 NULL, NULL, NULL, NULL, NULL,
00476 xml_serialize_simple_type<int64_item_t>,
00477 xml_serialize_simple_type<int8_item_t>,
00478 xml_serialize_simple_type<int16_item_t>,
00479 NULL,
00480 xml_serialize_simple_type<int32_item_t>,
00481 NULL, NULL, NULL,
00482 xml_serialize_simple_type<double_item_t>,
00483 NULL, NULL, NULL,
00484 xml_serialize_simple_type<float_item_t>,
00485 NULL, NULL, NULL,
00486 xml_serialize_simple_type<uint64_item_t>,
00487 xml_serialize_simple_type<uint8_item_t>,
00488 xml_serialize_simple_type<uint16_item_t>,
00489 NULL,
00490 xml_serialize_simple_type<uint32_item_t>
00491 };
00492
00493 void
00494 xml_serializer_t::serialize(pdata_item_t pit, xmlTextWriter* pwriter)
00495 {
00496 int rc;
00497
00498 rc = xmlTextWriterStartElement(pwriter, XMLCHAR_CAST type2str[pit->type()]);
00499 ASSERT_THROW(rc < 0, "Error at xmlTextWriterStartElement\n");
00500
00501 if(pit->name() && strlen(pit->name()))
00502 {
00503 rc = xmlTextWriterWriteAttribute(pwriter, XMLCHAR_CAST "name", XMLCHAR_CAST pit->name());
00504 ASSERT_THROW(rc < 0, "Error at xmlWriterWriteAttribute\n");
00505 }
00506
00507 if(e_list_t == pit->type())
00508 {
00509 list_item_t *plist= (list_item_t*)pit.get();
00510 msg_item_impl_t<e_list_t>::container_t::const_iterator it;
00511
00512 if(plist->variable())
00513 {
00514 rc = xmlTextWriterWriteAttribute(pwriter, XMLCHAR_CAST "variable", XMLCHAR_CAST "true");
00515 ASSERT_THROW(rc < 0, "Error at xmlWriterWriteAttribute\n");
00516 }
00517
00518 for(it = plist->_data.begin(); it < plist->_data.end(); ++it)
00519 {
00520 xml_serializer_t xs(*it, pwriter);
00521 }
00522 }
00523 else
00524 {
00525 xfuncs[pit->type()](pit, pwriter);
00526 }
00527
00528 rc = xmlTextWriterEndElement(pwriter);
00529 ASSERT_THROW(rc < 0, "Error at xmlTextWriterEndElement\n");
00530 }
00531
00532 void
00533 xml_serializer_t::serialize(pmsg_t pmsg, xmlTextWriter* pwriter)
00534 {
00535 int rc;
00536 char buf[256];
00537 xmlChar *xml_str = XMLCHAR_CAST pmsg->name.c_str();
00538
00539 rc = xmlTextWriterStartElement(pwriter, XMLCHAR_CAST "secsIImsg");
00540 ASSERT_THROW(rc < 0, "Error at xmlTextWriterStartElement\n");
00541
00542 rc = xmlTextWriterWriteAttribute(pwriter, XMLCHAR_CAST "name", xml_str);
00543 ASSERT_THROW(rc < 0, "Error at xmlWriterWriteAttribute\n");
00544
00545 snprintf(buf, sizeof(buf), "%u", pmsg->sysbytes);
00546
00547 xml_str = XMLCHAR_CAST buf;
00548
00549 rc = xmlTextWriterWriteAttribute(pwriter, XMLCHAR_CAST "sysbytes", xml_str);
00550 ASSERT_THROW(rc < 0, "Error at xmlWriterWriteAttribute\n");
00551
00552
00553 rc = xmlTextWriterStartElement(pwriter, XMLCHAR_CAST "stream");
00554 ASSERT_THROW(rc < 0, "Error at xmlTextWriterStartElement\n");
00555
00556 snprintf(buf, sizeof(buf), "%u", pmsg->stream);
00557
00558 rc = xmlTextWriterWriteString(pwriter, XMLCHAR_CAST buf);
00559 ASSERT_THROW(rc < 0, "Error at xmlTextWriterWriteFormatString\n");
00560 rc = xmlTextWriterEndElement(pwriter);
00561 ASSERT_THROW(rc < 0, "Error at xmlTextWriterEndElement\n");
00562
00563
00564
00565 rc = xmlTextWriterStartElement(pwriter, XMLCHAR_CAST "function");
00566 ASSERT_THROW(rc < 0, "Error at xmlTextWriterStartElement\n");
00567
00568 snprintf(buf, sizeof(buf), "%u", pmsg->function);
00569
00570 rc = xmlTextWriterWriteString(pwriter, XMLCHAR_CAST buf);
00571 ASSERT_THROW(rc < 0, "Error at xmlTextWriterWriteFormatString\n");
00572 rc = xmlTextWriterEndElement(pwriter);
00573 ASSERT_THROW(rc < 0, "Error at xmlTextWriterEndElement\n");
00574
00575
00576
00577 rc = xmlTextWriterStartElement(pwriter, XMLCHAR_CAST "wbit");
00578 ASSERT_THROW(rc < 0, "Error at xmlTextWriterStartElement\n");
00579
00580
00581 rc = xmlTextWriterWriteString(pwriter, XMLCHAR_CAST (pmsg->wbit ? "true" : "false"));
00582 ASSERT_THROW(rc < 0, "Error at xmlTextWriterWriteFormatString\n");
00583 rc = xmlTextWriterEndElement(pwriter);
00584 ASSERT_THROW(rc < 0, "Error at xmlTextWriterEndElement\n");
00585
00586
00587 serialize(pmsg->_pitem, pwriter);
00588
00589 rc = xmlTextWriterEndElement(pwriter);
00590 ASSERT_THROW(rc < 0, "Error at xmlTextWriterEndElement\n");
00591
00592 }
00593
00594 xml_serializer_t::xml_serializer_t(pdata_item_t pit, xmlTextWriter* pwriter)
00595 {
00596 serialize(pit, pwriter);
00597 }
00598
00599 xml_serializer_t::xml_serializer_t(pmsg_t pmsg, xmlTextWriter* pwriter)
00600 {
00601 serialize(pmsg, pwriter);
00602 }
00603
00604 xml_serializer_t::xml_serializer_t(pdata_item_t pit)
00605 {
00606 int rc;
00607 xmlTextWriter *pwriter;
00608 xmlDoc *pdoc;
00609 xmlBuffer *pbuf;
00610 xmlSaveCtxt *psave_ctx;
00611
00612 pwriter = xmlNewTextWriterDoc(&pdoc, 0);
00613 ASSERT_THROW(NULL == pwriter, "Error at xmlNewTextWriterDoc\n");
00614
00615 rc = xmlTextWriterStartDocument(pwriter, NULL, ENCODING, NULL);
00616 ASSERT_THROW(rc, "Error at xmlTextWriterStartDocument\n");
00617
00618 serialize(pit, pwriter);
00619
00620 rc = xmlTextWriterEndDocument(pwriter);
00621 ASSERT_THROW(0 >= rc, "Error at xmlTextWriterEndDocument: %d\n", rc);
00622
00623 pbuf = xmlBufferCreate();
00624 ASSERT_THROW(0 == pbuf, "Error at xmlBufferCreate\n");
00625
00626 psave_ctx = xmlSaveToBuffer(pbuf, ENCODING, XML_SAVE_FORMAT | XML_SAVE_NO_EMPTY | XML_SAVE_NO_DECL);
00627 ASSERT_THROW(NULL == psave_ctx, "Error at xmlSaveToBuffer\n");
00628
00629 rc = xmlSaveDoc(psave_ctx, pdoc);
00630 ASSERT_THROW(0 > rc, "Error at xmlSaveDoc: %d\n", rc);
00631
00632 rc = xmlSaveClose(psave_ctx);
00633 ASSERT_THROW(0 >= rc, "Error at xmlSaveClose: %d\n", rc);
00634
00635 _raw_data = data_container_t((const char*)xmlBufferContent(pbuf), xmlBufferLength(pbuf));
00636
00637 xmlBufferFree(pbuf);
00638
00639 xmlFreeTextWriter(pwriter);
00640 xmlFreeDoc(pdoc);
00641 }
00642 xml_serializer_t::xml_serializer_t(pmsg_t pmsg)
00643 {
00644 int rc;
00645 xmlTextWriter *pwriter;
00646 xmlDoc *pdoc;
00647 xmlBuffer *pbuf;
00648 xmlSaveCtxt *psave_ctx;
00649
00650 pwriter = xmlNewTextWriterDoc(&pdoc, 0);
00651 ASSERT_THROW(NULL == pwriter, "Error at xmlNewTextWriterDoc\n");
00652
00653 rc = xmlTextWriterStartDocument(pwriter, NULL, ENCODING, NULL);
00654 ASSERT_THROW(rc, "Error at xmlTextWriterStartDocument\n");
00655
00656 serialize(pmsg, pwriter);
00657
00658 rc = xmlTextWriterEndDocument(pwriter);
00659 ASSERT_THROW(0 >= rc, "Error at xmlTextWriterEndDocument: %d\n", rc);
00660
00661 pbuf = xmlBufferCreate();
00662 ASSERT_THROW(0 == pbuf, "Error at xmlBufferCreate\n");
00663
00664 psave_ctx = xmlSaveToBuffer(pbuf, ENCODING, XML_SAVE_FORMAT | XML_SAVE_NO_EMPTY | XML_SAVE_NO_DECL);
00665 ASSERT_THROW(NULL == psave_ctx, "Error at xmlSaveToBuffer\n");
00666
00667 rc = xmlSaveDoc(psave_ctx, pdoc);
00668 ASSERT_THROW(0 > rc, "Error at xmlSaveDoc: %d\n", rc);
00669
00670 rc = xmlSaveClose(psave_ctx);
00671 ASSERT_THROW(0 >= rc, "Error at xmlSaveClose: %d\n", rc);
00672
00673
00674 _raw_data = data_container_t((const char*)xmlBufferContent(pbuf), xmlBufferLength(pbuf));
00675
00676
00677 xmlBufferFree(pbuf);
00678 xmlFreeTextWriter(pwriter);
00679
00680 xmlFreeDoc(pdoc);
00681 }
00682 xml_serializer_t::~xml_serializer_t()
00683 {
00684 }
00685 const char *
00686 xml_serializer_t::get()
00687 {
00688 return _raw_data.c_str();
00689 }
00690
00691 int
00692 xml_serializer_t::save_to(xmlSaveCtxt *psave_ctx, const xml_serializer_t::msg_container_t &msg_container)
00693 {
00694 int rc;
00695 xmlTextWriter *pwriter;
00696 xmlDoc *pdoc;
00697
00698 pwriter = xmlNewTextWriterDoc(&pdoc, 0);
00699 ASSERT_THROW(NULL == pwriter, "Error at xmlNewTextWriterDoc\n");
00700
00701 rc = xmlTextWriterStartDocument(pwriter, NULL, ENCODING, "yes");
00702 ASSERT_THROW(rc, "Error at xmlTextWriterStartDocument\n");
00703
00704 rc = xmlTextWriterStartElement(pwriter, XMLCHAR_CAST "messages");
00705 ASSERT_THROW(rc < 0, "Error at xmlTextWriterStartElement\n");
00706
00707 for(std::vector<pmsg_t>::const_iterator it = msg_container.begin(); it != msg_container.end(); ++it)
00708 {
00709 xml_serializer_t(*it, pwriter);
00710 }
00711
00712 rc = xmlTextWriterEndElement(pwriter);
00713 ASSERT_THROW(rc < 0, "Error at xmlTextWriterEndElement\n");
00714
00715 rc = xmlTextWriterEndDocument(pwriter);
00716 ASSERT_THROW(0 >= rc, "Error at xmlTextWriterEndDocument: %d\n", rc);
00717
00718 rc = xmlSaveDoc(psave_ctx, pdoc);
00719 ASSERT_THROW(0 > rc, "Error at xmlSaveDoc: %d\n", rc);
00720
00721 rc = xmlSaveClose(psave_ctx);
00722 ASSERT_THROW(0 >= rc, "Error at xmlSaveClose: %d\n", rc);
00723
00724 xmlFreeTextWriter(pwriter);
00725 xmlFreeDoc(pdoc);
00726
00727 return 0;
00728 }
00729
00730
00731 int
00732 xml_serializer_t::to_file(int fd, const msg_container_t &msg_container)
00733 {
00734 xmlSaveCtxt *psave_ctx = xmlSaveToFd(fd, ENCODING, XML_SAVE_FORMAT | XML_SAVE_NO_EMPTY );
00735 ASSERT_RETURN(NULL == psave_ctx, "Error at xmlSaveToFd(%d)\n", fd);
00736
00737 return save_to(psave_ctx, msg_container);
00738 }
00739
00740 int
00741 xml_serializer_t::to_mem(data_container_t &container, const msg_container_t &msg_container)
00742 {
00743 int rc =0;
00744
00745 xmlBufferPtr pbuf = xmlBufferCreate();
00746 ASSERT_THROW(0 == pbuf, "Error at xmlBufferCreate\n");
00747
00748 xmlSaveCtxtPtr psave_ctx = xmlSaveToBuffer(pbuf, ENCODING, XML_SAVE_FORMAT | XML_SAVE_NO_EMPTY | XML_SAVE_NO_DECL);
00749 ASSERT_THROW(NULL == psave_ctx, "Error at xmlSaveToBuffer\n");
00750
00751 rc = save_to(psave_ctx, msg_container);
00752
00753 if(!rc)
00754 {
00755 size_t buflen = xmlBufferLength(pbuf);
00756 char *pmem = new char[buflen];
00757 memcpy(pmem, xmlBufferContent(pbuf), buflen);
00758 pmem[buflen-1] = '\0';
00759 container = pmem;
00760 delete[] pmem;
00761 }
00762
00763 xmlBufferFree(pbuf);
00764
00765 return rc;
00766 }
00767
00768 template <data_type_t t, typename pub_t, pub_t convert_fn(const char*)>
00769 static int string_deserialize(xmlNode *pnode, typename type_selector<t>::container_type& cont)
00770 {
00771 const char *str;
00772 std::string word;
00773
00774 if(XML_TEXT_NODE != pnode->children->type ||
00775 !(str = (const char*)pnode->children->content))
00776 {
00777 return -1;
00778 }
00779
00780 std::istringstream is(str, std::istringstream::in);
00781
00782 while(is >> word)
00783 {
00784 cont.push_back((typename type_selector<t>::data_type)convert_fn(word.c_str()));
00785 }
00786
00787 return 0;
00788 }
00789
00790 template <data_type_t t>
00791 static int
00792 ulonglong_string_deserialize(xmlNode *pnode, typename type_selector<t>::container_type& cont)
00793 {
00794 const char *str;
00795 std::string word;
00796
00797 if(XML_TEXT_NODE != pnode->children->type ||
00798 !(str = (const char*)pnode->children->content))
00799 {
00800 return -1;
00801 }
00802
00803 std::istringstream is(str, std::istringstream::in);
00804
00805 while(is >> word)
00806 {
00807 cont.push_back((typename type_selector<t>::data_type)strtoull(word.c_str(), NULL, 0));
00808 }
00809
00810 return 0;
00811
00812 }
00813
00814 xml_deserializer_t::xml_deserializer_t(xmlNode *pnode)
00815 :_pitem(NULL),_pmsg(NULL)
00816 {
00817 const char *pname="";
00818 const char *ptype;
00819
00820 if(NULL == pnode)
00821 {
00822 throw 1;
00823 }
00824
00825 if(XML_ELEMENT_NODE != pnode->type)
00826 {
00827 throw 1;
00828 }
00829
00830 if(NULL != xmlHasProp(pnode, XMLCHAR_CAST "name"))
00831 {
00832 pname = (const char*)xmlGetProp(pnode, XMLCHAR_CAST "name");
00833 }
00834
00835 ptype = (const char*)pnode->name;
00836
00837 if(0 == strcmp("secsIImsg",ptype))
00838 {
00839 uint8_t stream, function;
00840 bool wbit;
00841 uint32_t sysbytes;
00842 pdata_item_t pitem;
00843
00844 if(NULL != xmlHasProp(pnode, XMLCHAR_CAST "sysbytes"))
00845 {
00846 char *str_sysbytes = (char*)xmlGetProp(pnode, XMLCHAR_CAST "sysbytes");
00847 sysbytes = atoi(str_sysbytes);
00848 xmlFree(str_sysbytes);
00849 }
00850 else
00851 {
00852 sysbytes = 0;
00853 }
00854
00855 xmlNode *curr_node = move_to_next(pnode->children);
00856 if(!curr_node) throw 1;
00857
00858 ptype = (const char*)curr_node->name;
00859
00860 if(0 == strcmp("stream", ptype))
00861 {
00862 stream = (uint8_t)atoi((const char*)curr_node->children->content);
00863 }
00864 else throw 1;
00865
00866 curr_node = move_to_next(curr_node->next);
00867 if(!curr_node) throw 1;
00868
00869 ptype = (const char*)curr_node->name;
00870
00871 if(0 == strcmp("function", ptype))
00872 {
00873 function = (uint8_t)atoi((const char*)curr_node->children->content);
00874 }
00875 else throw 1;
00876
00877 curr_node = move_to_next(curr_node->next);
00878 if(!curr_node) throw 1;
00879
00880 ptype = (const char*)curr_node->name;
00881
00882 if(0 == strcmp("wbit", ptype))
00883 {
00884 wbit = (bool)atoi((const char*)curr_node->children->content);
00885 curr_node = move_to_next(curr_node->next);
00886 }
00887 else
00888 {
00889 wbit =0;
00890 }
00891
00892 if(!curr_node) throw 1;
00893
00894 ptype = (const char*)curr_node->name;
00895
00896 bool known_type = false;
00897 for(unsigned i = 0; i < sizeof(type2str)/sizeof(type2str[0]) && !known_type; ++i)
00898 {
00899 if(0 == strcmp(type2str[i], ptype))
00900 {
00901 known_type = true;
00902 }
00903 }
00904
00905 if(!known_type) throw 1;
00906
00907 pitem = xml_deserializer_t(curr_node);
00908
00909 _pmsg = new msg_t(pname, stream, function);
00910 _pmsg->wbit = wbit;
00911 _pmsg->sysbytes = sysbytes;
00912 _pmsg->_pitem = pitem;
00913 }
00914 else
00915 {
00916 if(0 == strcmp("binary", ptype))
00917 {
00918 binary_item_t *pbin = new binary_item_t(pname);
00919 string_deserialize<e_binary_t, int, atoi>(pnode, pbin->_data);
00920 _pitem = (data_item_t*) pbin;
00921 }
00922 else if(0 == strcmp("boolean", ptype))
00923 {
00924 bool_item_t *pbool = new bool_item_t(pname);
00925 string_deserialize<e_boolean_t, int, atoi>(pnode, pbool->_data);
00926 _pitem = (data_item_t*) pbool;
00927 }
00928 else if(0 == strcmp("ascii", ptype))
00929 {
00930 ascii_item_t *pascii = new ascii_item_t(pname);
00931 if(pnode->children)
00932 {
00933 if(XML_TEXT_NODE == pnode->children->type)
00934 {
00935 pascii->_data = (const char*)pnode->children->content;
00936 }
00937 }
00938 _pitem = (data_item_t*) pascii;
00939 }
00940 else if(0 == strcmp("jis8", ptype))
00941 {
00942 jis8_item_t *pjis8 = new jis8_item_t(pname);
00943 pjis8->_data = (jis8_item_t::data_t*)pnode->children->content;
00944 _pitem = (data_item_t*)pjis8;
00945 }
00946 else if(0 == strcmp("unicode", ptype))
00947 {
00948 wchar_item_t *pwchar = new wchar_item_t(pname);
00949 pwchar->_data = (wchar_item_t::data_t*)pnode->children->content;
00950 _pitem = (data_item_t*)pwchar;
00951 }
00952 else if(0 == strcmp("int64", ptype))
00953 {
00954 int64_item_t *pint64 = new int64_item_t(pname);
00955 string_deserialize<e_int64_t, long long, atoll>(pnode, pint64->_data);
00956 _pitem = (data_item_t*) pint64;
00957 }
00958 else if(0 == strcmp("int8", ptype))
00959 {
00960 int8_item_t *pint8 = new int8_item_t(pname);
00961 string_deserialize<e_int8_t, int, atoi>(pnode, pint8->_data);
00962 _pitem = (data_item_t*) pint8;
00963 }
00964 else if(0 == strcmp("int16", ptype))
00965 {
00966 int16_item_t *pint16 = new int16_item_t(pname);
00967 string_deserialize<e_int16_t, int, atoi>(pnode, pint16->_data);
00968 _pitem = (data_item_t*) pint16;
00969 }
00970 else if(0 == strcmp("int32", ptype))
00971 {
00972 int32_item_t *pint32 = new int32_item_t(pname);
00973 string_deserialize<e_int32_t, int, atoi>(pnode, pint32->_data);
00974 _pitem = (data_item_t*) pint32;
00975 }
00976 else if(0 == strcmp("double", ptype))
00977 {
00978 double_item_t *pdbl = new double_item_t(pname);
00979 string_deserialize<e_double_t, double, atof>(pnode, pdbl->_data);
00980 _pitem = (data_item_t*) pdbl;
00981 }
00982 else if(0 == strcmp("float", ptype))
00983 {
00984 float_item_t *pflt = new float_item_t(pname);
00985 string_deserialize<e_float_t, double, atof>(pnode, pflt->_data);
00986 _pitem = (data_item_t*) pflt;
00987 }
00988 else if(0 == strcmp("uint64", ptype))
00989 {
00990 uint64_item_t *puint64 = new uint64_item_t(pname);
00991
00992 ulonglong_string_deserialize<e_uint64_t>(pnode, puint64->_data);
00993 _pitem = (data_item_t*) puint64;
00994 }
00995 else if(0 == strcmp("uint8", ptype))
00996 {
00997 uint8_item_t *puint8 = new uint8_item_t(pname);
00998 string_deserialize<e_uint8_t, int, atoi>(pnode, puint8->_data);
00999 _pitem = (data_item_t*) puint8;
01000 }
01001 else if(0 == strcmp("uint16", ptype))
01002 {
01003 uint16_item_t *puint16 = new uint16_item_t(pname);
01004 string_deserialize<e_uint16_t, int, atoi>(pnode, puint16->_data);
01005 _pitem = (data_item_t*) puint16;
01006 }
01007 else if(0 == strcmp("uint32", ptype))
01008 {
01009 uint32_item_t *puint32 = new uint32_item_t(pname);
01010
01011 ulonglong_string_deserialize<e_uint32_t>(pnode, puint32->_data);
01012 _pitem = (data_item_t*) puint32;
01013 }
01014 else if(0 == strcmp("list", ptype))
01015 {
01016 bool variable = false;
01017 if(NULL != xmlHasProp(pnode, XMLCHAR_CAST "variable"))
01018 {
01019 char *str_variable = NULL;
01020
01021 str_variable = (char*)xmlGetProp(pnode, XMLCHAR_CAST "variable");
01022
01023 if(0 == strcmp("true", str_variable))
01024 variable = true;
01025
01026 xmlFree(str_variable);
01027 }
01028
01029 list_item_t *plist = variable ? new var_list_item_t(pname) : new list_item_t(pname);
01030
01031 for(xmlNode *curr_node = pnode->children; curr_node; curr_node = curr_node->next)
01032 {
01033 try
01034 {
01035 pdata_item_t pit = xml_deserializer_t(curr_node);
01036
01037 if(plist->variable() && 0 == plist->size())
01038 {
01039 ((var_list_item_t*)plist)->_template = pit->clone();
01040 }
01041
01042 plist->_data.push_back(pit);
01043 }
01044 catch(...)
01045 {
01046 continue;
01047 }
01048 }
01049 _pitem = (data_item_t*)plist;
01050 }
01051 }
01052 if(pname && strlen(pname))xmlFree((void*)pname);
01053 }
01054
01055 xml_deserializer_t::operator const pdata_item_t&()
01056 {
01057 return _pitem;
01058 }
01059
01060 xml_deserializer_t::operator const pmsg_t&()
01061 {
01062 return _pmsg;
01063 }
01064
01065 int
01066 xml_deserializer_t::read_from(xmlDoc *pdoc, xmlDoc *pschema_doc, msg_container_t &msg_container)
01067 {
01068 int err = 0;
01069 xmlSchemaParserCtxtPtr ctxt = NULL;
01070 xmlSchemaPtr schema = NULL;
01071 xmlSchemaValidCtxtPtr validator = NULL;
01072
01073 if(pschema_doc)
01074 {
01075 ctxt = xmlSchemaNewDocParserCtxt(pschema_doc);
01076 if(!ctxt) err = -2;
01077
01078 schema = xmlSchemaParse(ctxt);
01079 if(!schema) err = -3;
01080
01081 validator = xmlSchemaNewValidCtxt(schema);
01082 if(!validator) err = -4;
01083
01084 if(xmlSchemaValidateDoc(validator, pdoc)) err = -5;
01085
01086
01087 if(err)
01088 {
01089 if(validator) xmlSchemaFreeValidCtxt(validator);
01090 if(schema) xmlSchemaFree(schema);
01091 if(ctxt) xmlSchemaFreeParserCtxt(ctxt);
01092
01093 return err;
01094 }
01095 }
01096
01097 err = 0;
01098
01099 xmlNode *pnode = xmlDocGetRootElement(pdoc);
01100
01101 while(!err && pnode)
01102 {
01103 if(XML_ELEMENT_NODE == pnode->type)
01104 {
01105 const char *ptype = (const char*)pnode->name;
01106 if(0 ==strcmp("messages", ptype))
01107 {
01108
01109 pnode = pnode->children;
01110 while(pnode)
01111 {
01112 try
01113 {
01114 xml_deserializer_t ds(pnode);
01115 msg_container.push_back(ds);
01116 }
01117 catch(...)
01118 {
01119 err = -6;
01120 break;
01121 }
01122 pnode = pnode->next;
01123 }
01124 }
01125 }
01126 else
01127 pnode = pnode->next;
01128 }
01129
01130 if(validator) xmlSchemaFreeValidCtxt(validator);
01131 if(schema) xmlSchemaFree(schema);
01132 if(ctxt) xmlSchemaFreeParserCtxt(ctxt);
01133
01134 return err;
01135 }
01136
01137 int
01138 xml_deserializer_t::from_file(int fd, int schema_fd, msg_container_t &msg_container)
01139 {
01140 int err = 0;
01141 xmlDocPtr doc = NULL, schema_doc = NULL;
01142
01143 doc = xmlReadFd(fd, NULL, ENCODING, XML_PARSE_NOBLANKS | XML_PARSE_COMPACT);
01144
01145 if(0 < schema_fd)
01146 {
01147 schema_doc = xmlReadFd(schema_fd, NULL, ENCODING, XML_PARSE_NOBLANKS | XML_PARSE_COMPACT);
01148 if(!schema_doc) err = -1;
01149 }
01150
01151 err = read_from(doc, schema_doc, msg_container);
01152
01153 if(schema_doc) xmlFreeDoc(schema_doc);
01154 if(doc) xmlFreeDoc(doc);
01155
01156 return err;
01157 }
01158
01159 int
01160 xml_deserializer_t::from_mem(void *buf, size_t buflen, void *schema_buf, size_t schema_buflen, msg_container_t &msg_container)
01161 {
01162 int err = 0;
01163 xmlDocPtr doc = NULL, schema_doc = NULL;
01164
01165 doc = xmlReadMemory((const char*)buf, buflen, NULL, ENCODING, XML_PARSE_NOBLANKS | XML_PARSE_COMPACT);
01166
01167 if(!doc) return -1;
01168
01169 if(NULL != schema_buf && 0 < schema_buflen)
01170 {
01171 schema_doc = xmlReadMemory((const char*)schema_buf, schema_buflen, NULL, ENCODING, XML_PARSE_NOBLANKS | XML_PARSE_COMPACT);
01172
01173 if(!schema_doc) return -2;
01174 }
01175
01176 err = read_from(doc, schema_doc, msg_container);
01177
01178 if(doc) xmlFreeDoc(doc);
01179 if(schema_doc) xmlFreeDoc(schema_doc);
01180
01181 return err;
01182 }