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