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