1 thilo.boehm 1.1 //%LICENSE////////////////////////////////////////////////////////////////
2 //
3 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 thilo.boehm 1.1 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //////////////////////////////////////////////////////////////////////////
29 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <string.h>
33 #include "Packer.h"
34
35 PEGASUS_NAMESPACE_BEGIN
36
37 static bool _constains16BitChars(const String& x)
38 {
39 const Char16* p = x.getChar16Data();
40 Uint32 n = x.size();
41
42 while (n--)
43 thilo.boehm 1.1 {
44 if (Uint16(*p++) > 0xFF)
45 return true;
46 }
47
48 return false;
49 }
50
51 void Packer::packString(Buffer& out, const String& x)
52 {
53 Uint32 n = x.size();
54
55 if (_constains16BitChars(x))
56 {
57 packUint8(out, 16);
58 packSize(out, n);
59 packChar16(out, x.getChar16Data(), n);
60 }
61 else
62 {
63 packUint8(out, 8);
64 thilo.boehm 1.1 packSize(out, n);
65 const Char16* data = x.getChar16Data();
66
67 for (Uint32 i = 0; i < n; i++)
68 Packer::packUint8(out, (Uint8)data[i]);
69 }
70 }
71
72 void Packer::packSize(Buffer& out, Uint32 x)
73 {
74 // Top two bits indicate the number of bytes used to
75 // pack this size:
76 //
77 // 00 : 1 byte
78 // 01 : 2 bytes
79 // 10 : 4 bytes
80 // 11 : illegal
81
82 if (x > 16383)
83 {
84 // Use four bytes for size (tag == '1')
85 thilo.boehm 1.1 packUint32(out, 0x80000000 | x);
86 }
87 else if (x > 63)
88 {
89 // Use two bytes for size.
90 packUint16(out, 0x4000 | Uint16(x));
91 }
92 else /* x > 1073741823 */
93 {
94 // Use one byte for size.
95 packUint8(out, 0x00 | Uint8(x));
96 }
97 }
98
99 void Packer::unpackSize(const Buffer& in, Uint32& pos, Uint32& x)
100 {
101 // Top two bits form a tag that indicates the number of bytes used to
102 // pack this size:
103 //
104 // 00 : 1 byte
105 // 01 : 2 bytes
106 thilo.boehm 1.1 // 10 : 4 bytes
107 // 11 : illegal
108
109 // Unpack first byte.
110
111 Uint8 byte = Uint8(in[pos++]);
112 Uint8 tag = byte & 0xC0;
113
114 if (!tag)
115 {
116 // One-byte size:
117 x = byte;
118 }
119 else if (tag == 0x80)
120 {
121 // Four-byte size:
122 Uint8 b0 = tag ^ byte;
123 Uint8 b1;
124 Uint8 b2;
125 Uint8 b3;
126
127 thilo.boehm 1.1 Packer::unpackUint8(in, pos, b1);
128 Packer::unpackUint8(in, pos, b2);
129 Packer::unpackUint8(in, pos, b3);
130 Uint32 tmp = (Uint32(b0) << 24) |
131 (Uint32(b1) << 16) |
132 (Uint32(b2) << 8) |
133 (Uint32(b3));
134
135 x = tmp;
136 }
137 else if (tag == 0x40)
138 {
139 // Two-byte size:
140 x = (tag ^ byte) << 8;
141 Packer::unpackUint8(in, pos, byte);
142 x |= byte;
143 }
144 else
145 {
146 PEGASUS_DEBUG_ASSERT(0);
147 }
148 thilo.boehm 1.1
149 PEGASUS_DEBUG_ASSERT(pos <= in.size());
150 }
151
152 template<class T>
153 void _pack_array(Buffer& out, const T* x, Uint32 n)
154 {
155 Uint32 bytes = n * sizeof(T);
156 out.reserveCapacity(out.size() + bytes);
157
158 if (Packer::isLittleEndian())
159 {
160 for (size_t i = 0; i < n; i++)
161 {
162 T tmp = Packer::swap(x[i]);
163 out.append((char*)&tmp, sizeof(tmp));
164 }
165 }
166 else
167 out.append((char*)x, bytes);
168 }
169 thilo.boehm 1.1
170 void Packer::packBoolean(Buffer& out, const Boolean* x, Uint32 n)
171 {
172 out.reserveCapacity(out.size() + n);
173
174 for (size_t i = 0; i < n; i++)
175 {
176 Uint8 tmp = Uint8(x[i]);
177 out.append((char*)&tmp, sizeof(tmp));
178 }
179 }
180
181 void Packer::packUint8(Buffer& out, const Uint8* x, Uint32 n)
182 {
183 out.append((char*)x, n);
184 }
185
186 void Packer::packUint16(Buffer& out, const Uint16* x, Uint32 n)
187 {
188 _pack_array(out, x, n);
189 }
190 thilo.boehm 1.1
191 void Packer::packUint32(Buffer& out, const Uint32* x, Uint32 n)
192 {
193 _pack_array(out, x, n);
194 }
195
196 void Packer::packUint64(Buffer& out, const Uint64* x, Uint32 n)
197 {
198 _pack_array(out, x, n);
199 }
200
201 void Packer::packString(Buffer& out, const String* x, Uint32 n)
202 {
203 for (size_t i = 0; i < n; i++)
204 packString(out, x[i]);
205 }
206
207 void Packer::unpackUint16(
208 const Buffer& in, Uint32& pos, Uint16& x)
209 {
210 memcpy(&x, &in[pos], sizeof(x));
211 thilo.boehm 1.1 pos += sizeof(x);
212
213 if (isLittleEndian())
214 x = Packer::swapUint16(x);
215 }
216
217 void Packer::unpackUint32(
218 const Buffer& in, Uint32& pos, Uint32& x)
219 {
220 memcpy(&x, &in[pos], sizeof(x));
221 pos += sizeof(x);
222
223 if (isLittleEndian())
224 x = Packer::swapUint32(x);
225
226 PEGASUS_DEBUG_ASSERT(pos <= in.size());
227 }
228
229 void Packer::unpackUint64(
230 const Buffer& in, Uint32& pos, Uint64& x)
231 {
232 thilo.boehm 1.1 memcpy(&x, &in[pos], sizeof(x));
233 pos += sizeof(x);
234
235 if (isLittleEndian())
236 x = Packer::swapUint64(x);
237
238 PEGASUS_DEBUG_ASSERT(pos <= in.size());
239 }
240
241 void Packer::unpackString(const Buffer& in, Uint32& pos, String& x)
242 {
243 // Determine whether packed as 8-bit or 16-bit.
244
245 Uint8 bits = Uint8(in[pos++]);
246
247 PEGASUS_DEBUG_ASSERT(bits == 16 || bits == 8);
248
249 // Unpack array size.
250
251 Uint32 n;
252 unpackSize(in, pos, n);
253 thilo.boehm 1.1
254 if (bits & 8)
255 {
256 x.assign(&in[pos], n);
257 pos += n;
258 }
259 else
260 {
261 x.clear();
262 x.reserveCapacity(n);
263
264 for (size_t i = 0; i < n; i++)
265 {
266 Char16 tmp;
267 unpackChar16(in , pos, tmp);
268 x.append(tmp);
269 }
270 }
271
272 PEGASUS_DEBUG_ASSERT(pos <= in.size());
273 }
274 thilo.boehm 1.1
275 void Packer::unpackBoolean(
276 Buffer& in, Uint32& pos, Boolean* x, Uint32 n)
277 {
278 for (size_t i = 0; i < n; i++)
279 unpackBoolean(in, pos, x[i]);
280
281 PEGASUS_DEBUG_ASSERT(pos <= in.size());
282 }
283
284 void Packer::unpackUint8(
285 Buffer& in, Uint32& pos, Uint8* x, Uint32 n)
286 {
287 for (size_t i = 0; i < n; i++)
288 unpackUint8(in, pos, x[i]);
289
290 PEGASUS_DEBUG_ASSERT(pos <= in.size());
291 }
292
293 void Packer::unpackUint16(
294 Buffer& in, Uint32& pos, Uint16* x, Uint32 n)
295 thilo.boehm 1.1 {
296 for (size_t i = 0; i < n; i++)
297 unpackUint16(in, pos, x[i]);
298
299 PEGASUS_DEBUG_ASSERT(pos <= in.size());
300 }
301
302 void Packer::unpackUint32(
303 Buffer& in, Uint32& pos, Uint32* x, Uint32 n)
304 {
305 for (size_t i = 0; i < n; i++)
306 unpackUint32(in, pos, x[i]);
307
308 PEGASUS_DEBUG_ASSERT(pos <= in.size());
309 }
310
311 void Packer::unpackUint64(
312 Buffer& in, Uint32& pos, Uint64* x, Uint32 n)
313 {
314 for (size_t i = 0; i < n; i++)
315 unpackUint64(in, pos, x[i]);
316 thilo.boehm 1.1
317 PEGASUS_DEBUG_ASSERT(pos <= in.size());
318 }
319
320 void Packer::unpackString(
321 Buffer& in, Uint32& pos, String* x, Uint32 n)
322 {
323 for (size_t i = 0; i < n; i++)
324 unpackString(in, pos, x[i]);
325
326 PEGASUS_DEBUG_ASSERT(pos <= in.size());
327 }
328
329 PEGASUS_NAMESPACE_END
|