]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSData.cpp
xnu-517.tar.gz
[apple/xnu.git] / libkern / c++ / OSData.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* IOData.m created by rsulack on Thu 25-Sep-1997 */
26
9bccf70c 27#include <string.h>
1c79356b
A
28
29#include <libkern/c++/OSData.h>
30#include <libkern/c++/OSSerialize.h>
31#include <libkern/c++/OSLib.h>
32#include <libkern/c++/OSString.h>
9bccf70c 33#include <string.h>
1c79356b
A
34
35#define super OSObject
36
37OSDefineMetaClassAndStructors(OSData, OSObject)
38OSMetaClassDefineReservedUnused(OSData, 0);
39OSMetaClassDefineReservedUnused(OSData, 1);
40OSMetaClassDefineReservedUnused(OSData, 2);
41OSMetaClassDefineReservedUnused(OSData, 3);
42OSMetaClassDefineReservedUnused(OSData, 4);
43OSMetaClassDefineReservedUnused(OSData, 5);
44OSMetaClassDefineReservedUnused(OSData, 6);
45OSMetaClassDefineReservedUnused(OSData, 7);
46
47#define EXTERNAL ((unsigned int) -1)
48
49#if OSALLOCDEBUG
55e303ae 50extern int debug_container_malloc_size;
1c79356b
A
51#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
52#else
53#define ACCUMSIZE(s)
54#endif
55
56bool OSData::initWithCapacity(unsigned int inCapacity)
57{
58 if (!super::init())
59 return false;
60
55e303ae
A
61 if (data && (!inCapacity || capacity < inCapacity) ) {
62 // clean out old data's storage if it isn't big enough
63 kfree((vm_address_t) data, capacity);
64 data = 0;
65 ACCUMSIZE(-capacity);
66 }
67
68 if (inCapacity && !data) {
1c79356b
A
69 data = (void *) kalloc(inCapacity);
70 if (!data)
71 return false;
55e303ae
A
72 capacity = inCapacity;
73 ACCUMSIZE(inCapacity);
1c79356b
A
74 }
75
76 length = 0;
55e303ae 77 if (inCapacity < 16)
1c79356b 78 capacityIncrement = 16;
55e303ae
A
79 else
80 capacityIncrement = inCapacity;
1c79356b
A
81
82 return true;
83}
84
85bool OSData::initWithBytes(const void *bytes, unsigned int inLength)
86{
87 if ((inLength && !bytes) || !initWithCapacity(inLength))
88 return false;
89
55e303ae
A
90 if (bytes != data)
91 bcopy(bytes, data, inLength);
1c79356b
A
92 length = inLength;
93
94 return true;
95}
96
97bool OSData::initWithBytesNoCopy(void *bytes, unsigned int inLength)
98{
99 if (!super::init())
100 return false;
101
102 length = inLength;
103 capacity = EXTERNAL;
104 data = bytes;
105
106 return true;
107}
108
109bool OSData::initWithData(const OSData *inData)
110{
111 return initWithBytes(inData->data, inData->length);
112}
113
114bool OSData::initWithData(const OSData *inData,
115 unsigned int start, unsigned int inLength)
116{
117 const void *localData = inData->getBytesNoCopy(start, inLength);
118
119 if (localData)
120 return initWithBytes(localData, inLength);
121 else
122 return false;
123}
124
125OSData *OSData::withCapacity(unsigned int inCapacity)
126{
127 OSData *me = new OSData;
128
129 if (me && !me->initWithCapacity(inCapacity)) {
55e303ae 130 me->release();
1c79356b
A
131 return 0;
132 }
133
134 return me;
135}
136
137OSData *OSData::withBytes(const void *bytes, unsigned int inLength)
138{
139 OSData *me = new OSData;
140
141 if (me && !me->initWithBytes(bytes, inLength)) {
55e303ae 142 me->release();
1c79356b
A
143 return 0;
144 }
145 return me;
146}
147
148OSData *OSData::withBytesNoCopy(void *bytes, unsigned int inLength)
149{
150 OSData *me = new OSData;
151
152 if (me && !me->initWithBytesNoCopy(bytes, inLength)) {
55e303ae 153 me->release();
1c79356b
A
154 return 0;
155 }
156
157 return me;
158}
159
160OSData *OSData::withData(const OSData *inData)
161{
162 OSData *me = new OSData;
163
164 if (me && !me->initWithData(inData)) {
55e303ae 165 me->release();
1c79356b
A
166 return 0;
167 }
168
169 return me;
170}
171
172OSData *OSData::withData(const OSData *inData,
173 unsigned int start, unsigned int inLength)
174{
175 OSData *me = new OSData;
176
177 if (me && !me->initWithData(inData, start, inLength)) {
55e303ae 178 me->release();
1c79356b
A
179 return 0;
180 }
181
182 return me;
183}
184
185void OSData::free()
186{
187 if (capacity != EXTERNAL && data && capacity) {
188 kfree((vm_offset_t)data, capacity);
189 ACCUMSIZE( -capacity );
190 }
191 super::free();
192}
193
194unsigned int OSData::getLength() const { return length; }
195unsigned int OSData::getCapacity() const { return capacity; }
196
197unsigned int OSData::getCapacityIncrement() const
198{
199 return capacityIncrement;
200}
201
202unsigned int OSData::setCapacityIncrement(unsigned increment)
203{
204 return capacityIncrement = increment;
205}
206
207unsigned int OSData::ensureCapacity(unsigned int newCapacity)
208{
209 unsigned char * newData;
210
211 if (newCapacity <= capacity)
212 return capacity;
213
214 newCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
215 * capacityIncrement;
216
217 newData = (unsigned char *) kalloc(newCapacity);
218
219 if ( newData ) {
220 bzero(newData + capacity, newCapacity - capacity);
221 if (data) {
222 bcopy(data, newData, capacity);
223 kfree((vm_offset_t)data, capacity);
224 }
225 ACCUMSIZE( newCapacity - capacity );
226 data = (void *) newData;
227 capacity = newCapacity;
228 }
229
230 return capacity;
231}
232
233bool OSData::appendBytes(const void *bytes, unsigned int inLength)
234{
235 unsigned int newSize;
236
55e303ae 237 if (!inLength)
1c79356b
A
238 return true;
239
240 if (capacity == EXTERNAL)
241 return false;
242
243 newSize = length + inLength;
244 if ( (newSize > capacity) && newSize > ensureCapacity(newSize) )
245 return false;
246
55e303ae
A
247 if (bytes)
248 bcopy(bytes, &((unsigned char *)data)[length], inLength);
249 else
250 bzero(&((unsigned char *)data)[length], inLength);
251
1c79356b
A
252 length = newSize;
253
254 return true;
255}
256
257bool OSData::appendByte(unsigned char byte, unsigned int inLength)
258{
259 unsigned int newSize;
260
55e303ae 261 if (!inLength)
1c79356b
A
262 return true;
263
264 if (capacity == EXTERNAL)
265 return false;
266
267 newSize = length + inLength;
268 if ( (newSize > capacity) && newSize > ensureCapacity(newSize) )
269 return false;
270
271 memset(&((unsigned char *)data)[length], byte, inLength);
272 length = newSize;
273
274 return true;
275}
276
277bool OSData::appendBytes(const OSData *other)
278{
279 return appendBytes(other->data, other->length);
280}
281
282const void *OSData::getBytesNoCopy() const
283{
55e303ae 284 if (!length)
1c79356b
A
285 return 0;
286 else
287 return data;
288}
289
290const void *OSData::getBytesNoCopy(unsigned int start,
291 unsigned int inLength) const
292{
293 const void *outData = 0;
294
295 if (length
296 && start < length
297 && (start + inLength) <= length)
298 outData = (const void *) ((char *) data + start);
299
300 return outData;
301}
302
303bool OSData::isEqualTo(const OSData *aData) const
304{
305 unsigned int len;
306
307 len = aData->length;
308 if ( length != len )
309 return false;
310
311 return isEqualTo(aData->data, len);
312}
313
314bool OSData::isEqualTo(const void *someData, unsigned int inLength) const
315{
316 return (length >= inLength) && (bcmp(data, someData, inLength) == 0);
317}
318
319bool OSData::isEqualTo(const OSMetaClassBase *obj) const
320{
321 OSData * data;
322 OSString * str;
323
324 if ((data = OSDynamicCast(OSData, obj)))
325 return isEqualTo(data);
326 else if ((str = OSDynamicCast (OSString, obj)))
327 return isEqualTo(str);
328 else
329 return false;
330}
331
332bool OSData::isEqualTo(const OSString *obj) const
333{
334 const char * aCString;
335 char * dataPtr;
336 unsigned int checkLen = length;
337 unsigned int stringLen;
338
55e303ae 339 if (!obj)
1c79356b
A
340 return false;
341
342 stringLen = obj->getLength ();
343
344 dataPtr = (char *)data;
345
346 if (stringLen != checkLen) {
347
348 // check for the fact that OSData may be a buffer that
349 // that includes a termination byte and will thus have
350 // a length of the actual string length PLUS 1. In this
351 // case we verify that the additional byte is a terminator
352 // and if so count the two lengths as being the same.
353
354 if ( (checkLen - stringLen) == 1) {
355 if (dataPtr[checkLen-1] != 0) // non-zero means not a terminator and thus not likely the same
356 return false;
357 checkLen--;
358 }
359 else
360 return false;
361 }
362
363 aCString = obj->getCStringNoCopy ();
364
365 for ( unsigned int i=0; i < checkLen; i++ ) {
366 if ( *dataPtr++ != aCString[i] )
367 return false;
368 }
369
370 return true;
371}
372
373//this was taken from CFPropertyList.c
374static const char __CFPLDataEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
375
376bool OSData::serialize(OSSerialize *s) const
377{
378 unsigned int i;
379 const unsigned char *p;
380 unsigned char c;
381
382 if (s->previouslySerialized(this)) return true;
383
384 if (!s->addXMLStartTag(this, "data")) return false;
385
386 for (i = 0, p = (unsigned char *)data; i < length; i++, p++) {
387 /* 3 bytes are encoded as 4 */
388 switch (i % 3) {
389 case 0:
390 c = __CFPLDataEncodeTable [ ((p[0] >> 2) & 0x3f)];
391 if (!s->addChar(c)) return false;
392 break;
393 case 1:
394 c = __CFPLDataEncodeTable [ ((((p[-1] << 8) | p[0]) >> 4) & 0x3f)];
395 if (!s->addChar(c)) return false;
396 break;
397 case 2:
398 c = __CFPLDataEncodeTable [ ((((p[-1] << 8) | p[0]) >> 6) & 0x3f)];
399 if (!s->addChar(c)) return false;
400 c = __CFPLDataEncodeTable [ (p[0] & 0x3f)];
401 if (!s->addChar(c)) return false;
402 break;
403 }
404 }
405 switch (i % 3) {
406 case 0:
407 break;
408 case 1:
409 c = __CFPLDataEncodeTable [ ((p[-1] << 4) & 0x30)];
410 if (!s->addChar(c)) return false;
411 if (!s->addChar('=')) return false;
412 if (!s->addChar('=')) return false;
413 break;
414 case 2:
415 c = __CFPLDataEncodeTable [ ((p[-1] << 2) & 0x3c)];
416 if (!s->addChar(c)) return false;
417 if (!s->addChar('=')) return false;
418 break;
419 }
420
421 return s->addXMLEndTag("data");
422}