DocumentModel.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:24k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. #include "VXMLDocumentRep.hpp"
  23. #include "VXMLDocument.hpp"
  24. #include <sstream>                     // by CreateHiddenVariable()
  25. #include <list>                        // by VXMLElementRef
  26. #include <iostream>
  27. //#############################################################################
  28. // One mutex is shared across all the VXMLNodes.  The small performance
  29. // reduction is offset by the large number of mutexes which would be otherwise
  30. // created.
  31. #include "InternalMutex.hpp"                    // by VXMLNodeRef
  32. static InternalMutex * mutex = NULL;
  33. // To avoid race condition for reference count of VXMLDocumentRep
  34. // object, we need to store the object address. The object is valid
  35. // as long as its address is present in the list.  This is protected
  36. // by global mutex
  37. typedef std::list<VXMLDocumentRep*> DOCREPLIST;
  38. static DOCREPLIST gblDocRep = DOCREPLIST();
  39. static InternalMutex * gblDocRepMutex = NULL;
  40. bool VXMLDocumentModel::Initialize()
  41. {
  42.   gblDocRepMutex = new InternalMutex();
  43.   mutex = new InternalMutex();
  44.   gblDocRep.clear();
  45.   return !(mutex == NULL || mutex->IsBad());
  46. }
  47. void VXMLDocumentModel::Deinitialize()
  48. {
  49.   if (mutex != NULL) delete mutex;
  50.   if (gblDocRepMutex != NULL) delete gblDocRepMutex;
  51.   gblDocRepMutex = NULL;
  52.   mutex = NULL;
  53. }
  54. //#############################################################################
  55. static const VXIchar * const HIDDEN_VAR_PREFIX   = L"$_internalName_";
  56. // The cautious reader will notice that this routine is not thread safe.  This
  57. // perfectly acceptible.  We don't really care what the numbers are so long
  58. // as they keep incrementing.
  59. //
  60. // The 'dangerous' line is indicated with the asterisk.  A context switch
  61. // would need to happen between the comparison and the assignment but only when
  62. // the threshold is exceeded.  Even on those architectures which permit this
  63. // context switch, the risk is near zero.
  64. //
  65. void VXMLDocumentModel::CreateHiddenVariable(vxistring & v)
  66. {
  67.   static long internalCount = 31415;
  68.   long count = 0;
  69.   
  70.   // Need to lock because multiple channels using the same var.
  71.   mutex->Lock();
  72.   // Increment counter or reset if necessary (LONG_MAX must be larger).
  73.   count = ++internalCount;
  74.   if (internalCount > 2141234567) internalCount = 271828;  // *
  75.   mutex->Unlock();
  76.   
  77.   std::basic_stringstream<VXIchar> name;
  78.   name << HIDDEN_VAR_PREFIX << count;
  79.   v = name.str();
  80. }
  81. // As long as HIDDEN_VAR_PREFIX is sufficiently obscure, this should be good
  82. // enough.
  83. bool VXMLDocumentModel::IsHiddenVariable(const vxistring & v)
  84. {
  85.   return (v.find(HIDDEN_VAR_PREFIX) == 0);
  86. }
  87. //#############################################################################
  88. // This defines the reference counted data for VXMLNodes.
  89. class VXMLNodeRef {
  90. public:
  91.   const VXMLNodeRef * GetParent() const         { return parent; }
  92.   VXMLNode::VXMLNodeType GetType() const        { return type; }
  93.   virtual ~VXMLNodeRef() { }
  94. protected:
  95.   VXMLNodeRef(const VXMLNodeRef * p, VXMLNode::VXMLNodeType t)
  96.     : parent(p), type(t) { }
  97.   const VXMLNodeRef * parent;
  98.   VXMLNode::VXMLNodeType type;
  99. };
  100. //#############################################################################
  101. // Content nodes are simple - they consist of a block of data.
  102. class VXMLContentRef : public VXMLNodeRef {
  103. public:
  104.   vxistring data;
  105.   VXIulong ssmlHeaderLen;
  106.       
  107.   VXMLContentRef(const VXMLNodeRef * p)
  108.     : VXMLNodeRef(p, VXMLNode::Type_VXMLContent), ssmlHeaderLen(0) { }
  109.   virtual ~VXMLContentRef() { }
  110. };
  111. //#############################################################################
  112. class VXMLElementRef : public VXMLNodeRef {
  113. public:
  114.   class VXMLElementAttribute {
  115.   public:
  116.     VXMLAttributeType key;
  117.     vxistring value;
  118.     VXMLElementAttribute() { }
  119.     VXMLElementAttribute(VXMLAttributeType k, const vxistring & attr)
  120.       : key(k), value(attr) { }
  121.   };
  122.   typedef std::list<VXMLNodeRef *> CHILDREN;
  123.   typedef std::list<VXMLElementAttribute> ATTRIBUTES;
  124.   VXMLElementType name;
  125.   ATTRIBUTES attributes;
  126.   CHILDREN   children;
  127.   DocumentLevel docLevel;
  128.   
  129.   DocumentLevel GetDocumentLevel() const { return docLevel; }
  130.   bool GetAttribute(VXMLAttributeType key, vxistring & attr) const;
  131.   VXMLElementRef(const VXMLNodeRef * p, VXMLElementType n, DocumentLevel dlevel)
  132.     : VXMLNodeRef(p, VXMLNode::Type_VXMLElement), name(n), docLevel(dlevel) { }
  133.   virtual ~VXMLElementRef() {
  134.     for (CHILDREN::iterator i = children.begin(); i != children.end(); ++i)
  135.       delete (*i);
  136.   }
  137. };
  138. bool VXMLElementRef::GetAttribute(VXMLAttributeType key,
  139.                                   vxistring & attr) const
  140. {
  141.   ATTRIBUTES::const_iterator i;
  142.   for (i = attributes.begin(); i != attributes.end(); ++i) {
  143.     if ((*i).key == key) {
  144.       attr = (*i).value;
  145.       return true;
  146.     }
  147.   }
  148.   attr.erase();
  149.   return false;
  150. }
  151. //#############################################################################
  152. class VXMLNodeIteratorData {
  153. public:
  154.   const VXMLElementRef & ref;
  155.   VXMLElementRef::CHILDREN::const_iterator i;
  156.   VXMLNodeIteratorData(const VXMLElementRef & r) : ref(r)
  157.     { i = ref.children.begin(); }
  158. };
  159. VXMLNodeIterator::VXMLNodeIterator(const VXMLNode & n) : data(NULL)
  160. {
  161.   if (n.internals == NULL ||
  162.       n.internals->GetType() != VXMLNode::Type_VXMLElement)  return;
  163.   
  164.   const VXMLElementRef * tmp = static_cast<const VXMLElementRef*>(n.internals);
  165.   data = new VXMLNodeIteratorData(*tmp);
  166. }
  167. VXMLNodeIterator::~VXMLNodeIterator()
  168. {
  169.   if (data != NULL) delete data;
  170. }
  171. void VXMLNodeIterator::operator++()
  172. {
  173.   if (data != NULL) ++data->i;
  174. }
  175. void VXMLNodeIterator::reset()
  176. {
  177.   if (data != NULL) data->i = data->ref.children.begin();
  178. }
  179. VXMLNode VXMLNodeIterator::operator*() const
  180. {
  181.   if (data == NULL) return VXMLNode();
  182.   return *(data->i);
  183. }
  184. VXMLNodeIterator::operator const void *() const
  185. {
  186.   if (data == NULL || data->i == data->ref.children.end()) return NULL;
  187.   return reinterpret_cast<void *>(1);
  188. }
  189. //#############################################################################
  190. bool VXMLDocumentRep::IsValidDocRep(VXMLDocumentRep * t )
  191. {
  192.   bool rc = false;
  193.   gblDocRepMutex->Lock();
  194.   if( !gblDocRep.empty() && t != NULL ) {
  195.     for( DOCREPLIST::iterator i = gblDocRep.begin();
  196.        i != gblDocRep.end(); ++i)
  197.     {
  198.       if( (*i) == t ) {
  199.         rc = true;
  200.         break;
  201.       }
  202.     }
  203.   }
  204.   gblDocRepMutex->Unlock();
  205.   return rc;
  206. }
  207. void VXMLDocumentRep::IfValidRemoveDocRep(VXMLDocumentRep * t )
  208. {
  209.   // Note: Must already protected by the global mutex
  210.   gblDocRepMutex->Lock();
  211.   if( !gblDocRep.empty() && t != NULL ) {
  212.     for( DOCREPLIST::iterator i = gblDocRep.begin();
  213.          i != gblDocRep.end(); ++i)
  214.     {
  215.       if( (*i) == t ) {
  216.         gblDocRep.erase(i);
  217.         break;
  218.       }
  219.     }
  220.   }
  221.   gblDocRepMutex->Unlock();
  222. }
  223. bool VXMLDocumentRep::AddRefAtomic(VXMLDocumentRep * t)
  224. {
  225.   if( IsValidDocRep(t) ) {
  226.     ++t->count;    
  227.     return true;
  228.   }
  229.   return false;
  230. }
  231. bool VXMLDocumentRep::AddRef(VXMLDocumentRep * t)
  232. {
  233.   mutex->Lock();
  234.   bool valid = AddRefAtomic(t);
  235.   mutex->Unlock();
  236.   return valid;
  237. }
  238. bool VXMLDocumentRep::ReleaseAtomic(VXMLDocumentRep * & t)
  239. {
  240.   bool rc = false;
  241.   if( IsValidDocRep(t) ) {
  242.     // Note: when the document is deleted, its address
  243.     // also is removed from the global list.  This is important
  244.     // to avoid race condition when one thread is wait to addRef()
  245.     // while the last refCount is found by the other thread
  246.     if(--t->count == 0 )
  247.       delete t;  
  248.     rc = true;
  249.   }
  250.   t = NULL;
  251.   return rc;
  252. }
  253. bool VXMLDocumentRep::Release(VXMLDocumentRep * & t)
  254. {
  255.   mutex->Lock();
  256.   bool valid = ReleaseAtomic(t);
  257.   mutex->Unlock();
  258.   return valid;
  259. }
  260. VXMLDocumentRep::VXMLDocumentRep()
  261.   : root(NULL), pos(NULL), posType(VXMLNode::Type_VXMLNode), count(1), 
  262.     rootBaseURL(), defaultLang()
  263. {
  264.   // Add to global list
  265.   gblDocRepMutex->Lock();
  266.   gblDocRep.push_back(this);
  267.   gblDocRepMutex->Unlock();
  268. }
  269. VXMLDocumentRep::~VXMLDocumentRep()
  270. {
  271.   // Remove from the global list
  272.   IfValidRemoveDocRep(this);
  273.   if (root != NULL) delete root;
  274. }
  275. void VXMLDocumentRep::AddContent(const VXIchar * c, unsigned int len)
  276. {
  277.   // (0) Parameter check.
  278.   if (c == NULL || len == 0) return;
  279.   // (1) Handle the case where we're just appending content to an existing node
  280.   if (posType == VXMLNode::Type_VXMLContent) {
  281.     (static_cast<VXMLContentRef *>(pos))->data += vxistring(c, len);
  282.     return;
  283.   }
  284.   // (2) Create new content node.
  285.   VXMLContentRef * temp = new VXMLContentRef(pos);
  286.   if (temp == NULL) throw VXMLDocumentModel::OutOfMemory();
  287.   temp->data = vxistring(c, len);
  288.   AddChild(temp);
  289.   pos = temp;
  290.   posType = VXMLNode::Type_VXMLContent;
  291. }
  292. void VXMLDocumentRep::MarkSSMLHeader(VXIint len)
  293. {
  294.   if (posType == VXMLNode::Type_VXMLContent) {
  295.     VXMLContentRef* ref = static_cast<VXMLContentRef *>(pos);
  296.     if( len < 0 )
  297.       ref->ssmlHeaderLen = ref->data.length();
  298.     else
  299.       ref->ssmlHeaderLen = len;
  300.   }
  301. }
  302. void VXMLDocumentRep::StartElement(VXMLElementType n, DocumentLevel dlevel)
  303. {
  304.   if (root != NULL) {
  305.     if (pos == NULL)
  306.       throw VXMLDocumentModel::InternalError();
  307.     else if (posType == VXMLNode::Type_VXMLContent) {
  308.       pos = const_cast<VXMLNodeRef *>(pos->GetParent());
  309.       posType = pos->GetType();
  310.     }
  311.   }
  312.   VXMLElementRef * temp = new VXMLElementRef(pos, n, dlevel);
  313.   if (temp == NULL) throw VXMLDocumentModel::OutOfMemory();
  314.   AddChild(temp);
  315.   pos = temp;
  316.   posType = VXMLNode::Type_VXMLElement;
  317. }
  318. void VXMLDocumentRep::PruneWhitespace()
  319. {
  320.   // Set start to the current element.
  321.   VXMLNodeRef * temp = pos;
  322.   if (posType == VXMLNode::Type_VXMLContent)
  323.     temp = const_cast<VXMLNodeRef *>(pos->GetParent());
  324.   VXMLElementRef * start = static_cast<VXMLElementRef *>(temp);
  325.   for (VXMLElementRef::CHILDREN::const_iterator j = start->children.begin();
  326.        j != start->children.end(); ++j)
  327.   {
  328.     if ((*j)->GetType() != VXMLNode::Type_VXMLContent) continue;
  329.     // Set up a very helpful reference...
  330.     vxistring & str = reinterpret_cast<VXMLContentRef *>(*j)->data;
  331.     vxistring::size_type len = str.length();
  332.     if (len == 0) continue;
  333.     // Convert all whitespace to spaces.
  334.     unsigned int i;
  335.     for (i = 0; i < len; ++i)
  336.       if (str[i] == 'r' || str[i] == 'n' || str[i] == 't')  str[i] = ' ';
  337.     // Eliminate trailing and double spaces
  338.     bool lastWasSpace = true;
  339.     for (i = len; i > 0; --i) {
  340.       if (str[i-1] != ' ') {
  341.         lastWasSpace = false;
  342.         continue;
  343.       }
  344.       if (lastWasSpace)
  345.         str.erase(i-1, 1);
  346.       else 
  347.         lastWasSpace = true;
  348.     }
  349.     // Eliminate space at very beginning.
  350.     if (str[0] == ' ') str.erase(0, 1);
  351.   }
  352. }
  353. void VXMLDocumentRep::EndElement()
  354. {
  355.   if (pos == NULL)
  356.     throw VXMLDocumentModel::InternalError();
  357.   if (posType == VXMLNode::Type_VXMLContent) {
  358.     posType = pos->GetType();
  359.     pos = const_cast<VXMLNodeRef *>(pos->GetParent());
  360.   }
  361.   if (pos == NULL)
  362.     throw VXMLDocumentModel::InternalError();
  363.   posType = pos->GetType();
  364.   pos = const_cast<VXMLNodeRef *>(pos->GetParent());
  365. }
  366. VXMLElementType VXMLDocumentRep::GetParentType() const
  367. {
  368.   if (pos == NULL)
  369.     throw VXMLDocumentModel::InternalError();
  370.   return static_cast<const VXMLElementRef *>(pos->GetParent())->name;
  371. }
  372. bool VXMLDocumentRep::GetAttribute(VXMLAttributeType key,
  373.                                    vxistring & attr) const
  374. {
  375.   if (pos == NULL || posType != VXMLNode::Type_VXMLElement)
  376.     throw VXMLDocumentModel::InternalError();
  377.   const VXMLElementRef * temp = static_cast<const VXMLElementRef *>(pos);
  378.   return temp->GetAttribute(key, attr);
  379. }
  380. void VXMLDocumentRep::AddAttribute(VXMLAttributeType name,
  381.                                    const vxistring & attr)
  382. {
  383.   if (pos == NULL || posType != VXMLNode::Type_VXMLElement)
  384.     throw VXMLDocumentModel::InternalError();
  385.   VXMLElementRef * temp = static_cast<VXMLElementRef *>(pos);
  386.   temp->attributes.push_back(VXMLElementRef::VXMLElementAttribute(name, attr));
  387. }
  388. void VXMLDocumentRep::AddChild(VXMLNodeRef * c)
  389. {
  390.   if (root == NULL) {
  391.     root = c;
  392.     return;
  393.   }
  394.   if (pos == NULL || posType != VXMLNode::Type_VXMLElement)
  395.     throw VXMLDocumentModel::InternalError();
  396.   VXMLElementRef * temp = static_cast<VXMLElementRef *>(pos);
  397.   temp->children.push_back(c);
  398. }
  399. const VXMLNodeRef * VXMLDocumentRep::GetRoot() const
  400. {
  401.   return root;
  402. }
  403. //#############################################################################
  404. VXMLDocument::VXMLDocument(VXMLDocumentRep * x) : internals(x)
  405. {
  406.   // Note: To avoid race condition between addRef and releaseRef
  407.   // it is important to check if the document is still valid
  408.   mutex->Lock();  
  409.   if( !VXMLDocumentRep::IsValidDocRep(x) )
  410.     internals = NULL;  
  411.   // Create a new document if none is found
  412.   if (internals == NULL)
  413.     internals = new VXMLDocumentRep();
  414.   mutex->Unlock();
  415.   if (internals == NULL) throw VXMLDocumentModel::OutOfMemory();
  416. }
  417. VXMLDocument::~VXMLDocument()
  418. {
  419.   VXMLDocumentRep::Release(internals);
  420. }
  421. VXMLDocument::VXMLDocument(const VXMLDocument & x)
  422. {
  423.   mutex->Lock();  
  424.   if( VXMLDocumentRep::IsValidDocRep(x.internals) ) {
  425.     internals = x.internals;
  426.     VXMLDocumentRep::AddRefAtomic(internals);
  427.   }
  428.   else {
  429.     internals = NULL;
  430.   }
  431.   mutex->Unlock();
  432.   // TODO: should throw this error OR should create new Document ???
  433.   if (internals == NULL) throw VXMLDocumentModel::InternalError();
  434. }
  435. VXMLDocument & VXMLDocument::operator=(const VXMLDocument & x)
  436. {  
  437.   mutex->Lock();  
  438.   if (this != &x && VXMLDocumentRep::IsValidDocRep(x.internals) ) {
  439.     VXMLDocumentRep::ReleaseAtomic(internals);
  440.     internals = x.internals;
  441.     VXMLDocumentRep::AddRefAtomic(internals);
  442.   }
  443.   else {
  444.     internals = NULL;  
  445.   }
  446.   mutex->Unlock();  
  447.   // TODO: should throw this error OR should create new Document ???
  448.   if (internals == NULL) throw VXMLDocumentModel::InternalError();
  449.   return *this;
  450. }
  451. VXMLElement VXMLDocument::GetRoot() const
  452. {
  453.   if (internals == NULL) return VXMLElement();
  454.   const VXMLNodeRef * root = internals->GetRoot();
  455.   if (root == NULL) return VXMLElement();
  456.   return VXMLElement(root);
  457. }
  458. void VXMLDocument::GetBaseURL(vxistring & baseURL) const
  459. {
  460.   mutex->Lock();  
  461.   if( internals != NULL ) baseURL = internals->rootBaseURL;
  462.   mutex->Unlock();
  463. }
  464. void VXMLDocument::SetBaseURL(const vxistring & baseuri)
  465. {
  466.   mutex->Lock();  
  467.   if( internals != NULL ) internals->rootBaseURL = baseuri;
  468.   mutex->Unlock();  
  469. }
  470. void VXMLDocument::GetDefaultLang(vxistring & defaultLanguage) const
  471. {
  472.   mutex->Lock();  
  473.   if( internals != NULL ) defaultLanguage = internals->defaultLang;
  474.   mutex->Unlock();
  475. }
  476. void VXMLDocument::SetDefaultLang(const vxistring & defaultLanguage)
  477. {
  478.   mutex->Lock();  
  479.   if( internals != NULL ) internals->defaultLang = defaultLanguage;
  480.   mutex->Unlock();  
  481. }
  482. //#############################################################################
  483. VXMLNode::VXMLNode(const VXMLNode & x)
  484. {
  485.   internals = x.internals;
  486. }
  487. VXMLNode & VXMLNode::operator=(const VXMLNode & x)
  488. {
  489.   if (this != &x) {
  490.     internals = x.internals;
  491.   }
  492.   return *this;
  493. }
  494. VXMLElement VXMLNode::GetParent() const
  495. {
  496.   if (internals != NULL && internals->GetType() == VXMLNode::Type_VXMLNode)
  497.     throw VXMLDocumentModel::InternalError();
  498.   if (internals == NULL) return VXMLElement();
  499.   return VXMLElement(internals->GetParent());
  500. }
  501. VXMLNode::VXMLNodeType VXMLNode::GetType() const
  502. {
  503.   if (internals == NULL) return VXMLNode::Type_VXMLNode;
  504.   return internals->GetType();
  505. }
  506. //#############################################################################
  507. const vxistring & VXMLContent::GetValue() const
  508. {
  509.   if (internals == NULL) throw VXMLDocumentModel::InternalError();
  510.   const VXMLContentRef * ref = static_cast<const VXMLContentRef *>(internals);
  511.   return ref->data;
  512. }
  513. VXIulong VXMLContent::GetSSMLHeaderLen() const
  514. {
  515.   if (internals == NULL) throw VXMLDocumentModel::InternalError();
  516.   const VXMLContentRef * ref = static_cast<const VXMLContentRef *>(internals);
  517.   return ref->ssmlHeaderLen;
  518. }
  519. //#############################################################################
  520. VXMLElement::VXMLElement(const VXMLNodeRef * ref) : VXMLNode(ref)
  521. {
  522. }
  523. VXMLElement::VXMLElement(const VXMLElement & x)
  524. {
  525.   internals = x.internals;
  526. }
  527. bool VXMLElement::hasChildren() const
  528. {
  529.   if (internals == NULL) throw VXMLDocumentModel::InternalError();
  530.   const VXMLElementRef * ref = static_cast<const VXMLElementRef *>(internals);
  531.   return !ref->children.empty();
  532. }
  533. VXMLElementType VXMLElement::GetName() const
  534. {
  535.   if (internals == NULL) throw VXMLDocumentModel::InternalError();
  536.   const VXMLElementRef * ref = static_cast<const VXMLElementRef *>(internals);
  537.   return ref->name;
  538. }
  539. bool VXMLElement::GetAttribute(VXMLAttributeType key, vxistring & attr) const
  540. {
  541.   if (internals == NULL) throw VXMLDocumentModel::InternalError();
  542.   const VXMLElementRef * ref = static_cast<const VXMLElementRef *>(internals);
  543.   return ref->GetAttribute(key, attr);
  544. }
  545. DocumentLevel VXMLElement::GetDocumentLevel() const
  546. {
  547.   if (internals == NULL) return DOCUMENT;
  548.   const VXMLElementRef * ref = static_cast<const VXMLElementRef *>(internals);
  549.   return ref->GetDocumentLevel();
  550. }
  551. //#############################################################################
  552. // This code is NOT sensitive to possible byte order differences....  This is
  553. // a problem if the cache is shared across machines with different endian
  554. // architectures.
  555. // ------*---------*---------*---------*---------*---------*---------*---------
  556. static const unsigned int INT_MULTIPLIER  = sizeof(VXIulong) / sizeof(VXIbyte);
  557. static const unsigned int CHAR_MULTIPLIER = sizeof(VXIchar) / sizeof(VXIbyte);
  558. inline void WriteInt(VXIulong i, SerializerOutput & writer)
  559. {
  560.   writer.Write(reinterpret_cast<const VXIbyte *>(&i), INT_MULTIPLIER);
  561. }
  562. inline void WriteBlock(const vxistring & block, SerializerOutput & writer)
  563. {
  564.   vxistring::size_type size = block.size();
  565.   WriteInt(size, writer);
  566.   if (size != 0) {
  567.     writer.Write(reinterpret_cast<const VXIbyte *>(block.c_str()),
  568.                  block.size() * CHAR_MULTIPLIER);
  569.   }
  570. }
  571. inline VXIulong ReadInt(SerializerInput & reader)
  572. {
  573.   VXIbyte temp[INT_MULTIPLIER];
  574.   if (reader.Read(temp, INT_MULTIPLIER) != INT_MULTIPLIER)
  575.     throw VXMLDocument::SerializationError();
  576.   VXIulong * ptr = reinterpret_cast<VXIulong *>(temp);
  577.   return *ptr;
  578. }
  579. inline void ReadBlock(vxistring & block, VXIulong size,
  580.                       SerializerInput & reader)
  581. {
  582.   const VXIulong NUM_CHARS = 256;
  583.   VXIbyte temp[NUM_CHARS * CHAR_MULTIPLIER];
  584.   // Clear string.
  585.   if (!block.empty()) block.erase();
  586.   if (size == 0) return;
  587.   do {
  588.     const VXIulong REQUEST = (size < NUM_CHARS ? size : NUM_CHARS);
  589.     const VXIulong MAXREAD = REQUEST * CHAR_MULTIPLIER;
  590.     if (reader.Read(temp, MAXREAD) != MAXREAD)
  591.       throw VXMLDocument::SerializationError();
  592.     block += vxistring(reinterpret_cast<const VXIchar *>(temp), REQUEST);
  593.     size -= REQUEST;
  594.   } while (size > 0);
  595. }
  596. // ------*---------*---------*---------*---------*---------*---------*---------
  597. void WriteElement(const VXMLElementRef * elem, SerializerOutput & writer)
  598. {
  599.   WriteInt(VXMLNode::Type_VXMLElement, writer);
  600.   // Write out the element name.
  601.   WriteInt(elem->name, writer);
  602.   // Write out the attributes.
  603.   WriteInt(elem->attributes.size(), writer);
  604.   for (VXMLElementRef::ATTRIBUTES::const_iterator i = elem->attributes.begin();
  605.        i != elem->attributes.end(); ++i)
  606.   {
  607.     WriteInt((*i).key, writer);
  608.     WriteBlock((*i).value, writer);
  609.   }
  610.   // Write out the children.
  611.   WriteInt(elem->children.size(), writer);
  612.   for (VXMLElementRef::CHILDREN::const_iterator j = elem->children.begin();
  613.        j != elem->children.end(); ++j)
  614.   {
  615.     switch ((*j)->GetType()) {
  616.     case VXMLNode::Type_VXMLElement:
  617.       WriteElement(reinterpret_cast<const VXMLElementRef *>(*j), writer);
  618.       break;
  619.     case VXMLNode::Type_VXMLContent:
  620.       WriteInt(VXMLNode::Type_VXMLContent, writer);
  621.       WriteBlock(reinterpret_cast<const VXMLContentRef *>(*j)->data, writer);
  622.       WriteInt(reinterpret_cast<const VXMLContentRef *>(*j)->ssmlHeaderLen, writer);
  623.       break;
  624.     default:
  625.       throw VXMLDocument::SerializationError();
  626.     }
  627.   }
  628. }
  629. void VXMLDocument::WriteDocument(SerializerOutput & writer) const
  630. {
  631.   if (internals == NULL) return;
  632.   const VXMLNodeRef * root = internals->GetRoot();
  633.   if (root == NULL || root->GetType() != VXMLNode::Type_VXMLElement)
  634.     throw VXMLDocument::SerializationError();
  635.   WriteElement(static_cast<const VXMLElementRef *>(root), writer);
  636. }
  637. // ------*---------*---------*---------*---------*---------*---------*---------
  638. void LoadElement(VXMLDocumentRep & docRep, SerializerInput & reader)
  639. {
  640.   int type = ReadInt(reader);
  641.   // Need to store the document level with the disk cache and read it back
  642.   // I just put DOCUMENT here to pass compilation.  Also current 
  643.   // implementation no longer ultilize disk cache
  644.   docRep.StartElement(VXMLElementType(type), DOCUMENT);
  645.   VXIulong numAttributes = ReadInt(reader);
  646.   for (unsigned int i = 0; i < numAttributes; ++i) {
  647.     VXIulong key  = ReadInt(reader);
  648.     VXIulong size = ReadInt(reader);
  649.     vxistring attr;
  650.     ReadBlock(attr, size, reader);
  651.     docRep.AddAttribute(VXMLAttributeType(key), attr);
  652.   }
  653.   VXIulong numChildren = ReadInt(reader);
  654.   for (unsigned int j = 0; j < numChildren; ++j) {
  655.     VXIulong nodeType = ReadInt(reader);
  656.     if (nodeType == VXMLNode::Type_VXMLContent) {
  657.       VXIulong size = ReadInt(reader);
  658.       vxistring data;
  659.       ReadBlock(data, size, reader);
  660.       docRep.AddContent(data.c_str(), data.size());
  661.       size = ReadInt(reader);
  662.       docRep.MarkSSMLHeader(size);
  663.     }
  664.     else if (nodeType == VXMLNode::Type_VXMLElement)
  665.       LoadElement(docRep, reader);
  666.     else {
  667.       throw VXMLDocument::SerializationError();
  668.     }
  669.   }
  670.   docRep.EndElement();
  671. }
  672. void VXMLDocument::ReadDocument(SerializerInput & reader)
  673. {
  674.   VXIulong type = ReadInt(reader);
  675.   if (type != VXMLNode::Type_VXMLElement)
  676.     throw VXMLDocument::SerializationError();
  677.   VXMLDocumentRep * docRep = new VXMLDocumentRep();
  678.   LoadElement(*docRep, reader);
  679.   if (internals != NULL)
  680.     VXMLDocumentRep::Release(internals);
  681.   internals = docRep;
  682. }