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