BinarySerialization.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 *
00008 *  - Redistributions of source code must retain the above copyright notice,
00009 *    this list of conditions and the following disclaimer.
00010 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00032 
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/BinarySerialization.hpp"
00040 #include "blocxx/AutoPtr.hpp"
00041 #include "blocxx/ByteSwap.hpp"
00042 #include "blocxx/IOException.hpp"
00043 #include "blocxx/Format.hpp"
00044 #include <cerrno>
00045 
00046 namespace BLOCXX_NAMESPACE
00047 {
00048 
00049 namespace BinarySerialization
00050 {
00052 template <typename Handler, typename ReaderFunc>
00053 static inline void readEnum(std::istream& istrm, Handler& result,
00054    const ReaderFunc& read, const Int32 beginsig, const Int32 endsig)
00055 {
00056    verifySignature(istrm, beginsig);
00057    bool done = false;
00058    while (!done)
00059    {
00060       try
00061       {
00062          result.handle(read(istrm));
00063       }
00064       catch (const BadSignatureException& e)
00065       {
00066          // read threw because we've read all the objects
00067          verifySignature(istrm, endsig);
00068          done = true;
00069       }
00070    }
00071 }
00073 // STATIC
00074 void
00075 writeLen(std::ostream& ostrm, UInt32 len)
00076 {
00077    // This is ASN.1 length encoding
00078    /*
00079     * short len if it's less than 128 - one byte giving the len,
00080     * with bit 8 0.
00081     */
00082    if ( len <= 127 )
00083    {
00084       UInt8 length_byte = static_cast<UInt8>(len);
00085       write(ostrm, &length_byte, 1);
00086       return;
00087    }
00088    /*
00089     * long len otherwise - one byte with bit 8 set, giving the
00090     * length of the length, followed by the length itself.
00091     */
00092    /* find the first non-all-zero byte */
00093    UInt8 lenlen;
00094    if (len <= 255)
00095    {
00096       lenlen = 1;
00097    }
00098    else if (len <= 65536)
00099    {
00100       lenlen = 2;
00101    }
00102    else if (len <= 16777216)
00103    {
00104       lenlen = 3;
00105    }
00106    else
00107    {
00108       lenlen = 4;
00109    }
00110    UInt8 netlenlen = lenlen | 0x80UL;
00111    /* write the length of the length */
00112    write(ostrm, &netlenlen, 1);
00113    UInt8 netlen[sizeof(len)];
00114    for (int j = 0; j < lenlen; j++)
00115    {
00116       netlen[(sizeof(len)-1) - j] = static_cast<UInt8>(len & 0xffU);
00117       len >>= 8;
00118    }
00119    /* write the length itself */
00120    write(ostrm, static_cast<void *>(&netlen[sizeof(len)-lenlen]), lenlen);
00121 }
00123 // STATIC
00124 void
00125 readLen(std::istream& istrm, UInt32& len)
00126 {
00127    // This is ASN.1 length encoding
00128    UInt8 lc;
00129    read(istrm, lc);
00130    if (lc & 0x80U) 
00131    {
00132       UInt8 noctets = lc & 0x7fU;
00133       if ( noctets > sizeof(len) ) {
00134          BLOCXX_THROW(IOException, Format("Failed reading data: length length (%1) is too large (> %2)", noctets, sizeof(len)).c_str());
00135       }
00136       UInt8 netlen[sizeof(len)];
00137       read(istrm, static_cast<void *>(netlen), noctets);
00138       len = 0;
00139       for (int i = 0; i < noctets; i++ ) {
00140          len <<= 8;
00141          len |= netlen[i];
00142       }
00143    } else {
00144       len = lc;
00145    }
00146 }
00148 // STATIC
00149 void
00150 write(std::ostream& ostrm, const void* dataOut,
00151    int dataOutLen)
00152 {
00153    if (!ostrm.write(reinterpret_cast<const char*>(dataOut), dataOutLen))
00154    {
00155       BLOCXX_THROW_ERRNO_MSG(IOException, "Failed writing data");
00156    }
00157 }
00159 // STATIC
00160 void
00161 verifySignature(std::istream& istrm, UInt8 validSig)
00162 {
00163    UInt8 val;
00164    read(istrm, val);
00165    if (val != validSig)
00166    {
00167       BLOCXX_THROW(BadSignatureException,
00168          Format("Received invalid signature. Got: %1 Expected: %2", Int32(val),
00169             Int32(validSig)).c_str());
00170    }
00171 }
00173 // STATIC
00174 void
00175 writeStringArray(std::ostream& ostrm,
00176    const StringArray* propertyList)
00177 {
00178    bool nullPropertyList = (propertyList == 0);
00179    writeBool(ostrm, nullPropertyList);
00180    if (!nullPropertyList)
00181    {
00182       writeStringArray(ostrm, *propertyList);
00183    }
00184 }
00186 // STATIC
00187 void
00188 read(std::istream& istrm, void* dataIn, int dataInLen)
00189 {
00190    if (!istrm.read(reinterpret_cast<char*>(dataIn), dataInLen))
00191    {
00192       BLOCXX_THROW_ERRNO_MSG(IOException, "Failed reading data");
00193    }
00194 }
00195 }
00196 
00197 } // end namespace BLOCXX_NAMESPACE
00198 

Generated on Fri Jun 16 15:39:08 2006 for blocxx by  doxygen 1.4.6