blocxx
BinarySerialization.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
3 * Copyright (C) 2006, Novell, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of
14 * Vintela, Inc.,
15 * nor Novell, Inc.,
16 * nor the names of its contributors or employees may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *******************************************************************************/
32 
33 
39 #include "blocxx/BLOCXX_config.h"
41 #include "blocxx/AutoPtr.hpp"
42 #include "blocxx/ByteSwap.hpp"
43 #include "blocxx/IOException.hpp"
44 #include "blocxx/Format.hpp"
45 #include <cerrno>
46 
47 namespace BLOCXX_NAMESPACE
48 {
49 
50 namespace BinarySerialization
51 {
53 // STATIC
54 void
55 writeLen(std::streambuf & ostrm, UInt32 len)
56 {
57  // This is ASN.1 length encoding
58  /*
59  * short len if it's less than 128 - one byte giving the len,
60  * with bit 8 0.
61  */
62  if (len < 128)
63  {
64  UInt8 length_byte = static_cast<UInt8>(len);
65  write(ostrm, &length_byte, 1);
66  return;
67  }
68  /*
69  * long len otherwise - one byte with bit 8 set, giving the
70  * length of the length, followed by the length itself.
71  */
72  /* find the first non-all-zero byte */
73  UInt8 lenlen;
74  if (len < (1 << 8))
75  {
76  lenlen = 1;
77  }
78  else if (len < (1 << 16))
79  {
80  lenlen = 2;
81  }
82  else if (len < (1 << 24))
83  {
84  lenlen = 3;
85  }
86  else
87  {
88  lenlen = 4;
89  }
90  UInt8 netlenlen = lenlen | 0x80UL;
91  /* write the length of the length */
92  write(ostrm, &netlenlen, 1);
93  UInt8 netlen[sizeof(len)];
94  for (int j = 0; j < lenlen; j++)
95  {
96  netlen[(sizeof(len)-1) - j] = static_cast<UInt8>(len & 0xffU);
97  len >>= 8;
98  }
99  /* write the length itself */
100  write(ostrm, static_cast<void *>(&netlen[sizeof(len)-lenlen]), lenlen);
101 }
103 // STATIC
104 void
105 readLen(std::streambuf & istrm, UInt32 & len)
106 {
107  // This is ASN.1 length encoding
108  UInt8 lc;
109  read(istrm, lc);
110  if (lc & 0x80U)
111  {
112  UInt8 noctets = lc & 0x7fU;
113  if ( noctets > sizeof(len) )
114  {
115  BLOCXX_THROW(IOException, Format("Failed reading data: length length (%1) is too large (> %2)", static_cast<int>(noctets), sizeof(len)).c_str());
116  }
117  UInt8 netlen[sizeof(len)];
118  read(istrm, static_cast<void *>(netlen), noctets);
119  len = 0;
120  for (int i = 0; i < noctets; i++ )
121  {
122  len <<= 8;
123  len |= netlen[i];
124  }
125  }
126  else
127  {
128  len = lc;
129  }
130 }
132 // STATIC
133 void
134 write(std::streambuf & ostrm, void const * dataOut, size_t dataOutLen)
135 {
136  std::streamsize cnt = dataOutLen;
137  if (ostrm.sputn(static_cast<char const *>(dataOut), cnt) != cnt)
138  {
139  BLOCXX_THROW_ERRNO_MSG(IOException, "Failed writing data");
140  }
141 }
143 // STATIC
144 void
145 verifySignature(std::streambuf & istrm, UInt8 validSig)
146 {
147  UInt8 val;
148  read(istrm, val);
149  if (val != validSig)
150  {
152  Format("Received invalid signature. Got: %1 Expected: %2", Int32(val),
153  Int32(validSig)).c_str());
154  }
155 }
157 // STATIC
158 void
159 writeStringArray(std::streambuf & ostrm, const StringArray * propertyList)
160 {
161  bool nullPropertyList = (propertyList == 0);
162  writeBool(ostrm, nullPropertyList);
163  if (!nullPropertyList)
164  {
165  writeStringArray(ostrm, *propertyList);
166  }
167 }
169 // STATIC
170 void
171 read(std::streambuf & istrm, void * dataIn, size_t dataInLen)
172 {
173  std::streamsize cnt = dataInLen;
174  if (istrm.sgetn(static_cast<char *>(dataIn), cnt) != cnt)
175  {
176  BLOCXX_THROW(IOException, "Failed reading data");
177  }
178 }
179 
180 } // namespace BinarySerialization
181 
182 } // end namespace BLOCXX_NAMESPACE
183