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