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