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