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
38
39#include "blocxx/BLOCXX_config.h"
41#include "blocxx/AutoPtr.hpp"
42#include "blocxx/ByteSwap.hpp"
44#include "blocxx/Format.hpp"
45#include <cerrno>
46
47namespace BLOCXX_NAMESPACE
48{
49
51{
53// STATIC
54void
55writeLen(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}
102
103// STATIC
104void
105readLen(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}
131
132// STATIC
133void
134write(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}
142
143// STATIC
144void
145verifySignature(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}
156
157// STATIC
158void
159writeStringArray(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}
168
169// STATIC
170void
171read(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
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
#define BLOCXX_THROW_ERRNO_MSG(exType, msg)
Throw an exception using FILE, LINE, errno and strerror(errno)
void readLen(std::streambuf &istrm, UInt32 &len)
void verifySignature(std::streambuf &istrm, UInt8 validSig)
void read(std::streambuf &istrm, void *dataIn, size_t dataInLen)
void writeStringArray(std::streambuf &ostrm, const StringArray *propertyList)
void write(std::streambuf &ostrm, void const *dataOut, size_t dataOutLen)
void writeLen(std::streambuf &ostrm, UInt32 len)
void writeBool(std::streambuf &ostrm, Bool arg)
Taken from RFC 1321.
unsigned char UInt8
Definition Types.hpp:66
Array< String > StringArray
Definition CommonFwd.hpp:73