00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00067 verifySignature(istrm, endsig);
00068 done = true;
00069 }
00070 }
00071 }
00073
00074 void
00075 writeLen(std::ostream& ostrm, UInt32 len)
00076 {
00077
00078
00079
00080
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
00090
00091
00092
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
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
00120 write(ostrm, static_cast<void *>(&netlen[sizeof(len)-lenlen]), lenlen);
00121 }
00123
00124 void
00125 readLen(std::istream& istrm, UInt32& len)
00126 {
00127
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
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
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
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
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 }
00198