GME  13
XSerializeEngine.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: XSerializeEngine.cpp 834826 2009-11-11 10:03:53Z borisk $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <xercesc/internal/XSerializeEngine.hpp>
00027 #include <xercesc/internal/XSerializable.hpp>
00028 #include <xercesc/internal/XProtoType.hpp>
00029 
00030 #include <xercesc/framework/XMLGrammarPool.hpp>
00031 #include <xercesc/framework/BinOutputStream.hpp>
00032 #include <xercesc/util/BinInputStream.hpp>
00033 
00034 #include <stdio.h>
00035 #include <assert.h>
00036 
00037 XERCES_CPP_NAMESPACE_BEGIN
00038 
00039 const bool XSerializeEngine::toWriteBufferLen = true;
00040 const bool XSerializeEngine::toReadBufferLen  = true;
00041 
00042 static const unsigned long noDataFollowed = (unsigned long)-1;
00043 
00044 static const XSerializeEngine::XSerializedObjectId_t fgNullObjectTag  = 0;           // indicating null ptrs
00045 static const XSerializeEngine::XSerializedObjectId_t fgNewClassTag    = 0xFFFFFFFF;  // indicating new class
00046 static const XSerializeEngine::XSerializedObjectId_t fgTemplateObjTag = 0xFFFFFFFE;  // indicating template object
00047 static const XSerializeEngine::XSerializedObjectId_t fgClassMask      = 0x80000000;  // indicates class tag
00048 static const XSerializeEngine::XSerializedObjectId_t fgMaxObjectCount = 0x3FFFFFFD;
00049 
00050 #define TEST_THROW_ARG1(condition, data, err_msg) \
00051 if (condition) \
00052 { \
00053     XMLCh value1[64]; \
00054     XMLString::sizeToText(data, value1, 65, 10, getMemoryManager()); \
00055     ThrowXMLwithMemMgr1(XSerializationException \
00056             , err_msg  \
00057             , value1 \
00058             , getMemoryManager()); \
00059 }
00060 
00061 #define TEST_THROW_ARG2(condition, data1, data2, err_msg) \
00062 if (condition) \
00063 { \
00064     XMLCh value1[64]; \
00065     XMLCh value2[64]; \
00066     XMLString::sizeToText(data1, value1, 65, 10, getMemoryManager()); \
00067     XMLString::sizeToText(data2, value2, 65, 10, getMemoryManager()); \
00068     ThrowXMLwithMemMgr2(XSerializationException \
00069             , err_msg  \
00070             , value1   \
00071             , value2 \
00072             , getMemoryManager()); \
00073 }
00074 
00075 // ---------------------------------------------------------------------------
00076 //  Constructor and Destructor
00077 // ---------------------------------------------------------------------------
00078 XSerializeEngine::~XSerializeEngine()
00079 {
00080     if (isStoring())
00081     {
00082         flush();
00083         delete fStorePool;
00084     }
00085     else
00086     {
00087         delete fLoadPool;
00088     }
00089 
00090     getMemoryManager()->deallocate(fBufStart);
00091 
00092 }
00093 
00094 XSerializeEngine::XSerializeEngine(BinInputStream*         inStream
00095                                  , XMLGrammarPool* const   gramPool
00096                                  , XMLSize_t               bufSize)
00097 :fStoreLoad(mode_Load)
00098 ,fStorerLevel(0)
00099 ,fGrammarPool(gramPool)
00100 ,fInputStream(inStream)
00101 ,fOutputStream(0)
00102 ,fBufCount(0)
00103 ,fBufSize(bufSize)
00104 ,fBufStart( (XMLByte*) gramPool->getMemoryManager()->allocate(bufSize))
00105 ,fBufEnd(0)
00106 ,fBufCur(fBufStart)
00107 ,fBufLoadMax(fBufStart)
00108 ,fStorePool(0)
00109 ,fLoadPool( new (gramPool->getMemoryManager()) ValueVectorOf<void*>(29, gramPool->getMemoryManager(), false))
00110 ,fObjectCount(0)
00111 {
00112     /***
00113      *  initialize buffer from the inStream
00114      ***/
00115     fillBuffer();
00116 
00117 }
00118 
00119 XSerializeEngine::XSerializeEngine(BinOutputStream*        outStream
00120                                  , XMLGrammarPool* const   gramPool
00121                                  , XMLSize_t               bufSize)
00122 :fStoreLoad(mode_Store)
00123 ,fStorerLevel(0)
00124 ,fGrammarPool(gramPool)
00125 ,fInputStream(0)
00126 ,fOutputStream(outStream)
00127 ,fBufCount(0)
00128 ,fBufSize(bufSize)
00129 ,fBufStart((XMLByte*) gramPool->getMemoryManager()->allocate(bufSize))
00130 ,fBufEnd(fBufStart+bufSize)
00131 ,fBufCur(fBufStart)
00132 ,fBufLoadMax(0)
00133 ,fStorePool( new (gramPool->getMemoryManager()) RefHashTableOf<XSerializedObjectId, PtrHasher>(29, true, gramPool->getMemoryManager()) )
00134 ,fLoadPool(0)
00135 ,fObjectCount(0)
00136 {
00137     resetBuffer();
00138 
00139     //initialize store pool
00140     fStorePool->put(0, new (gramPool->getMemoryManager()) XSerializedObjectId(fgNullObjectTag));
00141 
00142 }
00143 
00144 void XSerializeEngine::flush()
00145 {
00146     if (isStoring())
00147         flushBuffer();
00148 
00149 }
00150 
00151 // ---------------------------------------------------------------------------
00152 //  Storing
00153 // ---------------------------------------------------------------------------
00154 void XSerializeEngine::write(XSerializable* const objectToWrite)
00155 {
00156     ensureStoring();
00157     //don't ensurePointer here !!!
00158 
00159     XSerializedObjectId_t   objIndex = 0;
00160 
00161         if (!objectToWrite)  // null pointer
00162         {
00163                 *this << fgNullObjectTag;
00164         }
00165     else if (0 != (objIndex = lookupStorePool((void*) objectToWrite)))
00166         {
00167         // writing an object reference tag
00168         *this << objIndex;
00169         }
00170         else
00171         {
00172                 // write protoType first
00173                 XProtoType* protoType = objectToWrite->getProtoType();
00174                 write(protoType);
00175 
00176                 // put the object into StorePool
00177         addStorePool((void*)objectToWrite);
00178 
00179         // ask the object to serialize itself
00180                 objectToWrite->serialize(*this);
00181         }
00182 
00183 }
00184 
00185 void XSerializeEngine::write(XProtoType* const protoType)
00186 {
00187     ensureStoring();
00188     ensurePointer(protoType);
00189 
00190         XSerializedObjectId_t objIndex = lookupStorePool((void*)protoType);
00191 
00192     if (objIndex)
00193     {
00194         //protoType seen in the store pool
00195         *this << (fgClassMask | objIndex);
00196         }
00197         else
00198         {
00199                 // store protoType
00200                 *this << fgNewClassTag;
00201                 protoType->store(*this);
00202         addStorePool((void*)protoType);
00203         }
00204 
00205 }
00206 
00207 /***
00208  *
00209 ***/
00210 void XSerializeEngine::write(const XMLCh* const toWrite
00211                            ,       XMLSize_t    writeLen)
00212 {
00213     write((XMLByte*)toWrite, (sizeof(XMLCh)/sizeof(XMLByte)) * writeLen);
00214 }
00215 
00216 
00217 void XSerializeEngine::write(const XMLByte* const toWrite
00218                            ,       XMLSize_t      writeLen)
00219 {
00220     ensureStoring();
00221     ensurePointer((void*)toWrite);
00222     ensureStoreBuffer();
00223 
00224     if (writeLen == 0)
00225         return;
00226 
00227     /***
00228      *  If the available space is sufficient, write it up
00229      ***/
00230     XMLSize_t bufAvail = fBufEnd - fBufCur;
00231 
00232     if (writeLen <= bufAvail)
00233     {
00234         memcpy(fBufCur, toWrite, writeLen);
00235         fBufCur += writeLen;
00236         return;
00237     }
00238 
00239     const XMLByte*  tempWrite   = (const XMLByte*) toWrite;
00240     XMLSize_t       writeRemain = writeLen;
00241 
00242     // fill up the avaiable space and flush
00243     memcpy(fBufCur, tempWrite, bufAvail);
00244     tempWrite   += bufAvail;
00245     writeRemain -= bufAvail;
00246     flushBuffer();
00247 
00248     // write chunks of fBufSize
00249     while (writeRemain >= fBufSize)
00250     {
00251         memcpy(fBufCur, tempWrite, fBufSize);
00252         tempWrite   += fBufSize;
00253         writeRemain -= fBufSize;
00254         flushBuffer();
00255     }
00256 
00257     // write the remaining if any
00258     if (writeRemain)
00259     {
00260         memcpy(fBufCur, tempWrite, writeRemain);
00261         fBufCur += writeRemain;
00262     }
00263 
00264 }
00265 
00266 /***
00267  *
00268  *     Storage scheme (normal):
00269  *
00270  *     <
00271  *     1st integer:    bufferLen (optional)
00272  *     2nd integer:    dataLen
00273  *     bytes following:
00274  *     >
00275  *
00276  *     Storage scheme (special):
00277  *     <
00278  *     only integer:   noDataFollowed
00279  *     >
00280  */
00281 
00282 void XSerializeEngine::writeString(const XMLCh* const toWrite
00283                                  , const XMLSize_t    bufferLen
00284                                  , bool               toWriteBufLen)
00285 {
00286     if (toWrite)
00287     {
00288         if (toWriteBufLen)
00289             *this<<(unsigned long)bufferLen;
00290 
00291         XMLSize_t strLen = XMLString::stringLen(toWrite);
00292         *this<<(unsigned long)strLen;
00293 
00294         write(toWrite, strLen);
00295     }
00296     else
00297     {
00298         *this<<noDataFollowed;
00299     }
00300 
00301 }
00302 
00303 void XSerializeEngine::writeString(const XMLByte* const toWrite
00304                                  , const XMLSize_t      bufferLen
00305                                  , bool                 toWriteBufLen)
00306 {
00307 
00308     if (toWrite)
00309     {
00310         if (toWriteBufLen)
00311             *this<<(unsigned long)bufferLen;
00312 
00313         XMLSize_t strLen = XMLString::stringLen((char*)toWrite);
00314         *this<<(unsigned long)strLen;
00315         write(toWrite, strLen);
00316     }
00317     else
00318     {
00319         *this<<noDataFollowed;
00320     }
00321 
00322 }
00323 
00324 // ---------------------------------------------------------------------------
00325 //  Loading
00326 // ---------------------------------------------------------------------------
00327 XSerializable* XSerializeEngine::read(XProtoType* const protoType)
00328 {
00329     ensureLoading();
00330     ensurePointer(protoType);
00331 
00332         XSerializedObjectId_t    objectTag;
00333         XSerializable*           objRet;
00334 
00335     if (! read(protoType, &objectTag))
00336         {
00337         /***
00338          * We hava a reference to an existing object in
00339          * load pool, get it.
00340          */
00341         objRet = lookupLoadPool(objectTag);
00342         }
00343         else
00344         {
00345                 // create the object from the prototype
00346                 objRet = protoType->fCreateObject(getMemoryManager());
00347         Assert((objRet != 0), XMLExcepts::XSer_CreateObject_Fail);
00348 
00349         // put it into load pool
00350         addLoadPool(objRet);
00351 
00352         // de-serialize it
00353                 objRet->serialize(*this);
00354 
00355         }
00356 
00357         return objRet;
00358 }
00359 
00360 bool XSerializeEngine::read(XProtoType*            const    protoType
00361                           , XSerializedObjectId_t*          objectTagRet)
00362 {
00363     ensureLoading();
00364     ensurePointer(protoType);
00365 
00366         XSerializedObjectId_t obTag;
00367 
00368     *this >> obTag;
00369 
00370     // object reference tag found
00371     if (!(obTag & fgClassMask))
00372         {
00373                 *objectTagRet = obTag;
00374                 return false;
00375         }
00376 
00377         if (obTag == fgNewClassTag)
00378         {
00379         // what follows fgNewClassTag is the prototype object info
00380         // for the object anticipated, go and verify the info
00381         XProtoType::load(*this, protoType->fClassName, getMemoryManager());
00382 
00383         addLoadPool((void*)protoType);
00384         }
00385         else
00386         {
00387         // what follows class tag is an XSerializable object
00388         XSerializedObjectId_t classIndex = (obTag & ~fgClassMask);
00389         XSerializedObjectId_t loadPoolSize = (XSerializedObjectId_t)fLoadPool->size();
00390 
00391         if ((classIndex == 0 ) || (classIndex > loadPoolSize))
00392         {
00393           XMLCh value1[64];
00394           XMLCh value2[64];
00395           XMLString::binToText(classIndex, value1, 65, 10, getMemoryManager());
00396           XMLString::binToText(loadPoolSize, value2, 65, 10, getMemoryManager());
00397           ThrowXMLwithMemMgr2(XSerializationException
00398                               , XMLExcepts::XSer_Inv_ClassIndex
00399                               , value1
00400                               , value2
00401                               , getMemoryManager());
00402         }
00403 
00404         ensurePointer(lookupLoadPool(classIndex));
00405    }
00406 
00407         return true;
00408 }
00409 
00410 void XSerializeEngine::read(XMLCh* const toRead
00411                           , XMLSize_t    readLen)
00412 {
00413     read((XMLByte*)toRead, (sizeof(XMLCh)/sizeof(XMLByte))*readLen);
00414 }
00415 
00416 void XSerializeEngine::read(XMLByte* const toRead
00417                           , XMLSize_t      readLen)
00418 {
00419     ensureLoading();
00420     ensurePointer(toRead);
00421     ensureLoadBuffer();
00422 
00423     if (readLen == 0)
00424         return;
00425 
00426     /***
00427      *  If unread is sufficient, read it up
00428      ***/
00429     XMLSize_t dataAvail = fBufLoadMax - fBufCur;
00430 
00431     if (readLen <= dataAvail)
00432     {
00433         memcpy(toRead, fBufCur, readLen);
00434         fBufCur += readLen;
00435         return;
00436     }
00437 
00438     /***
00439      *
00440      * fillBuffer will discard anything left in the buffer
00441      * before it asks the inputStream to fill in the buffer,
00442      * so we need to readup everything in the buffer before
00443      * calling fillBuffer
00444      *
00445      ***/
00446     XMLByte*     tempRead   = (XMLByte*) toRead;
00447     XMLSize_t    readRemain = readLen;
00448 
00449     // read the unread
00450     memcpy(tempRead, fBufCur, dataAvail);
00451     tempRead   += dataAvail;
00452     readRemain -= dataAvail;
00453 
00454     // read chunks of fBufSize
00455     while (readRemain >= fBufSize)
00456     {
00457         fillBuffer();
00458         memcpy(tempRead, fBufCur, fBufSize);
00459         tempRead   += fBufSize;
00460         readRemain -= fBufSize;
00461     }
00462 
00463     // read the remaining if any
00464     if (readRemain)
00465     {
00466         fillBuffer();
00467         memcpy(tempRead, fBufCur, readRemain);
00468         fBufCur += readRemain;
00469     }
00470 
00471 }
00472 
00473 /***
00474  *
00475  *     Storage scheme (normal):
00476  *
00477  *     <
00478  *     1st integer:    bufferLen (optional)
00479  *     2nd integer:    dataLen
00480  *     bytes following:
00481  *     >
00482  *
00483  *     Storage scheme (special):
00484  *     <
00485  *     only integer:   noDataFollowed
00486  *     >
00487  */
00488 void XSerializeEngine::readString(XMLCh*&       toRead
00489                                 , XMLSize_t&    bufferLen
00490                                 , XMLSize_t&    dataLen
00491                                 , bool          toReadBufLen)
00492 {
00493     /***
00494      * Check if any data written
00495      ***/
00496     unsigned long tmp;
00497     *this>>tmp;
00498     bufferLen=tmp;
00499 
00500     if (bufferLen == noDataFollowed)
00501     {
00502         toRead = 0;
00503         bufferLen = 0;
00504         dataLen = 0;
00505         return;
00506     }
00507 
00508     if (toReadBufLen)
00509     {
00510         *this>>tmp;
00511         dataLen=tmp;
00512     }
00513     else
00514     {
00515         dataLen = bufferLen++;
00516     }
00517 
00518     toRead = (XMLCh*) getMemoryManager()->allocate(bufferLen * sizeof(XMLCh));
00519     read(toRead, dataLen);
00520     toRead[dataLen] = 0;
00521 }
00522 
00523 void XSerializeEngine::readString(XMLByte*&     toRead
00524                                 , XMLSize_t&    bufferLen
00525                                 , XMLSize_t&    dataLen
00526                                 , bool          toReadBufLen)
00527 {
00528     /***
00529      * Check if any data written
00530      ***/
00531     unsigned long tmp;
00532     *this>>tmp;
00533     bufferLen=tmp;
00534     if (bufferLen == noDataFollowed)
00535     {
00536         toRead = 0;
00537         bufferLen = 0;
00538         dataLen = 0;
00539         return;
00540     }
00541 
00542     if (toReadBufLen)
00543     {
00544         *this>>tmp;
00545         dataLen=tmp;
00546     }
00547     else
00548     {
00549         dataLen = bufferLen++;
00550     }
00551 
00552     toRead = (XMLByte*) getMemoryManager()->allocate(bufferLen * sizeof(XMLByte));
00553     read(toRead, dataLen);
00554     toRead[dataLen] = 0;
00555 
00556 }
00557 
00558 // ---------------------------------------------------------------------------
00559 //  Insertion & Extraction
00560 // ---------------------------------------------------------------------------
00561 
00562 XSerializeEngine& XSerializeEngine::operator<<(XMLCh xch)
00563 {
00564     checkAndFlushBuffer(calBytesNeeded(sizeof(XMLCh)));
00565 
00566     alignBufCur(sizeof(XMLCh));
00567     *(XMLCh*)fBufCur = xch;
00568     fBufCur += sizeof(XMLCh);
00569     return *this;
00570 }
00571 
00572 XSerializeEngine& XSerializeEngine::operator>>(XMLCh& xch)
00573 {
00574     checkAndFillBuffer(calBytesNeeded(sizeof(XMLCh)));
00575 
00576     alignBufCur(sizeof(XMLCh));
00577     xch = *(XMLCh*)fBufCur;
00578     fBufCur += sizeof(XMLCh);
00579     return *this;
00580 }
00581 
00582 XSerializeEngine& XSerializeEngine::operator<<(XMLByte by)
00583 {
00584     checkAndFlushBuffer(sizeof(XMLByte));
00585 
00586     *(XMLByte*)fBufCur = by;
00587     fBufCur += sizeof(XMLByte);
00588     return *this;
00589 }
00590 
00591 XSerializeEngine& XSerializeEngine::operator>>(XMLByte& by)
00592 {
00593     checkAndFillBuffer(sizeof(XMLByte));
00594 
00595     by = *(XMLByte*)fBufCur;
00596     fBufCur += sizeof(XMLByte);
00597     return *this;
00598 }
00599 
00600 XSerializeEngine& XSerializeEngine::operator<<(bool b)
00601 {
00602     checkAndFlushBuffer(sizeof(bool));
00603 
00604     *(bool*)fBufCur = b;
00605     fBufCur += sizeof(bool);
00606     return *this;
00607 }
00608 
00609 XSerializeEngine& XSerializeEngine::operator>>(bool& b)
00610 {
00611     checkAndFillBuffer(sizeof(bool));
00612 
00613     b = *(bool*)fBufCur;
00614     fBufCur += sizeof(bool);
00615     return *this;
00616 }
00617 
00618 void XSerializeEngine::writeSize (XMLSize_t t)
00619 {
00620   checkAndFlushBuffer(sizeof(t));
00621 
00622   memcpy(fBufCur, &t, sizeof(t));
00623   fBufCur += sizeof(t);
00624 }
00625 
00626 void XSerializeEngine::writeInt64 (XMLInt64 t)
00627 {
00628   checkAndFlushBuffer(sizeof(t));
00629 
00630   memcpy(fBufCur, &t, sizeof(t));
00631   fBufCur += sizeof(t);
00632 }
00633 
00634 void XSerializeEngine::writeUInt64 (XMLUInt64 t)
00635 {
00636   checkAndFlushBuffer(sizeof(t));
00637 
00638   memcpy(fBufCur, &t, sizeof(t));
00639   fBufCur += sizeof(t);
00640 }
00641 
00642 void XSerializeEngine::readSize (XMLSize_t& t)
00643 {
00644   checkAndFillBuffer(sizeof(t));
00645 
00646   memcpy(&t, fBufCur, sizeof(t));
00647   fBufCur += sizeof(t);
00648 }
00649 
00650 void XSerializeEngine::readInt64 (XMLInt64& t)
00651 {
00652   checkAndFillBuffer(sizeof(t));
00653 
00654   memcpy(&t, fBufCur, sizeof(t));
00655   fBufCur += sizeof(t);
00656 }
00657 
00658 void XSerializeEngine::readUInt64 (XMLUInt64& t)
00659 {
00660   checkAndFillBuffer(sizeof(t));
00661 
00662   memcpy(&t, fBufCur, sizeof(t));
00663   fBufCur += sizeof(t);
00664 }
00665 
00666 XSerializeEngine& XSerializeEngine::operator<<(char ch)
00667 {
00668     return XSerializeEngine::operator<<((XMLByte)ch);
00669 }
00670 
00671 XSerializeEngine& XSerializeEngine::operator>>(char& ch)
00672 {
00673     return XSerializeEngine::operator>>((XMLByte&)ch);
00674 }
00675 
00676 XSerializeEngine& XSerializeEngine::operator<<(short sh)
00677 {
00678     checkAndFlushBuffer(calBytesNeeded(sizeof(short)));
00679 
00680     alignBufCur(sizeof(short));
00681     *(short*)fBufCur = sh;
00682     fBufCur += sizeof(short);
00683     return *this;
00684 }
00685 
00686 XSerializeEngine& XSerializeEngine::operator>>(short& sh)
00687 {
00688     checkAndFillBuffer(calBytesNeeded(sizeof(short)));
00689 
00690     alignBufCur(sizeof(short));
00691     sh = *(short*)fBufCur;
00692     fBufCur += sizeof(short);
00693     return *this;
00694 }
00695 
00696 XSerializeEngine& XSerializeEngine::operator<<(int i)
00697 {
00698     checkAndFlushBuffer(calBytesNeeded(sizeof(int)));
00699 
00700     alignBufCur(sizeof(int));
00701     *(int*)fBufCur = i;
00702     fBufCur += sizeof(int);
00703     return *this;
00704 }
00705 
00706 XSerializeEngine& XSerializeEngine::operator>>(int& i)
00707 {
00708     checkAndFillBuffer(calBytesNeeded(sizeof(int)));
00709 
00710     alignBufCur(sizeof(int));
00711     i = *(int*)fBufCur;
00712     fBufCur += sizeof(int);
00713     return *this;
00714 }
00715 
00716 XSerializeEngine& XSerializeEngine::operator<<(unsigned int ui)
00717 {
00718 
00719     checkAndFlushBuffer(calBytesNeeded(sizeof(unsigned int)));
00720 
00721     alignBufCur(sizeof(unsigned int));
00722     *(unsigned int*)fBufCur = ui;
00723     fBufCur += sizeof(unsigned int);
00724     return *this;
00725 }
00726 
00727 XSerializeEngine& XSerializeEngine::operator>>(unsigned int& ui)
00728 {
00729 
00730     checkAndFillBuffer(calBytesNeeded(sizeof(unsigned int)));
00731 
00732     alignBufCur(sizeof(unsigned int));
00733     ui = *(unsigned int*)fBufCur;
00734     fBufCur += sizeof(unsigned int);
00735     return *this;
00736 }
00737 
00738 XSerializeEngine& XSerializeEngine::operator<<(long l)
00739 {
00740     checkAndFlushBuffer(calBytesNeeded(sizeof(long)));
00741 
00742     alignBufCur(sizeof(long));
00743     *(long*)fBufCur = l;
00744     fBufCur += sizeof(long);
00745     return *this;
00746 }
00747 
00748 XSerializeEngine& XSerializeEngine::operator>>(long& l)
00749 {
00750     checkAndFillBuffer(calBytesNeeded(sizeof(long)));
00751 
00752     alignBufCur(sizeof(long));
00753     l = *(long*)fBufCur;
00754     fBufCur += sizeof(long);
00755     return *this;
00756 }
00757 
00758 XSerializeEngine& XSerializeEngine::operator<<(unsigned long ul)
00759 {
00760     checkAndFlushBuffer(calBytesNeeded(sizeof(unsigned long)));
00761 
00762     alignBufCur(sizeof(unsigned long));
00763     *(unsigned long*)fBufCur = ul;
00764     fBufCur += sizeof(unsigned long);
00765     return *this;
00766 }
00767 
00768 XSerializeEngine& XSerializeEngine::operator>>(unsigned long& ul)
00769 {
00770     checkAndFillBuffer(calBytesNeeded(sizeof(unsigned long)));
00771 
00772     alignBufCur(sizeof(unsigned long));
00773     ul = *(unsigned long*)fBufCur;
00774     fBufCur += sizeof(unsigned long);
00775     return *this;
00776 }
00777 
00778 XSerializeEngine& XSerializeEngine::operator<<(float f)
00779 {
00780     checkAndFlushBuffer(calBytesNeeded(sizeof(float)));
00781 
00782     alignBufCur(sizeof(float));
00783     *(float*)fBufCur = *(float*)&f;
00784     fBufCur += sizeof(float);
00785     return *this;
00786 }
00787 
00788 XSerializeEngine& XSerializeEngine::operator>>(float& f)
00789 {
00790     checkAndFillBuffer(calBytesNeeded(sizeof(float)));
00791 
00792     alignBufCur(sizeof(float));
00793     *(float*)&f = *(float*)fBufCur;
00794     fBufCur += sizeof(float);
00795     return *this;
00796 }
00797 
00798 XSerializeEngine& XSerializeEngine::operator<<(double d)
00799 {
00800     checkAndFlushBuffer(calBytesNeeded(sizeof(double)));
00801 
00802     alignBufCur(sizeof(double));
00803     *(double*)fBufCur = *(double*)&d;
00804     fBufCur += sizeof(double);
00805     return *this;
00806 }
00807 
00808 XSerializeEngine& XSerializeEngine::operator>>(double& d)
00809 {
00810     checkAndFillBuffer(calBytesNeeded(sizeof(double)));
00811 
00812     alignBufCur(sizeof(double));
00813     *(double*)&d = *(double*)fBufCur;
00814     fBufCur += sizeof(double);
00815     return *this;
00816 }
00817 
00818 // ---------------------------------------------------------------------------
00819 //  StorePool/LoadPool Opertions
00820 // ---------------------------------------------------------------------------
00821 XSerializeEngine::XSerializedObjectId_t
00822 XSerializeEngine::lookupStorePool(void* const objToLookup) const
00823 {
00824     //0 indicating object is not in the StorePool
00825     XSerializedObjectId* data = fStorePool->get(objToLookup);
00826     return (XSerializeEngine::XSerializedObjectId_t) (data ? data->getValue() : 0);
00827 
00828 }
00829 
00830 void XSerializeEngine::addStorePool(void* const objToAdd)
00831 {
00832     pumpCount();
00833     fStorePool->put(objToAdd, new (fGrammarPool->getMemoryManager()) XSerializedObjectId(fObjectCount));
00834 }
00835 
00836 XSerializable* XSerializeEngine::lookupLoadPool(XSerializedObjectId_t objectTag) const
00837 {
00838 
00839     /***
00840       *  an object tag read from the binary refering to
00841       *  an object beyond the upper most boundary of the load pool
00842       ***/
00843 
00844     if (objectTag > fLoadPool->size())
00845     {
00846       XMLCh value1[64];
00847       XMLCh value2[64];
00848       XMLString::binToText(objectTag, value1, 65, 10, getMemoryManager());
00849       XMLString::sizeToText(fLoadPool->size(), value2, 65, 10, getMemoryManager());
00850       ThrowXMLwithMemMgr2(XSerializationException
00851                           , XMLExcepts::XSer_LoadPool_UppBnd_Exceed
00852                           , value1
00853                           , value2
00854                           , getMemoryManager());
00855     }
00856 
00857     if (objectTag == 0)
00858         return 0;
00859 
00860     /***
00861      *   A non-null object tag starts from 1 while fLoadPool starts from 0
00862      ***/
00863     return (XSerializable*) fLoadPool->elementAt(objectTag - 1);
00864 }
00865 
00866 void XSerializeEngine::addLoadPool(void* const objToAdd)
00867 {
00868 
00869     TEST_THROW_ARG2( (fLoadPool->size() != fObjectCount)
00870                , fObjectCount
00871                , fLoadPool->size()
00872                , XMLExcepts::XSer_LoadPool_NoTally_ObjCnt
00873                )
00874 
00875     pumpCount();
00876     fLoadPool->addElement(objToAdd);
00877 
00878 }
00879 
00880 void XSerializeEngine::pumpCount()
00881 {
00882     if (fObjectCount >= fgMaxObjectCount)
00883     {
00884       XMLCh value1[64];
00885       XMLCh value2[64];
00886       XMLString::sizeToText(fObjectCount, value1, 65, 10, getMemoryManager());
00887       XMLString::binToText(fgMaxObjectCount, value2, 65, 10, getMemoryManager());
00888       ThrowXMLwithMemMgr2(XSerializationException
00889                           , XMLExcepts::XSer_ObjCount_UppBnd_Exceed
00890                           , value1
00891                           , value2
00892                           , getMemoryManager());
00893     }
00894 
00895     fObjectCount++;
00896 
00897 }
00898 
00899 // ---------------------------------------------------------------------------
00900 //  Buffer Opertions
00901 // ---------------------------------------------------------------------------
00902 /***
00903  *
00904  *  Though client may need only miniBytesNeeded, we always request
00905  *  a full size reading from our inputStream.
00906  *
00907  *  Whatever possibly left in the buffer is abandoned, such as in
00908  *  the case of CheckAndFillBuffer()
00909  *
00910  ***/
00911 void XSerializeEngine::fillBuffer()
00912 {
00913     ensureLoading();
00914     ensureLoadBuffer();
00915 
00916     resetBuffer();
00917 
00918     XMLSize_t bytesRead = fInputStream->readBytes(fBufStart, fBufSize);
00919 
00920     /***
00921      * InputStream MUST fill in the exact amount of bytes as requested
00922      * to do: combine the checking and create a new exception code later
00923     ***/
00924     TEST_THROW_ARG2( (bytesRead < fBufSize)
00925                , bytesRead
00926                , fBufSize
00927                , XMLExcepts::XSer_InStream_Read_LT_Req
00928                )
00929 
00930     TEST_THROW_ARG2( (bytesRead > fBufSize)
00931                , bytesRead
00932                , fBufSize
00933                , XMLExcepts::XSer_InStream_Read_OverFlow
00934                )
00935 
00936     fBufLoadMax = fBufStart + fBufSize;
00937     fBufCur     = fBufStart;
00938 
00939     ensureLoadBuffer();
00940 
00941     fBufCount++;
00942 }
00943 
00944 /***
00945  *
00946  *  Flush out whatever left in the buffer, from
00947  *  fBufStart to fBufEnd.
00948  *
00949  ***/
00950 void XSerializeEngine::flushBuffer()
00951 {
00952     ensureStoring();
00953     ensureStoreBuffer();
00954 
00955     fOutputStream->writeBytes(fBufStart, fBufSize);
00956     fBufCur = fBufStart;
00957 
00958     resetBuffer();
00959     ensureStoreBuffer();
00960 
00961     fBufCount++;
00962 }
00963 
00964 inline void XSerializeEngine::checkAndFlushBuffer(XMLSize_t bytesNeedToWrite)
00965 {
00966     TEST_THROW_ARG1( (bytesNeedToWrite <= 0)
00967                    , bytesNeedToWrite
00968                    , XMLExcepts::XSer_Inv_checkFlushBuffer_Size
00969                    )
00970 
00971     // fBufStart ... fBufCur ...fBufEnd
00972     if ((fBufCur + bytesNeedToWrite) > fBufEnd)
00973         flushBuffer();
00974 }
00975 
00976 inline void XSerializeEngine::checkAndFillBuffer(XMLSize_t bytesNeedToRead)
00977 {
00978 
00979     TEST_THROW_ARG1( (bytesNeedToRead <= 0)
00980                    , bytesNeedToRead
00981                    , XMLExcepts::XSer_Inv_checkFillBuffer_Size
00982                    )
00983 
00984     // fBufStart ... fBufCur ...fBufLoadMax
00985     if ((fBufCur + bytesNeedToRead) > fBufLoadMax)
00986     {
00987         fillBuffer();
00988     }
00989 
00990 }
00991 
00992 inline void XSerializeEngine::ensureStoreBuffer() const
00993 {
00994     XMLSize_t a = (XMLSize_t) (fBufCur - fBufStart);
00995     XMLSize_t b = (XMLSize_t) (fBufEnd - fBufCur);
00996 
00997     TEST_THROW_ARG2 ( !((fBufStart <= fBufCur) && (fBufCur <= fBufEnd))
00998                     , a
00999                     , b
01000                     , XMLExcepts::XSer_StoreBuffer_Violation
01001                     )
01002 
01003 }
01004 
01005 inline void XSerializeEngine::ensureLoadBuffer() const
01006 {
01007     XMLSize_t a = (XMLSize_t) (fBufCur - fBufStart);
01008     XMLSize_t b = (XMLSize_t) (fBufLoadMax - fBufCur);
01009 
01010     TEST_THROW_ARG2 ( !((fBufStart <= fBufCur) && (fBufCur <= fBufLoadMax))
01011                     , a
01012                     , b
01013                     , XMLExcepts::XSer_LoadBuffer_Violation
01014                     )
01015 
01016 }
01017 
01018 inline void XSerializeEngine::ensurePointer(void* const ptr) const
01019 {
01020 
01021     TEST_THROW_ARG1( (ptr == 0)
01022                    , 0
01023                    , XMLExcepts::XSer_Inv_Null_Pointer
01024                    )
01025 
01026 }
01027 
01028 inline void XSerializeEngine::resetBuffer()
01029 {
01030     memset(fBufStart, 0, fBufSize * sizeof(XMLByte));
01031 }
01032 
01033 // ---------------------------------------------------------------------------
01034 //  Template object
01035 // ---------------------------------------------------------------------------
01036 /***
01037  *
01038  *  Search the store pool to see if the address has been seen before or not.
01039  *
01040  *  If yes, write the corresponding object Tag to the internal buffer
01041  *  and return true.
01042  *
01043  *  Otherwise, add the address to the store pool and return false
01044  *  to notifiy the client application code to store the template object.
01045  *
01046  ***/
01047 bool XSerializeEngine::needToStoreObject(void* const  templateObjectToWrite)
01048 {
01049     ensureStoring(); //don't ensurePointer here !!!
01050 
01051     XSerializedObjectId_t   objIndex = 0;
01052 
01053         if (!templateObjectToWrite)
01054         {
01055                 *this << fgNullObjectTag; // null pointer
01056         return false;
01057         }
01058     else if (0 != (objIndex = lookupStorePool(templateObjectToWrite)))
01059         {
01060         *this << objIndex;         // write an object reference tag
01061         return false;
01062         }
01063         else
01064         {
01065         *this << fgTemplateObjTag;            // write fgTemplateObjTag to denote that actual
01066                                               // template object follows
01067         addStorePool(templateObjectToWrite); // put the address into StorePool
01068         return true;
01069         }
01070 
01071 }
01072 
01073 bool XSerializeEngine::needToLoadObject(void**  templateObjectToRead)
01074 {
01075     ensureLoading();
01076 
01077         XSerializedObjectId_t obTag;
01078 
01079     *this >> obTag;
01080 
01081         if (obTag == fgTemplateObjTag)
01082         {
01083         /***
01084          * what follows fgTemplateObjTag is the actual template object
01085          * We need the client application to create a template object
01086          * and register it through registerObject(), and deserialize
01087          * template object
01088          ***/
01089         return true;
01090         }
01091         else
01092         {
01093         /***
01094          * We hava a reference to an existing template object, get it.
01095          */
01096         *templateObjectToRead = lookupLoadPool(obTag);
01097         return false;
01098    }
01099 
01100 }
01101 
01102 void XSerializeEngine::registerObject(void*  const templateObjectToRegister)
01103 {
01104     ensureLoading();
01105     addLoadPool(templateObjectToRegister);
01106 }
01107 
01108 XMLGrammarPool* XSerializeEngine::getGrammarPool() const
01109 {
01110     return fGrammarPool;
01111 }
01112 
01113 XMLStringPool* XSerializeEngine::getStringPool() const
01114 {
01115     return fGrammarPool->getURIStringPool();
01116 }
01117 
01118 MemoryManager* XSerializeEngine::getMemoryManager() const
01119 {
01120     //todo: changed to return fGrammarPool->getMemoryManager()
01121     return fGrammarPool ? fGrammarPool->getMemoryManager() : XMLPlatformUtils::fgMemoryManager;
01122 }
01123 
01124 //
01125 // Based on the current position (fBufCur), calculated the needed size
01126 // to read/write
01127 //
01128 inline XMLSize_t XSerializeEngine::alignAdjust(XMLSize_t size) const
01129 {
01130     XMLSize_t remainder = (XMLSize_t) fBufCur % size;
01131     return (remainder == 0) ? 0 : (size - remainder);
01132 }
01133 
01134 // Adjust the fBufCur
01135 inline void XSerializeEngine::alignBufCur(XMLSize_t size)
01136 {
01137     fBufCur+=alignAdjust(size);
01138     assert(((XMLSize_t) fBufCur % size)==0);
01139 }
01140 
01141 inline XMLSize_t XSerializeEngine::calBytesNeeded(XMLSize_t size) const
01142 {
01143     return (alignAdjust(size) + size);
01144 }
01145 
01146 void XSerializeEngine::trace(char* /*funcName*/) const
01147 {
01148     return;
01149 
01150 /*
01151    if (isStoring())
01152         printf("\n funcName=<%s>, storing, count=<%lu>, postion=<%lu>\n", funcName, fBufCount, getBufCurAccumulated());
01153     else
01154         printf("\n funcName=<%s>, loading, count=<%lu>, postion=<%lu>\n", funcName, fBufCount, getBufCurAccumulated());
01155 */
01156 }
01157 
01158 XERCES_CPP_NAMESPACE_END