xref: /xnu-8019.80.24/libkern/c++/OSData.cpp (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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