1*e7776783SApple OSS Distributions /*
2*e7776783SApple OSS Distributions * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3*e7776783SApple OSS Distributions *
4*e7776783SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*e7776783SApple OSS Distributions *
6*e7776783SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*e7776783SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*e7776783SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*e7776783SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*e7776783SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*e7776783SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*e7776783SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*e7776783SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*e7776783SApple OSS Distributions *
15*e7776783SApple OSS Distributions * Please obtain a copy of the License at
16*e7776783SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*e7776783SApple OSS Distributions *
18*e7776783SApple OSS Distributions * The Original Code and all software distributed under the License are
19*e7776783SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*e7776783SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*e7776783SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*e7776783SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*e7776783SApple OSS Distributions * Please see the License for the specific language governing rights and
24*e7776783SApple OSS Distributions * limitations under the License.
25*e7776783SApple OSS Distributions *
26*e7776783SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*e7776783SApple OSS Distributions */
28*e7776783SApple OSS Distributions /* IOData.m created by rsulack on Thu 25-Sep-1997 */
29*e7776783SApple OSS Distributions
30*e7776783SApple OSS Distributions #include <string.h>
31*e7776783SApple OSS Distributions
32*e7776783SApple OSS Distributions #include <vm/vm_kern.h>
33*e7776783SApple OSS Distributions
34*e7776783SApple OSS Distributions #define IOKIT_ENABLE_SHARED_PTR
35*e7776783SApple OSS Distributions
36*e7776783SApple OSS Distributions #include <libkern/c++/OSData.h>
37*e7776783SApple OSS Distributions #include <libkern/c++/OSSerialize.h>
38*e7776783SApple OSS Distributions #include <libkern/c++/OSLib.h>
39*e7776783SApple OSS Distributions #include <libkern/c++/OSString.h>
40*e7776783SApple OSS Distributions #include <IOKit/IOLib.h>
41*e7776783SApple OSS Distributions
42*e7776783SApple OSS Distributions #define super OSObject
43*e7776783SApple OSS Distributions
44*e7776783SApple OSS Distributions OSDefineMetaClassAndStructorsWithZone(OSData, OSObject, ZC_ZFREE_CLEARMEM)
45*e7776783SApple OSS Distributions OSMetaClassDefineReservedUsedX86(OSData, 0); // setDeallocFunction
46*e7776783SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 1);
47*e7776783SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 2);
48*e7776783SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 3);
49*e7776783SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 4);
50*e7776783SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 5);
51*e7776783SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 6);
52*e7776783SApple OSS Distributions OSMetaClassDefineReservedUnused(OSData, 7);
53*e7776783SApple OSS Distributions
54*e7776783SApple OSS Distributions #define EXTERNAL ((unsigned int) -1)
55*e7776783SApple OSS Distributions
56*e7776783SApple OSS Distributions static SECURITY_READ_ONLY_LATE(vm_map_t) alloc_map;
57*e7776783SApple OSS Distributions __startup_func
58*e7776783SApple OSS Distributions static void
getAllocMap(void)59*e7776783SApple OSS Distributions getAllocMap(void)
60*e7776783SApple OSS Distributions {
61*e7776783SApple OSS Distributions alloc_map = KHEAP_DATA_BUFFERS->kh_fallback_map;
62*e7776783SApple OSS Distributions }
63*e7776783SApple OSS Distributions STARTUP(ZALLOC, STARTUP_RANK_LAST, getAllocMap);
64*e7776783SApple OSS Distributions
65*e7776783SApple OSS Distributions bool
initWithCapacity(unsigned int inCapacity)66*e7776783SApple OSS Distributions OSData::initWithCapacity(unsigned int inCapacity)
67*e7776783SApple OSS Distributions {
68*e7776783SApple OSS Distributions void *_data = NULL;
69*e7776783SApple OSS Distributions
70*e7776783SApple OSS Distributions if (data) {
71*e7776783SApple OSS Distributions OSCONTAINER_ACCUMSIZE(-((size_t)capacity));
72*e7776783SApple OSS Distributions if (!inCapacity || (capacity < inCapacity)) {
73*e7776783SApple OSS Distributions // clean out old data's storage if it isn't big enough
74*e7776783SApple OSS Distributions if (capacity < page_size) {
75*e7776783SApple OSS Distributions kfree_data_container(data, capacity);
76*e7776783SApple OSS Distributions } else {
77*e7776783SApple OSS Distributions kmem_free(alloc_map, (vm_offset_t)data, capacity);
78*e7776783SApple OSS Distributions }
79*e7776783SApple OSS Distributions data = NULL;
80*e7776783SApple OSS Distributions capacity = 0;
81*e7776783SApple OSS Distributions }
82*e7776783SApple OSS Distributions }
83*e7776783SApple OSS Distributions
84*e7776783SApple OSS Distributions if (!super::init()) {
85*e7776783SApple OSS Distributions return false;
86*e7776783SApple OSS Distributions }
87*e7776783SApple OSS Distributions
88*e7776783SApple OSS Distributions if (inCapacity && !data) {
89*e7776783SApple OSS Distributions if (inCapacity < page_size) {
90*e7776783SApple OSS Distributions data = (void *)kalloc_data_container(inCapacity, Z_WAITOK);
91*e7776783SApple OSS Distributions } else {
92*e7776783SApple OSS Distributions kern_return_t kr;
93*e7776783SApple OSS Distributions if (round_page_overflow(inCapacity, &inCapacity)) {
94*e7776783SApple OSS Distributions kr = KERN_RESOURCE_SHORTAGE;
95*e7776783SApple OSS Distributions } else {
96*e7776783SApple OSS Distributions kr = kernel_memory_allocate(alloc_map,
97*e7776783SApple OSS Distributions (vm_offset_t *)&_data, inCapacity,
98*e7776783SApple OSS Distributions 0, KMA_ATOMIC, IOMemoryTag(alloc_map));
99*e7776783SApple OSS Distributions data = _data;
100*e7776783SApple OSS Distributions }
101*e7776783SApple OSS Distributions if (KERN_SUCCESS != kr) {
102*e7776783SApple OSS Distributions data = NULL;
103*e7776783SApple OSS Distributions }
104*e7776783SApple OSS Distributions }
105*e7776783SApple OSS Distributions if (!data) {
106*e7776783SApple OSS Distributions return false;
107*e7776783SApple OSS Distributions }
108*e7776783SApple OSS Distributions capacity = inCapacity;
109*e7776783SApple OSS Distributions }
110*e7776783SApple OSS Distributions OSCONTAINER_ACCUMSIZE(capacity);
111*e7776783SApple OSS Distributions
112*e7776783SApple OSS Distributions length = 0;
113*e7776783SApple OSS Distributions if (inCapacity < 16) {
114*e7776783SApple OSS Distributions capacityIncrement = 16;
115*e7776783SApple OSS Distributions } else {
116*e7776783SApple OSS Distributions capacityIncrement = inCapacity;
117*e7776783SApple OSS Distributions }
118*e7776783SApple OSS Distributions
119*e7776783SApple OSS Distributions return true;
120*e7776783SApple OSS Distributions }
121*e7776783SApple OSS Distributions
122*e7776783SApple OSS Distributions bool
initWithBytes(const void * bytes,unsigned int inLength)123*e7776783SApple OSS Distributions OSData::initWithBytes(const void *bytes, unsigned int inLength)
124*e7776783SApple OSS Distributions {
125*e7776783SApple OSS Distributions if ((inLength && !bytes) || !initWithCapacity(inLength)) {
126*e7776783SApple OSS Distributions return false;
127*e7776783SApple OSS Distributions }
128*e7776783SApple OSS Distributions
129*e7776783SApple OSS Distributions if (bytes != data) {
130*e7776783SApple OSS Distributions bcopy(bytes, data, inLength);
131*e7776783SApple OSS Distributions }
132*e7776783SApple OSS Distributions length = inLength;
133*e7776783SApple OSS Distributions
134*e7776783SApple OSS Distributions return true;
135*e7776783SApple OSS Distributions }
136*e7776783SApple OSS Distributions
137*e7776783SApple OSS Distributions bool
initWithBytesNoCopy(void * bytes,unsigned int inLength)138*e7776783SApple OSS Distributions OSData::initWithBytesNoCopy(void *bytes, unsigned int inLength)
139*e7776783SApple OSS Distributions {
140*e7776783SApple OSS Distributions if (!super::init()) {
141*e7776783SApple OSS Distributions return false;
142*e7776783SApple OSS Distributions }
143*e7776783SApple OSS Distributions
144*e7776783SApple OSS Distributions length = inLength;
145*e7776783SApple OSS Distributions capacity = EXTERNAL;
146*e7776783SApple OSS Distributions data = bytes;
147*e7776783SApple OSS Distributions
148*e7776783SApple OSS Distributions return true;
149*e7776783SApple OSS Distributions }
150*e7776783SApple OSS Distributions
151*e7776783SApple OSS Distributions bool
initWithData(const OSData * inData)152*e7776783SApple OSS Distributions OSData::initWithData(const OSData *inData)
153*e7776783SApple OSS Distributions {
154*e7776783SApple OSS Distributions return initWithBytes(inData->data, inData->length);
155*e7776783SApple OSS Distributions }
156*e7776783SApple OSS Distributions
157*e7776783SApple OSS Distributions bool
initWithData(const OSData * inData,unsigned int start,unsigned int inLength)158*e7776783SApple OSS Distributions OSData::initWithData(const OSData *inData,
159*e7776783SApple OSS Distributions unsigned int start, unsigned int inLength)
160*e7776783SApple OSS Distributions {
161*e7776783SApple OSS Distributions const void *localData = inData->getBytesNoCopy(start, inLength);
162*e7776783SApple OSS Distributions
163*e7776783SApple OSS Distributions if (localData) {
164*e7776783SApple OSS Distributions return initWithBytes(localData, inLength);
165*e7776783SApple OSS Distributions } else {
166*e7776783SApple OSS Distributions return false;
167*e7776783SApple OSS Distributions }
168*e7776783SApple OSS Distributions }
169*e7776783SApple OSS Distributions
170*e7776783SApple OSS Distributions OSSharedPtr<OSData>
withCapacity(unsigned int inCapacity)171*e7776783SApple OSS Distributions OSData::withCapacity(unsigned int inCapacity)
172*e7776783SApple OSS Distributions {
173*e7776783SApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
174*e7776783SApple OSS Distributions
175*e7776783SApple OSS Distributions if (me && !me->initWithCapacity(inCapacity)) {
176*e7776783SApple OSS Distributions return nullptr;
177*e7776783SApple OSS Distributions }
178*e7776783SApple OSS Distributions
179*e7776783SApple OSS Distributions return me;
180*e7776783SApple OSS Distributions }
181*e7776783SApple OSS Distributions
182*e7776783SApple OSS Distributions OSSharedPtr<OSData>
withBytes(const void * bytes,unsigned int inLength)183*e7776783SApple OSS Distributions OSData::withBytes(const void *bytes, unsigned int inLength)
184*e7776783SApple OSS Distributions {
185*e7776783SApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
186*e7776783SApple OSS Distributions
187*e7776783SApple OSS Distributions if (me && !me->initWithBytes(bytes, inLength)) {
188*e7776783SApple OSS Distributions return nullptr;
189*e7776783SApple OSS Distributions }
190*e7776783SApple OSS Distributions return me;
191*e7776783SApple OSS Distributions }
192*e7776783SApple OSS Distributions
193*e7776783SApple OSS Distributions OSSharedPtr<OSData>
withBytesNoCopy(void * bytes,unsigned int inLength)194*e7776783SApple OSS Distributions OSData::withBytesNoCopy(void *bytes, unsigned int inLength)
195*e7776783SApple OSS Distributions {
196*e7776783SApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
197*e7776783SApple OSS Distributions
198*e7776783SApple OSS Distributions if (me && !me->initWithBytesNoCopy(bytes, inLength)) {
199*e7776783SApple OSS Distributions return nullptr;
200*e7776783SApple OSS Distributions }
201*e7776783SApple OSS Distributions
202*e7776783SApple OSS Distributions return me;
203*e7776783SApple OSS Distributions }
204*e7776783SApple OSS Distributions
205*e7776783SApple OSS Distributions OSSharedPtr<OSData>
withData(const OSData * inData)206*e7776783SApple OSS Distributions OSData::withData(const OSData *inData)
207*e7776783SApple OSS Distributions {
208*e7776783SApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
209*e7776783SApple OSS Distributions
210*e7776783SApple OSS Distributions if (me && !me->initWithData(inData)) {
211*e7776783SApple OSS Distributions return nullptr;
212*e7776783SApple OSS Distributions }
213*e7776783SApple OSS Distributions
214*e7776783SApple OSS Distributions return me;
215*e7776783SApple OSS Distributions }
216*e7776783SApple OSS Distributions
217*e7776783SApple OSS Distributions OSSharedPtr<OSData>
withData(const OSData * inData,unsigned int start,unsigned int inLength)218*e7776783SApple OSS Distributions OSData::withData(const OSData *inData,
219*e7776783SApple OSS Distributions unsigned int start, unsigned int inLength)
220*e7776783SApple OSS Distributions {
221*e7776783SApple OSS Distributions OSSharedPtr<OSData> me = OSMakeShared<OSData>();
222*e7776783SApple OSS Distributions
223*e7776783SApple OSS Distributions if (me && !me->initWithData(inData, start, inLength)) {
224*e7776783SApple OSS Distributions return nullptr;
225*e7776783SApple OSS Distributions }
226*e7776783SApple OSS Distributions
227*e7776783SApple OSS Distributions return me;
228*e7776783SApple OSS Distributions }
229*e7776783SApple OSS Distributions
230*e7776783SApple OSS Distributions void
free()231*e7776783SApple OSS Distributions OSData::free()
232*e7776783SApple OSS Distributions {
233*e7776783SApple OSS Distributions if ((capacity != EXTERNAL) && data && capacity) {
234*e7776783SApple OSS Distributions if (capacity < page_size) {
235*e7776783SApple OSS Distributions kfree_data_container(data, capacity);
236*e7776783SApple OSS Distributions } else {
237*e7776783SApple OSS Distributions kmem_free(alloc_map, (vm_offset_t)data, capacity);
238*e7776783SApple OSS Distributions }
239*e7776783SApple OSS Distributions OSCONTAINER_ACCUMSIZE( -((size_t)capacity));
240*e7776783SApple OSS Distributions } else if (capacity == EXTERNAL) {
241*e7776783SApple OSS Distributions DeallocFunction freemem = reserved ? reserved->deallocFunction : NULL;
242*e7776783SApple OSS Distributions if (freemem && data && length) {
243*e7776783SApple OSS Distributions freemem(data, length);
244*e7776783SApple OSS Distributions }
245*e7776783SApple OSS Distributions }
246*e7776783SApple OSS Distributions if (reserved) {
247*e7776783SApple OSS Distributions kfree_type(ExpansionData, reserved);
248*e7776783SApple OSS Distributions }
249*e7776783SApple OSS Distributions super::free();
250*e7776783SApple OSS Distributions }
251*e7776783SApple OSS Distributions
252*e7776783SApple OSS Distributions unsigned int
getLength() const253*e7776783SApple OSS Distributions OSData::getLength() const
254*e7776783SApple OSS Distributions {
255*e7776783SApple OSS Distributions return length;
256*e7776783SApple OSS Distributions }
257*e7776783SApple OSS Distributions unsigned int
getCapacity() const258*e7776783SApple OSS Distributions OSData::getCapacity() const
259*e7776783SApple OSS Distributions {
260*e7776783SApple OSS Distributions return capacity;
261*e7776783SApple OSS Distributions }
262*e7776783SApple OSS Distributions
263*e7776783SApple OSS Distributions unsigned int
getCapacityIncrement() const264*e7776783SApple OSS Distributions OSData::getCapacityIncrement() const
265*e7776783SApple OSS Distributions {
266*e7776783SApple OSS Distributions return capacityIncrement;
267*e7776783SApple OSS Distributions }
268*e7776783SApple OSS Distributions
269*e7776783SApple OSS Distributions unsigned int
setCapacityIncrement(unsigned increment)270*e7776783SApple OSS Distributions OSData::setCapacityIncrement(unsigned increment)
271*e7776783SApple OSS Distributions {
272*e7776783SApple OSS Distributions return capacityIncrement = increment;
273*e7776783SApple OSS Distributions }
274*e7776783SApple OSS Distributions
275*e7776783SApple OSS Distributions // xx-review: does not check for capacity == EXTERNAL
276*e7776783SApple OSS Distributions
277*e7776783SApple OSS Distributions unsigned int
ensureCapacity(unsigned int newCapacity)278*e7776783SApple OSS Distributions OSData::ensureCapacity(unsigned int newCapacity)
279*e7776783SApple OSS Distributions {
280*e7776783SApple OSS Distributions unsigned char * newData;
281*e7776783SApple OSS Distributions unsigned int finalCapacity;
282*e7776783SApple OSS Distributions void * copydata;
283*e7776783SApple OSS Distributions kern_return_t kr;
284*e7776783SApple OSS Distributions
285*e7776783SApple OSS Distributions if (newCapacity <= capacity) {
286*e7776783SApple OSS Distributions return capacity;
287*e7776783SApple OSS Distributions }
288*e7776783SApple OSS Distributions
289*e7776783SApple OSS Distributions finalCapacity = (((newCapacity - 1) / capacityIncrement) + 1)
290*e7776783SApple OSS Distributions * capacityIncrement;
291*e7776783SApple OSS Distributions
292*e7776783SApple OSS Distributions // integer overflow check
293*e7776783SApple OSS Distributions if (finalCapacity < newCapacity) {
294*e7776783SApple OSS Distributions return capacity;
295*e7776783SApple OSS Distributions }
296*e7776783SApple OSS Distributions
297*e7776783SApple OSS Distributions copydata = data;
298*e7776783SApple OSS Distributions
299*e7776783SApple OSS Distributions if (finalCapacity >= page_size) {
300*e7776783SApple OSS Distributions // round up
301*e7776783SApple OSS Distributions finalCapacity = round_page_32(finalCapacity);
302*e7776783SApple OSS Distributions // integer overflow check
303*e7776783SApple OSS Distributions if (finalCapacity < newCapacity) {
304*e7776783SApple OSS Distributions return capacity;
305*e7776783SApple OSS Distributions }
306*e7776783SApple OSS Distributions if (capacity >= page_size) {
307*e7776783SApple OSS Distributions copydata = NULL;
308*e7776783SApple OSS Distributions kr = kmem_realloc(alloc_map,
309*e7776783SApple OSS Distributions (vm_offset_t)data,
310*e7776783SApple OSS Distributions capacity,
311*e7776783SApple OSS Distributions (vm_offset_t *)&newData,
312*e7776783SApple OSS Distributions finalCapacity,
313*e7776783SApple OSS Distributions IOMemoryTag(alloc_map));
314*e7776783SApple OSS Distributions } else {
315*e7776783SApple OSS Distributions kr = kernel_memory_allocate(alloc_map, (vm_offset_t *)&newData,
316*e7776783SApple OSS Distributions finalCapacity, 0, KMA_ATOMIC, IOMemoryTag(alloc_map));
317*e7776783SApple OSS Distributions }
318*e7776783SApple OSS Distributions if (KERN_SUCCESS != kr) {
319*e7776783SApple OSS Distributions newData = NULL;
320*e7776783SApple OSS Distributions }
321*e7776783SApple OSS Distributions } else {
322*e7776783SApple OSS Distributions newData = (unsigned char *)kalloc_data_container(finalCapacity, Z_WAITOK);
323*e7776783SApple OSS Distributions }
324*e7776783SApple OSS Distributions
325*e7776783SApple OSS Distributions if (newData) {
326*e7776783SApple OSS Distributions bzero(newData + capacity, finalCapacity - capacity);
327*e7776783SApple OSS Distributions if (copydata) {
328*e7776783SApple OSS Distributions bcopy(copydata, newData, capacity);
329*e7776783SApple OSS Distributions }
330*e7776783SApple OSS Distributions if (data) {
331*e7776783SApple OSS Distributions if (capacity < page_size) {
332*e7776783SApple OSS Distributions kfree_data_container(data, capacity);
333*e7776783SApple OSS Distributions } else {
334*e7776783SApple OSS Distributions kmem_free(alloc_map, (vm_offset_t)data, capacity);
335*e7776783SApple OSS Distributions }
336*e7776783SApple OSS Distributions }
337*e7776783SApple OSS Distributions OSCONTAINER_ACCUMSIZE(((size_t)finalCapacity) - ((size_t)capacity));
338*e7776783SApple OSS Distributions data = (void *) newData;
339*e7776783SApple OSS Distributions capacity = finalCapacity;
340*e7776783SApple OSS Distributions }
341*e7776783SApple OSS Distributions
342*e7776783SApple OSS Distributions return capacity;
343*e7776783SApple OSS Distributions }
344*e7776783SApple OSS Distributions
345*e7776783SApple OSS Distributions bool
appendBytes(const void * bytes,unsigned int inLength)346*e7776783SApple OSS Distributions OSData::appendBytes(const void *bytes, unsigned int inLength)
347*e7776783SApple OSS Distributions {
348*e7776783SApple OSS Distributions unsigned int newSize;
349*e7776783SApple OSS Distributions
350*e7776783SApple OSS Distributions if (!inLength) {
351*e7776783SApple OSS Distributions return true;
352*e7776783SApple OSS Distributions }
353*e7776783SApple OSS Distributions
354*e7776783SApple OSS Distributions if (capacity == EXTERNAL) {
355*e7776783SApple OSS Distributions return false;
356*e7776783SApple OSS Distributions }
357*e7776783SApple OSS Distributions
358*e7776783SApple OSS Distributions if (os_add_overflow(length, inLength, &newSize)) {
359*e7776783SApple OSS Distributions return false;
360*e7776783SApple OSS Distributions }
361*e7776783SApple OSS Distributions
362*e7776783SApple OSS Distributions if ((newSize > capacity) && newSize > ensureCapacity(newSize)) {
363*e7776783SApple OSS Distributions return false;
364*e7776783SApple OSS Distributions }
365*e7776783SApple OSS Distributions
366*e7776783SApple OSS Distributions if (bytes) {
367*e7776783SApple OSS Distributions bcopy(bytes, &((unsigned char *)data)[length], inLength);
368*e7776783SApple OSS Distributions } else {
369*e7776783SApple OSS Distributions bzero(&((unsigned char *)data)[length], inLength);
370*e7776783SApple OSS Distributions }
371*e7776783SApple OSS Distributions
372*e7776783SApple OSS Distributions length = newSize;
373*e7776783SApple OSS Distributions
374*e7776783SApple OSS Distributions return true;
375*e7776783SApple OSS Distributions }
376*e7776783SApple OSS Distributions
377*e7776783SApple OSS Distributions bool
appendByte(unsigned char byte,unsigned int inLength)378*e7776783SApple OSS Distributions OSData::appendByte(unsigned char byte, unsigned int inLength)
379*e7776783SApple OSS Distributions {
380*e7776783SApple OSS Distributions unsigned int newSize;
381*e7776783SApple OSS Distributions
382*e7776783SApple OSS Distributions if (!inLength) {
383*e7776783SApple OSS Distributions return true;
384*e7776783SApple OSS Distributions }
385*e7776783SApple OSS Distributions
386*e7776783SApple OSS Distributions if (capacity == EXTERNAL) {
387*e7776783SApple OSS Distributions return false;
388*e7776783SApple OSS Distributions }
389*e7776783SApple OSS Distributions
390*e7776783SApple OSS Distributions if (os_add_overflow(length, inLength, &newSize)) {
391*e7776783SApple OSS Distributions return false;
392*e7776783SApple OSS Distributions }
393*e7776783SApple OSS Distributions
394*e7776783SApple OSS Distributions if ((newSize > capacity) && newSize > ensureCapacity(newSize)) {
395*e7776783SApple OSS Distributions return false;
396*e7776783SApple OSS Distributions }
397*e7776783SApple OSS Distributions
398*e7776783SApple OSS Distributions memset(&((unsigned char *)data)[length], byte, inLength);
399*e7776783SApple OSS Distributions length = newSize;
400*e7776783SApple OSS Distributions
401*e7776783SApple OSS Distributions return true;
402*e7776783SApple OSS Distributions }
403*e7776783SApple OSS Distributions
404*e7776783SApple OSS Distributions bool
appendBytes(const OSData * other)405*e7776783SApple OSS Distributions OSData::appendBytes(const OSData *other)
406*e7776783SApple OSS Distributions {
407*e7776783SApple OSS Distributions return appendBytes(other->data, other->length);
408*e7776783SApple OSS Distributions }
409*e7776783SApple OSS Distributions
410*e7776783SApple OSS Distributions const void *
getBytesNoCopy() const411*e7776783SApple OSS Distributions OSData::getBytesNoCopy() const
412*e7776783SApple OSS Distributions {
413*e7776783SApple OSS Distributions if (!length) {
414*e7776783SApple OSS Distributions return NULL;
415*e7776783SApple OSS Distributions } else {
416*e7776783SApple OSS Distributions return data;
417*e7776783SApple OSS Distributions }
418*e7776783SApple OSS Distributions }
419*e7776783SApple OSS Distributions
420*e7776783SApple OSS Distributions const void *
getBytesNoCopy(unsigned int start,unsigned int inLength) const421*e7776783SApple OSS Distributions OSData::getBytesNoCopy(unsigned int start,
422*e7776783SApple OSS Distributions unsigned int inLength) const
423*e7776783SApple OSS Distributions {
424*e7776783SApple OSS Distributions const void *outData = NULL;
425*e7776783SApple OSS Distributions
426*e7776783SApple OSS Distributions if (length
427*e7776783SApple OSS Distributions && start < length
428*e7776783SApple OSS Distributions && (start + inLength) >= inLength // overflow check
429*e7776783SApple OSS Distributions && (start + inLength) <= length) {
430*e7776783SApple OSS Distributions outData = (const void *) ((char *) data + start);
431*e7776783SApple OSS Distributions }
432*e7776783SApple OSS Distributions
433*e7776783SApple OSS Distributions return outData;
434*e7776783SApple OSS Distributions }
435*e7776783SApple OSS Distributions
436*e7776783SApple OSS Distributions bool
isEqualTo(const OSData * aData) const437*e7776783SApple OSS Distributions OSData::isEqualTo(const OSData *aData) const
438*e7776783SApple OSS Distributions {
439*e7776783SApple OSS Distributions unsigned int len;
440*e7776783SApple OSS Distributions
441*e7776783SApple OSS Distributions len = aData->length;
442*e7776783SApple OSS Distributions if (length != len) {
443*e7776783SApple OSS Distributions return false;
444*e7776783SApple OSS Distributions }
445*e7776783SApple OSS Distributions
446*e7776783SApple OSS Distributions return isEqualTo(aData->data, len);
447*e7776783SApple OSS Distributions }
448*e7776783SApple OSS Distributions
449*e7776783SApple OSS Distributions bool
isEqualTo(const void * someData,unsigned int inLength) const450*e7776783SApple OSS Distributions OSData::isEqualTo(const void *someData, unsigned int inLength) const
451*e7776783SApple OSS Distributions {
452*e7776783SApple OSS Distributions return (length >= inLength) && (bcmp(data, someData, inLength) == 0);
453*e7776783SApple OSS Distributions }
454*e7776783SApple OSS Distributions
455*e7776783SApple OSS Distributions bool
isEqualTo(const OSMetaClassBase * obj) const456*e7776783SApple OSS Distributions OSData::isEqualTo(const OSMetaClassBase *obj) const
457*e7776783SApple OSS Distributions {
458*e7776783SApple OSS Distributions OSData * otherData;
459*e7776783SApple OSS Distributions OSString * str;
460*e7776783SApple OSS Distributions
461*e7776783SApple OSS Distributions if ((otherData = OSDynamicCast(OSData, obj))) {
462*e7776783SApple OSS Distributions return isEqualTo(otherData);
463*e7776783SApple OSS Distributions } else if ((str = OSDynamicCast(OSString, obj))) {
464*e7776783SApple OSS Distributions return isEqualTo(str);
465*e7776783SApple OSS Distributions } else {
466*e7776783SApple OSS Distributions return false;
467*e7776783SApple OSS Distributions }
468*e7776783SApple OSS Distributions }
469*e7776783SApple OSS Distributions
470*e7776783SApple OSS Distributions bool
isEqualTo(const OSString * obj) const471*e7776783SApple OSS Distributions OSData::isEqualTo(const OSString *obj) const
472*e7776783SApple OSS Distributions {
473*e7776783SApple OSS Distributions const char * aCString;
474*e7776783SApple OSS Distributions char * dataPtr;
475*e7776783SApple OSS Distributions unsigned int checkLen = length;
476*e7776783SApple OSS Distributions unsigned int stringLen;
477*e7776783SApple OSS Distributions
478*e7776783SApple OSS Distributions if (!obj) {
479*e7776783SApple OSS Distributions return false;
480*e7776783SApple OSS Distributions }
481*e7776783SApple OSS Distributions
482*e7776783SApple OSS Distributions stringLen = obj->getLength();
483*e7776783SApple OSS Distributions
484*e7776783SApple OSS Distributions dataPtr = (char *)data;
485*e7776783SApple OSS Distributions
486*e7776783SApple OSS Distributions if (stringLen != checkLen) {
487*e7776783SApple OSS Distributions // check for the fact that OSData may be a buffer that
488*e7776783SApple OSS Distributions // that includes a termination byte and will thus have
489*e7776783SApple OSS Distributions // a length of the actual string length PLUS 1. In this
490*e7776783SApple OSS Distributions // case we verify that the additional byte is a terminator
491*e7776783SApple OSS Distributions // and if so count the two lengths as being the same.
492*e7776783SApple OSS Distributions
493*e7776783SApple OSS Distributions if ((checkLen - stringLen) == 1) {
494*e7776783SApple OSS Distributions if (dataPtr[checkLen - 1] != 0) { // non-zero means not a terminator and thus not likely the same
495*e7776783SApple OSS Distributions return false;
496*e7776783SApple OSS Distributions }
497*e7776783SApple OSS Distributions checkLen--;
498*e7776783SApple OSS Distributions } else {
499*e7776783SApple OSS Distributions return false;
500*e7776783SApple OSS Distributions }
501*e7776783SApple OSS Distributions }
502*e7776783SApple OSS Distributions
503*e7776783SApple OSS Distributions aCString = obj->getCStringNoCopy();
504*e7776783SApple OSS Distributions
505*e7776783SApple OSS Distributions for (unsigned int i = 0; i < checkLen; i++) {
506*e7776783SApple OSS Distributions if (*dataPtr++ != aCString[i]) {
507*e7776783SApple OSS Distributions return false;
508*e7776783SApple OSS Distributions }
509*e7776783SApple OSS Distributions }
510*e7776783SApple OSS Distributions
511*e7776783SApple OSS Distributions return true;
512*e7776783SApple OSS Distributions }
513*e7776783SApple OSS Distributions
514*e7776783SApple OSS Distributions //this was taken from CFPropertyList.c
515*e7776783SApple OSS Distributions static const char __CFPLDataEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
516*e7776783SApple OSS Distributions
517*e7776783SApple OSS Distributions bool
serialize(OSSerialize * s) const518*e7776783SApple OSS Distributions OSData::serialize(OSSerialize *s) const
519*e7776783SApple OSS Distributions {
520*e7776783SApple OSS Distributions unsigned int i;
521*e7776783SApple OSS Distributions const unsigned char *p;
522*e7776783SApple OSS Distributions unsigned char c;
523*e7776783SApple OSS Distributions unsigned int serializeLength;
524*e7776783SApple OSS Distributions
525*e7776783SApple OSS Distributions if (s->previouslySerialized(this)) {
526*e7776783SApple OSS Distributions return true;
527*e7776783SApple OSS Distributions }
528*e7776783SApple OSS Distributions
529*e7776783SApple OSS Distributions if (!s->addXMLStartTag(this, "data")) {
530*e7776783SApple OSS Distributions return false;
531*e7776783SApple OSS Distributions }
532*e7776783SApple OSS Distributions
533*e7776783SApple OSS Distributions serializeLength = length;
534*e7776783SApple OSS Distributions if (reserved && reserved->disableSerialization) {
535*e7776783SApple OSS Distributions serializeLength = 0;
536*e7776783SApple OSS Distributions }
537*e7776783SApple OSS Distributions
538*e7776783SApple OSS Distributions for (i = 0, p = (unsigned char *)data; i < serializeLength; i++, p++) {
539*e7776783SApple OSS Distributions /* 3 bytes are encoded as 4 */
540*e7776783SApple OSS Distributions switch (i % 3) {
541*e7776783SApple OSS Distributions case 0:
542*e7776783SApple OSS Distributions c = __CFPLDataEncodeTable[((p[0] >> 2) & 0x3f)];
543*e7776783SApple OSS Distributions if (!s->addChar(c)) {
544*e7776783SApple OSS Distributions return false;
545*e7776783SApple OSS Distributions }
546*e7776783SApple OSS Distributions break;
547*e7776783SApple OSS Distributions case 1:
548*e7776783SApple OSS Distributions c = __CFPLDataEncodeTable[((((p[-1] << 8) | p[0]) >> 4) & 0x3f)];
549*e7776783SApple OSS Distributions if (!s->addChar(c)) {
550*e7776783SApple OSS Distributions return false;
551*e7776783SApple OSS Distributions }
552*e7776783SApple OSS Distributions break;
553*e7776783SApple OSS Distributions case 2:
554*e7776783SApple OSS Distributions c = __CFPLDataEncodeTable[((((p[-1] << 8) | p[0]) >> 6) & 0x3f)];
555*e7776783SApple OSS Distributions if (!s->addChar(c)) {
556*e7776783SApple OSS Distributions return false;
557*e7776783SApple OSS Distributions }
558*e7776783SApple OSS Distributions c = __CFPLDataEncodeTable[(p[0] & 0x3f)];
559*e7776783SApple OSS Distributions if (!s->addChar(c)) {
560*e7776783SApple OSS Distributions return false;
561*e7776783SApple OSS Distributions }
562*e7776783SApple OSS Distributions break;
563*e7776783SApple OSS Distributions }
564*e7776783SApple OSS Distributions }
565*e7776783SApple OSS Distributions switch (i % 3) {
566*e7776783SApple OSS Distributions case 0:
567*e7776783SApple OSS Distributions break;
568*e7776783SApple OSS Distributions case 1:
569*e7776783SApple OSS Distributions c = __CFPLDataEncodeTable[((p[-1] << 4) & 0x30)];
570*e7776783SApple OSS Distributions if (!s->addChar(c)) {
571*e7776783SApple OSS Distributions return false;
572*e7776783SApple OSS Distributions }
573*e7776783SApple OSS Distributions if (!s->addChar('=')) {
574*e7776783SApple OSS Distributions return false;
575*e7776783SApple OSS Distributions }
576*e7776783SApple OSS Distributions if (!s->addChar('=')) {
577*e7776783SApple OSS Distributions return false;
578*e7776783SApple OSS Distributions }
579*e7776783SApple OSS Distributions break;
580*e7776783SApple OSS Distributions case 2:
581*e7776783SApple OSS Distributions c = __CFPLDataEncodeTable[((p[-1] << 2) & 0x3c)];
582*e7776783SApple OSS Distributions if (!s->addChar(c)) {
583*e7776783SApple OSS Distributions return false;
584*e7776783SApple OSS Distributions }
585*e7776783SApple OSS Distributions if (!s->addChar('=')) {
586*e7776783SApple OSS Distributions return false;
587*e7776783SApple OSS Distributions }
588*e7776783SApple OSS Distributions break;
589*e7776783SApple OSS Distributions }
590*e7776783SApple OSS Distributions
591*e7776783SApple OSS Distributions return s->addXMLEndTag("data");
592*e7776783SApple OSS Distributions }
593*e7776783SApple OSS Distributions
594*e7776783SApple OSS Distributions void
setDeallocFunction(DeallocFunction func)595*e7776783SApple OSS Distributions OSData::setDeallocFunction(DeallocFunction func)
596*e7776783SApple OSS Distributions {
597*e7776783SApple OSS Distributions if (!reserved) {
598*e7776783SApple OSS Distributions reserved = (typeof(reserved))kalloc_type(ExpansionData, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
599*e7776783SApple OSS Distributions if (!reserved) {
600*e7776783SApple OSS Distributions return;
601*e7776783SApple OSS Distributions }
602*e7776783SApple OSS Distributions }
603*e7776783SApple OSS Distributions reserved->deallocFunction = func;
604*e7776783SApple OSS Distributions }
605*e7776783SApple OSS Distributions
606*e7776783SApple OSS Distributions void
setSerializable(bool serializable)607*e7776783SApple OSS Distributions OSData::setSerializable(bool serializable)
608*e7776783SApple OSS Distributions {
609*e7776783SApple OSS Distributions if (!reserved) {
610*e7776783SApple OSS Distributions reserved = (typeof(reserved))kalloc_type(ExpansionData, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
611*e7776783SApple OSS Distributions if (!reserved) {
612*e7776783SApple OSS Distributions return;
613*e7776783SApple OSS Distributions }
614*e7776783SApple OSS Distributions }
615*e7776783SApple OSS Distributions reserved->disableSerialization = (!serializable);
616*e7776783SApple OSS Distributions }
617*e7776783SApple OSS Distributions
618*e7776783SApple OSS Distributions bool
isSerializable(void)619*e7776783SApple OSS Distributions OSData::isSerializable(void)
620*e7776783SApple OSS Distributions {
621*e7776783SApple OSS Distributions return !reserved || !reserved->disableSerialization;
622*e7776783SApple OSS Distributions }
623