1a3bb9fccSApple OSS Distributions /*
2a3bb9fccSApple OSS Distributions  * Copyright (c) 2014 Apple Computer, Inc. All rights reserved.
3a3bb9fccSApple OSS Distributions  *
4a3bb9fccSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5a3bb9fccSApple OSS Distributions  *
6a3bb9fccSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7a3bb9fccSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8a3bb9fccSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9a3bb9fccSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10a3bb9fccSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11a3bb9fccSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12a3bb9fccSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13a3bb9fccSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14a3bb9fccSApple OSS Distributions  *
15a3bb9fccSApple OSS Distributions  * Please obtain a copy of the License at
16a3bb9fccSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17a3bb9fccSApple OSS Distributions  *
18a3bb9fccSApple OSS Distributions  * The Original Code and all software distributed under the License are
19a3bb9fccSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20a3bb9fccSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21a3bb9fccSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22a3bb9fccSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23a3bb9fccSApple OSS Distributions  * Please see the License for the specific language governing rights and
24a3bb9fccSApple OSS Distributions  * limitations under the License.
25a3bb9fccSApple OSS Distributions  *
26a3bb9fccSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27a3bb9fccSApple OSS Distributions  */
28a3bb9fccSApple OSS Distributions 
29a3bb9fccSApple OSS Distributions 
30*bb611c8fSApple OSS Distributions #include <libkern/c++/OSSharedPtr.h>
31*bb611c8fSApple OSS Distributions #include <libkern/OSSerializeBinary.h>
32a3bb9fccSApple OSS Distributions #include <libkern/c++/OSContainers.h>
33a3bb9fccSApple OSS Distributions #include <libkern/c++/OSLib.h>
34a3bb9fccSApple OSS Distributions #include <libkern/c++/OSDictionary.h>
35a3bb9fccSApple OSS Distributions #include <libkern/OSSerializeBinary.h>
36*bb611c8fSApple OSS Distributions #include <libkern/c++/OSSharedPtr.h>
37a3bb9fccSApple OSS Distributions 
38a3bb9fccSApple OSS Distributions #include <IOKit/IOLib.h>
39a3bb9fccSApple OSS Distributions 
40a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41a3bb9fccSApple OSS Distributions 
42a3bb9fccSApple OSS Distributions #if 0
43a3bb9fccSApple OSS Distributions #define DEBG(fmt, args ...)  { kprintf(fmt, args); }
44a3bb9fccSApple OSS Distributions #else
45a3bb9fccSApple OSS Distributions #define DEBG(fmt, args ...)      {}
46a3bb9fccSApple OSS Distributions #endif
47a3bb9fccSApple OSS Distributions 
48a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49a3bb9fccSApple OSS Distributions 
50a5e72196SApple OSS Distributions OSSerialize *
51a5e72196SApple OSS Distributions OSSerialize::binaryWithCapacity(unsigned int inCapacity,
52a3bb9fccSApple OSS Distributions     Editor editor, void * reference)
53a3bb9fccSApple OSS Distributions {
54a3bb9fccSApple OSS Distributions 	OSSerialize *me;
55a3bb9fccSApple OSS Distributions 
56a5e72196SApple OSS Distributions 	if (inCapacity < sizeof(uint32_t)) {
57a5e72196SApple OSS Distributions 		return NULL;
58a5e72196SApple OSS Distributions 	}
59a3bb9fccSApple OSS Distributions 	me = OSSerialize::withCapacity(inCapacity);
60a5e72196SApple OSS Distributions 	if (!me) {
61a5e72196SApple OSS Distributions 		return NULL;
62a5e72196SApple OSS Distributions 	}
63a3bb9fccSApple OSS Distributions 
64a3bb9fccSApple OSS Distributions 	me->binary        = true;
65a3bb9fccSApple OSS Distributions 	me->endCollection = true;
66a3bb9fccSApple OSS Distributions 	me->editor        = editor;
67a3bb9fccSApple OSS Distributions 	me->editRef       = reference;
68a3bb9fccSApple OSS Distributions 
69a3bb9fccSApple OSS Distributions 	bcopy(kOSSerializeBinarySignature, &me->data[0], sizeof(kOSSerializeBinarySignature));
70a3bb9fccSApple OSS Distributions 	me->length = sizeof(kOSSerializeBinarySignature);
71a3bb9fccSApple OSS Distributions 
72a5e72196SApple OSS Distributions 	return me;
73a3bb9fccSApple OSS Distributions }
74a3bb9fccSApple OSS Distributions 
75a5e72196SApple OSS Distributions bool
76a5e72196SApple OSS Distributions OSSerialize::addBinary(const void * bits, size_t size)
77a3bb9fccSApple OSS Distributions {
78a3bb9fccSApple OSS Distributions 	unsigned int newCapacity;
79a3bb9fccSApple OSS Distributions 	size_t       alignSize;
80a3bb9fccSApple OSS Distributions 
81a5e72196SApple OSS Distributions 	if (os_add_overflow(size, 3, &alignSize)) {
82a5e72196SApple OSS Distributions 		return false;
83a5e72196SApple OSS Distributions 	}
8476e12aa3SApple OSS Distributions 	alignSize &= ~3L;
85a5e72196SApple OSS Distributions 	if (os_add_overflow(length, alignSize, &newCapacity)) {
86a5e72196SApple OSS Distributions 		return false;
87a5e72196SApple OSS Distributions 	}
88a5e72196SApple OSS Distributions 	if (newCapacity >= capacity) {
89a3bb9fccSApple OSS Distributions 		newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement;
90a5e72196SApple OSS Distributions 		if (newCapacity < capacity) {
91a5e72196SApple OSS Distributions 			return false;
92a5e72196SApple OSS Distributions 		}
93a5e72196SApple OSS Distributions 		if (newCapacity > ensureCapacity(newCapacity)) {
94a5e72196SApple OSS Distributions 			return false;
95a5e72196SApple OSS Distributions 		}
96a3bb9fccSApple OSS Distributions 	}
97a3bb9fccSApple OSS Distributions 
98a3bb9fccSApple OSS Distributions 	bcopy(bits, &data[length], size);
99a3bb9fccSApple OSS Distributions 	length += alignSize;
100a3bb9fccSApple OSS Distributions 
101a5e72196SApple OSS Distributions 	return true;
102a3bb9fccSApple OSS Distributions }
103a3bb9fccSApple OSS Distributions 
104a5e72196SApple OSS Distributions void
105a5e72196SApple OSS Distributions OSSerialize::setIndexed(bool index __unused)
106a5e72196SApple OSS Distributions {
107a5e72196SApple OSS Distributions 	assert(index && !indexData);
108a5e72196SApple OSS Distributions 	indexData = OSData::withCapacity(256);
109a5e72196SApple OSS Distributions 	assert(indexData);
110a5e72196SApple OSS Distributions }
111a5e72196SApple OSS Distributions 
112a5e72196SApple OSS Distributions bool
113a5e72196SApple OSS Distributions OSSerialize::addBinaryObject(const OSMetaClassBase * o, uint32_t key,
114*bb611c8fSApple OSS Distributions     const void * bits, uint32_t size,
115a5e72196SApple OSS Distributions     uint32_t * startCollection)
116a3bb9fccSApple OSS Distributions {
117a3bb9fccSApple OSS Distributions 	unsigned int newCapacity;
118a3bb9fccSApple OSS Distributions 	size_t       alignSize;
119a5e72196SApple OSS Distributions 	size_t       headerSize;
120a3bb9fccSApple OSS Distributions 
12188cc0b97SApple OSS Distributions 	// add to tag array
12288cc0b97SApple OSS Distributions 	tags->setObject(o);
123a3bb9fccSApple OSS Distributions 
124a5e72196SApple OSS Distributions 	headerSize = sizeof(key);
125a5e72196SApple OSS Distributions 	if (indexData) {
126a5e72196SApple OSS Distributions 		uint32_t offset = length;
127a5e72196SApple OSS Distributions 		if (startCollection) {
128a5e72196SApple OSS Distributions 			*startCollection = offset;
129a5e72196SApple OSS Distributions 			headerSize += sizeof(uint32_t);
130a5e72196SApple OSS Distributions 		}
131a5e72196SApple OSS Distributions 		offset /= sizeof(uint32_t);
132a5e72196SApple OSS Distributions 		indexData->appendBytes(&offset, sizeof(offset));
133a3bb9fccSApple OSS Distributions 	}
134a3bb9fccSApple OSS Distributions 
135a5e72196SApple OSS Distributions 	if (os_add3_overflow(size, headerSize, 3, &alignSize)) {
136a5e72196SApple OSS Distributions 		return false;
137a5e72196SApple OSS Distributions 	}
138a5e72196SApple OSS Distributions 	alignSize &= ~3L;
139a5e72196SApple OSS Distributions 	if (os_add_overflow(length, alignSize, &newCapacity)) {
140a5e72196SApple OSS Distributions 		return false;
141a5e72196SApple OSS Distributions 	}
142a5e72196SApple OSS Distributions 	if (newCapacity >= capacity) {
143a5e72196SApple OSS Distributions 		newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement;
144a5e72196SApple OSS Distributions 		if (newCapacity < capacity) {
145a5e72196SApple OSS Distributions 			return false;
146a5e72196SApple OSS Distributions 		}
147a5e72196SApple OSS Distributions 		if (newCapacity > ensureCapacity(newCapacity)) {
148a5e72196SApple OSS Distributions 			return false;
149a5e72196SApple OSS Distributions 		}
150a5e72196SApple OSS Distributions 	}
151a5e72196SApple OSS Distributions 
152a5e72196SApple OSS Distributions 	if (endCollection) {
153a3bb9fccSApple OSS Distributions 		endCollection = false;
154a3bb9fccSApple OSS Distributions 		key |= kOSSerializeEndCollecton;
155a3bb9fccSApple OSS Distributions 	}
156a3bb9fccSApple OSS Distributions 
157a3bb9fccSApple OSS Distributions 	bcopy(&key, &data[length], sizeof(key));
158a5e72196SApple OSS Distributions 	bcopy(bits, &data[length + headerSize], size);
159a3bb9fccSApple OSS Distributions 	length += alignSize;
160a3bb9fccSApple OSS Distributions 
161a5e72196SApple OSS Distributions 	return true;
162a3bb9fccSApple OSS Distributions }
163a3bb9fccSApple OSS Distributions 
164a5e72196SApple OSS Distributions void
165a5e72196SApple OSS Distributions OSSerialize::endBinaryCollection(uint32_t startCollection)
166a5e72196SApple OSS Distributions {
167a5e72196SApple OSS Distributions 	uint32_t clength;
168a5e72196SApple OSS Distributions 
169a5e72196SApple OSS Distributions 	if (!indexData) {
170a5e72196SApple OSS Distributions 		return;
171a5e72196SApple OSS Distributions 	}
172a5e72196SApple OSS Distributions 
173a5e72196SApple OSS Distributions 	assert(length > startCollection);
174a5e72196SApple OSS Distributions 	if (length <= startCollection) {
175a5e72196SApple OSS Distributions 		return;
176a5e72196SApple OSS Distributions 	}
177a5e72196SApple OSS Distributions 
178a5e72196SApple OSS Distributions 	clength = length - startCollection;
179a5e72196SApple OSS Distributions 	assert(!(clength & 3));
180a5e72196SApple OSS Distributions 	clength /= sizeof(uint32_t);
181a5e72196SApple OSS Distributions 
182a5e72196SApple OSS Distributions 	memcpy(&data[startCollection + sizeof(uint32_t)], &clength, sizeof(clength));
183a5e72196SApple OSS Distributions }
184a5e72196SApple OSS Distributions 
185a5e72196SApple OSS Distributions bool
186a5e72196SApple OSS Distributions OSSerialize::binarySerialize(const OSMetaClassBase *o)
187a5e72196SApple OSS Distributions {
188a5e72196SApple OSS Distributions 	bool ok;
189a5e72196SApple OSS Distributions 	uint32_t header;
190a5e72196SApple OSS Distributions 
191a5e72196SApple OSS Distributions 	ok = binarySerializeInternal(o);
192a5e72196SApple OSS Distributions 	if (!ok) {
193a5e72196SApple OSS Distributions 		return ok;
194a5e72196SApple OSS Distributions 	}
195a5e72196SApple OSS Distributions 
196a5e72196SApple OSS Distributions 	if (indexData) {
197a5e72196SApple OSS Distributions 		header = indexData->getLength() / sizeof(uint32_t);
198a5e72196SApple OSS Distributions 		assert(header <= kOSSerializeDataMask);
199a5e72196SApple OSS Distributions 		header <<= 8;
200a5e72196SApple OSS Distributions 		header |= kOSSerializeIndexedBinarySignature;
201a5e72196SApple OSS Distributions 
202a5e72196SApple OSS Distributions 		memcpy(&data[0], &header, sizeof(header));
203a5e72196SApple OSS Distributions 	}
204a5e72196SApple OSS Distributions 
205a5e72196SApple OSS Distributions 	return ok;
206a5e72196SApple OSS Distributions }
207a5e72196SApple OSS Distributions 
208a5e72196SApple OSS Distributions bool
209a5e72196SApple OSS Distributions OSSerialize::binarySerializeInternal(const OSMetaClassBase *o)
210a3bb9fccSApple OSS Distributions {
211a3bb9fccSApple OSS Distributions 	OSDictionary * dict;
212a3bb9fccSApple OSS Distributions 	OSArray      * array;
213a3bb9fccSApple OSS Distributions 	OSSet        * set;
214a3bb9fccSApple OSS Distributions 	OSNumber     * num;
215a3bb9fccSApple OSS Distributions 	OSSymbol     * sym;
216a3bb9fccSApple OSS Distributions 	OSString     * str;
21788cc0b97SApple OSS Distributions 	OSData       * ldata;
218a3bb9fccSApple OSS Distributions 	OSBoolean    * boo;
219a3bb9fccSApple OSS Distributions 
22088cc0b97SApple OSS Distributions 	unsigned int  tagIdx;
221a5e72196SApple OSS Distributions 	uint32_t   i, key, startCollection;
222*bb611c8fSApple OSS Distributions 	uint32_t   len;
223a3bb9fccSApple OSS Distributions 	bool       ok;
224a3bb9fccSApple OSS Distributions 
22588cc0b97SApple OSS Distributions 	tagIdx = tags->getNextIndexOfObject(o, 0);
226a3bb9fccSApple OSS Distributions 	// does it exist?
227a5e72196SApple OSS Distributions 	if (-1U != tagIdx) {
228a5e72196SApple OSS Distributions 		if (indexData) {
229a5e72196SApple OSS Distributions 			assert(indexData->getLength() > (tagIdx * sizeof(uint32_t)));
230a5e72196SApple OSS Distributions 			tagIdx = ((const uint32_t *)indexData->getBytesNoCopy())[tagIdx];
231a5e72196SApple OSS Distributions 			assert(tagIdx <= kOSSerializeDataMask);
232a5e72196SApple OSS Distributions 		}
23388cc0b97SApple OSS Distributions 		key = (kOSSerializeObject | tagIdx);
234a5e72196SApple OSS Distributions 		if (endCollection) {
235a3bb9fccSApple OSS Distributions 			endCollection = false;
236a3bb9fccSApple OSS Distributions 			key |= kOSSerializeEndCollecton;
237a3bb9fccSApple OSS Distributions 		}
238a3bb9fccSApple OSS Distributions 		ok = addBinary(&key, sizeof(key));
239a5e72196SApple OSS Distributions 		return ok;
240a3bb9fccSApple OSS Distributions 	}
241a3bb9fccSApple OSS Distributions 
242a5e72196SApple OSS Distributions 	if ((dict = OSDynamicCast(OSDictionary, o))) {
243a3bb9fccSApple OSS Distributions 		key = (kOSSerializeDictionary | dict->count);
244a5e72196SApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0, &startCollection);
245a5e72196SApple OSS Distributions 		for (i = 0; ok && (i < dict->count);) {
246a3bb9fccSApple OSS Distributions 			const OSSymbol        * dictKey;
247a3bb9fccSApple OSS Distributions 			const OSMetaClassBase * dictValue;
248a5e72196SApple OSS Distributions 			const OSMetaClassBase * nvalue = NULL;
249a3bb9fccSApple OSS Distributions 
25088cc0b97SApple OSS Distributions 			dictKey = dict->dictionary[i].key;
25188cc0b97SApple OSS Distributions 			dictValue = dict->dictionary[i].value;
252a3bb9fccSApple OSS Distributions 			i++;
253a5e72196SApple OSS Distributions 			if (editor) {
254a3bb9fccSApple OSS Distributions 				dictValue = nvalue = (*editor)(editRef, this, dict, dictKey, dictValue);
255a5e72196SApple OSS Distributions 				if (!dictValue) {
256a5e72196SApple OSS Distributions 					dictValue = dict;
257a5e72196SApple OSS Distributions 				}
258a3bb9fccSApple OSS Distributions 			}
259a3bb9fccSApple OSS Distributions 			ok = binarySerialize(dictKey);
260a5e72196SApple OSS Distributions 			if (!ok) {
261a5e72196SApple OSS Distributions 				break;
262a5e72196SApple OSS Distributions 			}
263a3bb9fccSApple OSS Distributions 			endCollection = (i == dict->count);
264a3bb9fccSApple OSS Distributions 			ok = binarySerialize(dictValue);
265a5e72196SApple OSS Distributions 			if (!ok) {
266a5e72196SApple OSS Distributions 				ok = dictValue->serialize(this);
267a5e72196SApple OSS Distributions 			}
268a5e72196SApple OSS Distributions 			if (nvalue) {
269a5e72196SApple OSS Distributions 				nvalue->release();
270a5e72196SApple OSS Distributions 			}
271a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
272a3bb9fccSApple OSS Distributions 		}
273a5e72196SApple OSS Distributions 		endBinaryCollection(startCollection);
274a5e72196SApple OSS Distributions 	} else if ((array = OSDynamicCast(OSArray, o))) {
275a3bb9fccSApple OSS Distributions 		key = (kOSSerializeArray | array->count);
276a5e72196SApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0, &startCollection);
277a5e72196SApple OSS Distributions 		for (i = 0; ok && (i < array->count);) {
278a3bb9fccSApple OSS Distributions 			i++;
279a3bb9fccSApple OSS Distributions 			endCollection = (i == array->count);
280a3bb9fccSApple OSS Distributions 			ok = binarySerialize(array->array[i - 1]);
281a5e72196SApple OSS Distributions 			if (!ok) {
282a5e72196SApple OSS Distributions 				ok = array->array[i - 1]->serialize(this);
283a5e72196SApple OSS Distributions 			}
284a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
285a3bb9fccSApple OSS Distributions 		}
286a5e72196SApple OSS Distributions 		endBinaryCollection(startCollection);
287a5e72196SApple OSS Distributions 	} else if ((set = OSDynamicCast(OSSet, o))) {
288a3bb9fccSApple OSS Distributions 		key = (kOSSerializeSet | set->members->count);
289a5e72196SApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0, &startCollection);
290a5e72196SApple OSS Distributions 		for (i = 0; ok && (i < set->members->count);) {
291a3bb9fccSApple OSS Distributions 			i++;
292a3bb9fccSApple OSS Distributions 			endCollection = (i == set->members->count);
293a3bb9fccSApple OSS Distributions 			ok = binarySerialize(set->members->array[i - 1]);
294a5e72196SApple OSS Distributions 			if (!ok) {
295a5e72196SApple OSS Distributions 				ok = set->members->array[i - 1]->serialize(this);
296a5e72196SApple OSS Distributions 			}
297a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
298a3bb9fccSApple OSS Distributions 		}
299a5e72196SApple OSS Distributions 		endBinaryCollection(startCollection);
300a5e72196SApple OSS Distributions 	} else if ((num = OSDynamicCast(OSNumber, o))) {
301a3bb9fccSApple OSS Distributions 		key = (kOSSerializeNumber | num->size);
302a5e72196SApple OSS Distributions 		ok = addBinaryObject(o, key, &num->value, sizeof(num->value), NULL);
303a5e72196SApple OSS Distributions 	} else if ((boo = OSDynamicCast(OSBoolean, o))) {
304a3bb9fccSApple OSS Distributions 		key = (kOSSerializeBoolean | (kOSBooleanTrue == boo));
305a5e72196SApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0, NULL);
306a5e72196SApple OSS Distributions 	} else if ((sym = OSDynamicCast(OSSymbol, o))) {
307a3bb9fccSApple OSS Distributions 		len = (sym->getLength() + 1);
308a3bb9fccSApple OSS Distributions 		key = (kOSSerializeSymbol | len);
309a5e72196SApple OSS Distributions 		ok = addBinaryObject(o, key, sym->getCStringNoCopy(), len, NULL);
310a5e72196SApple OSS Distributions 	} else if ((str = OSDynamicCast(OSString, o))) {
311a5e72196SApple OSS Distributions 		len = (str->getLength() + ((indexData != NULL) ? 1 : 0));
312a3bb9fccSApple OSS Distributions 		key = (kOSSerializeString | len);
313a5e72196SApple OSS Distributions 		ok = addBinaryObject(o, key, str->getCStringNoCopy(), len, NULL);
314a5e72196SApple OSS Distributions 	} else if ((ldata = OSDynamicCast(OSData, o))) {
31588cc0b97SApple OSS Distributions 		len = ldata->getLength();
316a5e72196SApple OSS Distributions 		if (ldata->reserved && ldata->reserved->disableSerialization) {
317a5e72196SApple OSS Distributions 			len = 0;
318a3bb9fccSApple OSS Distributions 		}
319a5e72196SApple OSS Distributions 		key = (kOSSerializeData | len);
320a5e72196SApple OSS Distributions 		ok = addBinaryObject(o, key, ldata->getBytesNoCopy(), len, NULL);
321a5e72196SApple OSS Distributions 	} else {
322a5e72196SApple OSS Distributions 		return false;
323a5e72196SApple OSS Distributions 	}
324a3bb9fccSApple OSS Distributions 
325a5e72196SApple OSS Distributions 	return ok;
326a3bb9fccSApple OSS Distributions }
327a3bb9fccSApple OSS Distributions 
328a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
329a3bb9fccSApple OSS Distributions 
330a3bb9fccSApple OSS Distributions #define setAtIndex(v, idx, o)                                                                                                           \
331a3bb9fccSApple OSS Distributions 	if (idx >= v##Capacity)                                                                                                                 \
332a3bb9fccSApple OSS Distributions 	{                                                                                                                                                               \
33388cc0b97SApple OSS Distributions 	if (v##Capacity >= v##CapacityMax) ok = false;                                  \
33488cc0b97SApple OSS Distributions 	else                                                                                                                                                    \
33588cc0b97SApple OSS Distributions 	{                                                                                                                                                           \
336a3bb9fccSApple OSS Distributions 	    uint32_t ncap = v##Capacity + 64;                                                                               \
3370f3703acSApple OSS Distributions 	    typeof(v##Array) nbuf = (typeof(v##Array)) kalloc_container(ncap * sizeof(o)); \
338a3bb9fccSApple OSS Distributions 	    if (!nbuf) ok = false;                                                                                                          \
33988cc0b97SApple OSS Distributions 	    else                                                                                                                                    \
34088cc0b97SApple OSS Distributions 	    {                                                                                                                                   \
341a3bb9fccSApple OSS Distributions 	        if (v##Array)                                                                                                                   \
342a3bb9fccSApple OSS Distributions 	        {                                                                                                                                               \
343a3bb9fccSApple OSS Distributions 	            bcopy(v##Array, nbuf, v##Capacity * sizeof(o));                                             \
344a3bb9fccSApple OSS Distributions 	            kfree(v##Array, v##Capacity * sizeof(o));                                                   \
345a3bb9fccSApple OSS Distributions 	        }                                                                                                                                               \
346a3bb9fccSApple OSS Distributions 	        v##Array    = nbuf;                                                                                                             \
347a3bb9fccSApple OSS Distributions 	        v##Capacity = ncap;                                                                                                             \
348a3bb9fccSApple OSS Distributions 	    }                                                                                                                                   \
34988cc0b97SApple OSS Distributions 	    }                                                                                                                                                       \
35088cc0b97SApple OSS Distributions 	}                                                                                                                                                               \
351a3bb9fccSApple OSS Distributions 	if (ok) v##Array[idx] = o;
352a3bb9fccSApple OSS Distributions 
353a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
354a3bb9fccSApple OSS Distributions 
355a3bb9fccSApple OSS Distributions OSObject *
356a3bb9fccSApple OSS Distributions OSUnserializeBinary(const char *buffer, size_t bufferSize, OSString **errorString)
357a3bb9fccSApple OSS Distributions {
358a3bb9fccSApple OSS Distributions 	OSObject ** objsArray;
359a3bb9fccSApple OSS Distributions 	uint32_t    objsCapacity;
36088cc0b97SApple OSS Distributions 	enum      { objsCapacityMax = 16 * 1024 * 1024 };
361a3bb9fccSApple OSS Distributions 	uint32_t    objsIdx;
362a3bb9fccSApple OSS Distributions 
363a3bb9fccSApple OSS Distributions 	OSObject ** stackArray;
364a3bb9fccSApple OSS Distributions 	uint32_t    stackCapacity;
36576e12aa3SApple OSS Distributions 	enum      { stackCapacityMax = 64 };
366a3bb9fccSApple OSS Distributions 	uint32_t    stackIdx;
367a3bb9fccSApple OSS Distributions 
368a3bb9fccSApple OSS Distributions 	OSObject     * result;
369a3bb9fccSApple OSS Distributions 	OSObject     * parent;
370a3bb9fccSApple OSS Distributions 	OSDictionary * dict;
371a3bb9fccSApple OSS Distributions 	OSArray      * array;
372a3bb9fccSApple OSS Distributions 	OSSet        * set;
373a3bb9fccSApple OSS Distributions 	OSDictionary * newDict;
374a3bb9fccSApple OSS Distributions 	OSArray      * newArray;
375a3bb9fccSApple OSS Distributions 	OSSet        * newSet;
376a3bb9fccSApple OSS Distributions 	OSObject     * o;
377a3bb9fccSApple OSS Distributions 	OSSymbol     * sym;
3780f3703acSApple OSS Distributions 	OSString     * str;
379a3bb9fccSApple OSS Distributions 
380a3bb9fccSApple OSS Distributions 	size_t           bufferPos;
381a3bb9fccSApple OSS Distributions 	const uint32_t * next;
382a5e72196SApple OSS Distributions 	uint32_t         key, len, wordLen, length;
383a3bb9fccSApple OSS Distributions 	bool             end, newCollect, isRef;
384a3bb9fccSApple OSS Distributions 	unsigned long long value;
385a5e72196SApple OSS Distributions 	bool ok, indexed, hasLength;
386a3bb9fccSApple OSS Distributions 
387a5e72196SApple OSS Distributions 	indexed = false;
388a5e72196SApple OSS Distributions 	if (errorString) {
389a5e72196SApple OSS Distributions 		*errorString = NULL;
390a5e72196SApple OSS Distributions 	}
391a5e72196SApple OSS Distributions 
392a5e72196SApple OSS Distributions 	if (bufferSize < sizeof(kOSSerializeBinarySignature)) {
393a5e72196SApple OSS Distributions 		return NULL;
394a5e72196SApple OSS Distributions 	}
395a5e72196SApple OSS Distributions 	if (kOSSerializeIndexedBinarySignature == (((const uint8_t *) buffer)[0])) {
396a5e72196SApple OSS Distributions 		indexed = true;
397a5e72196SApple OSS Distributions 	} else if (0 != strcmp(kOSSerializeBinarySignature, buffer)) {
398a5e72196SApple OSS Distributions 		return NULL;
399a5e72196SApple OSS Distributions 	}
400a5e72196SApple OSS Distributions 	if (3 & ((uintptr_t) buffer)) {
401a5e72196SApple OSS Distributions 		return NULL;
402a5e72196SApple OSS Distributions 	}
403a5e72196SApple OSS Distributions 
404a3bb9fccSApple OSS Distributions 	bufferPos = sizeof(kOSSerializeBinarySignature);
405a3bb9fccSApple OSS Distributions 	next = (typeof(next))(((uintptr_t) buffer) + bufferPos);
406a3bb9fccSApple OSS Distributions 
407a3bb9fccSApple OSS Distributions 	DEBG("---------OSUnserializeBinary(%p)\n", buffer);
408a3bb9fccSApple OSS Distributions 
409a3bb9fccSApple OSS Distributions 	objsArray = stackArray    = NULL;
410a3bb9fccSApple OSS Distributions 	objsIdx   = objsCapacity  = 0;
411a3bb9fccSApple OSS Distributions 	stackIdx  = stackCapacity = 0;
412a3bb9fccSApple OSS Distributions 
413a5e72196SApple OSS Distributions 	result   = NULL;
414a5e72196SApple OSS Distributions 	parent   = NULL;
415a5e72196SApple OSS Distributions 	dict     = NULL;
416a5e72196SApple OSS Distributions 	array    = NULL;
417a5e72196SApple OSS Distributions 	set      = NULL;
418a5e72196SApple OSS Distributions 	sym      = NULL;
419a3bb9fccSApple OSS Distributions 
420a3bb9fccSApple OSS Distributions 	ok = true;
421a5e72196SApple OSS Distributions 	while (ok) {
422a3bb9fccSApple OSS Distributions 		bufferPos += sizeof(*next);
423a5e72196SApple OSS Distributions 		if (!(ok = (bufferPos <= bufferSize))) {
424a5e72196SApple OSS Distributions 			break;
425a5e72196SApple OSS Distributions 		}
426a3bb9fccSApple OSS Distributions 		key = *next++;
427a5e72196SApple OSS Distributions 		length = 0;
428a3bb9fccSApple OSS Distributions 
429a3bb9fccSApple OSS Distributions 		len = (key & kOSSerializeDataMask);
430a3bb9fccSApple OSS Distributions 		wordLen = (len + 3) >> 2;
431a3bb9fccSApple OSS Distributions 		end = (0 != (kOSSerializeEndCollecton & key));
432a3bb9fccSApple OSS Distributions 		DEBG("key 0x%08x: 0x%04x, %d\n", key, len, end);
433a3bb9fccSApple OSS Distributions 
434a5e72196SApple OSS Distributions 		newCollect = isRef = hasLength = false;
435a5e72196SApple OSS Distributions 		o = NULL; newDict = NULL; newArray = NULL; newSet = NULL;
436a3bb9fccSApple OSS Distributions 
437a5e72196SApple OSS Distributions 		switch (kOSSerializeTypeMask & key) {
438a3bb9fccSApple OSS Distributions 		case kOSSerializeDictionary:
439a3bb9fccSApple OSS Distributions 			o = newDict = OSDictionary::withCapacity(len);
440a3bb9fccSApple OSS Distributions 			newCollect = (len != 0);
441a5e72196SApple OSS Distributions 			hasLength  = indexed;
442a3bb9fccSApple OSS Distributions 			break;
443a3bb9fccSApple OSS Distributions 		case kOSSerializeArray:
444a3bb9fccSApple OSS Distributions 			o = newArray = OSArray::withCapacity(len);
445a3bb9fccSApple OSS Distributions 			newCollect = (len != 0);
446a5e72196SApple OSS Distributions 			hasLength  = indexed;
447a3bb9fccSApple OSS Distributions 			break;
448a3bb9fccSApple OSS Distributions 		case kOSSerializeSet:
449a3bb9fccSApple OSS Distributions 			o = newSet = OSSet::withCapacity(len);
450a3bb9fccSApple OSS Distributions 			newCollect = (len != 0);
451a5e72196SApple OSS Distributions 			hasLength  = indexed;
452a3bb9fccSApple OSS Distributions 			break;
453a3bb9fccSApple OSS Distributions 
454a3bb9fccSApple OSS Distributions 		case kOSSerializeObject:
455a5e72196SApple OSS Distributions 			if (len >= objsIdx) {
456a5e72196SApple OSS Distributions 				break;
457a5e72196SApple OSS Distributions 			}
458a3bb9fccSApple OSS Distributions 			o = objsArray[len];
459a3bb9fccSApple OSS Distributions 			isRef = true;
460a3bb9fccSApple OSS Distributions 			break;
461a3bb9fccSApple OSS Distributions 
462a3bb9fccSApple OSS Distributions 		case kOSSerializeNumber:
463a3bb9fccSApple OSS Distributions 			bufferPos += sizeof(long long);
464a5e72196SApple OSS Distributions 			if (bufferPos > bufferSize) {
465a5e72196SApple OSS Distributions 				break;
466a5e72196SApple OSS Distributions 			}
467a5e72196SApple OSS Distributions 			if ((len != 32) && (len != 64) && (len != 16) && (len != 8)) {
468a5e72196SApple OSS Distributions 				break;
469a5e72196SApple OSS Distributions 			}
470a3bb9fccSApple OSS Distributions 			value = next[1];
471a3bb9fccSApple OSS Distributions 			value <<= 32;
472a3bb9fccSApple OSS Distributions 			value |= next[0];
473a3bb9fccSApple OSS Distributions 			o = OSNumber::withNumber(value, len);
474a3bb9fccSApple OSS Distributions 			next += 2;
475a3bb9fccSApple OSS Distributions 			break;
476a3bb9fccSApple OSS Distributions 
477a3bb9fccSApple OSS Distributions 		case kOSSerializeSymbol:
478a3bb9fccSApple OSS Distributions 			bufferPos += (wordLen * sizeof(uint32_t));
479a5e72196SApple OSS Distributions 			if (bufferPos > bufferSize) {
480a5e72196SApple OSS Distributions 				break;
481a5e72196SApple OSS Distributions 			}
482a5e72196SApple OSS Distributions 			if (len < 2) {
483a5e72196SApple OSS Distributions 				break;
484a5e72196SApple OSS Distributions 			}
485a5e72196SApple OSS Distributions 			if (0 != ((const char *)next)[len - 1]) {
486a5e72196SApple OSS Distributions 				break;
487a5e72196SApple OSS Distributions 			}
488a3bb9fccSApple OSS Distributions 			o = (OSObject *) OSSymbol::withCString((const char *) next);
489a3bb9fccSApple OSS Distributions 			next += wordLen;
490a3bb9fccSApple OSS Distributions 			break;
491a3bb9fccSApple OSS Distributions 
492a3bb9fccSApple OSS Distributions 		case kOSSerializeString:
493a3bb9fccSApple OSS Distributions 			bufferPos += (wordLen * sizeof(uint32_t));
494a5e72196SApple OSS Distributions 			if (bufferPos > bufferSize) {
495a5e72196SApple OSS Distributions 				break;
496a5e72196SApple OSS Distributions 			}
497a3bb9fccSApple OSS Distributions 			o = OSString::withStringOfLength((const char *) next, len);
498a3bb9fccSApple OSS Distributions 			next += wordLen;
499a3bb9fccSApple OSS Distributions 			break;
500a3bb9fccSApple OSS Distributions 
501a3bb9fccSApple OSS Distributions 		case kOSSerializeData:
502a3bb9fccSApple OSS Distributions 			bufferPos += (wordLen * sizeof(uint32_t));
503a5e72196SApple OSS Distributions 			if (bufferPos > bufferSize) {
504a5e72196SApple OSS Distributions 				break;
505a5e72196SApple OSS Distributions 			}
506a3bb9fccSApple OSS Distributions 			o = OSData::withBytes(next, len);
507a3bb9fccSApple OSS Distributions 			next += wordLen;
508a3bb9fccSApple OSS Distributions 			break;
509a3bb9fccSApple OSS Distributions 
510a3bb9fccSApple OSS Distributions 		case kOSSerializeBoolean:
511a3bb9fccSApple OSS Distributions 			o = (len ? kOSBooleanTrue : kOSBooleanFalse);
512a3bb9fccSApple OSS Distributions 			break;
513a3bb9fccSApple OSS Distributions 
514a3bb9fccSApple OSS Distributions 		default:
515a3bb9fccSApple OSS Distributions 			break;
516a3bb9fccSApple OSS Distributions 		}
517a3bb9fccSApple OSS Distributions 
518a5e72196SApple OSS Distributions 		if (!(ok = (o != NULL))) {
519a5e72196SApple OSS Distributions 			break;
520a5e72196SApple OSS Distributions 		}
521a3bb9fccSApple OSS Distributions 
522a5e72196SApple OSS Distributions 		if (hasLength) {
523a5e72196SApple OSS Distributions 			bufferPos += sizeof(*next);
524a5e72196SApple OSS Distributions 			if (!(ok = (bufferPos <= bufferSize))) {
525*bb611c8fSApple OSS Distributions 				o->release();
526a5e72196SApple OSS Distributions 				break;
527a5e72196SApple OSS Distributions 			}
528a5e72196SApple OSS Distributions 			length = *next++;
529a5e72196SApple OSS Distributions 		}
530a5e72196SApple OSS Distributions 
531a5e72196SApple OSS Distributions 		if (!isRef) {
532a3bb9fccSApple OSS Distributions 			setAtIndex(objs, objsIdx, o);
533a5e72196SApple OSS Distributions 			if (!ok) {
53488cc0b97SApple OSS Distributions 				o->release();
53588cc0b97SApple OSS Distributions 				break;
53688cc0b97SApple OSS Distributions 			}
537a3bb9fccSApple OSS Distributions 			objsIdx++;
538a3bb9fccSApple OSS Distributions 		}
539a3bb9fccSApple OSS Distributions 
540a5e72196SApple OSS Distributions 		if (dict) {
541a5e72196SApple OSS Distributions 			if (!sym) {
542a5e72196SApple OSS Distributions 				sym = (OSSymbol *) o;
543a5e72196SApple OSS Distributions 			} else {
54488cc0b97SApple OSS Distributions 				str = sym;
54588cc0b97SApple OSS Distributions 				sym = OSDynamicCast(OSSymbol, sym);
546a5e72196SApple OSS Distributions 				if (!sym && (str = OSDynamicCast(OSString, str))) {
547cc9a6355SApple OSS Distributions 					sym = const_cast<OSSymbol *>(OSSymbol::withString(str));
548a5e72196SApple OSS Distributions 					ok = (sym != NULL);
549a5e72196SApple OSS Distributions 					if (!ok) {
550a5e72196SApple OSS Distributions 						break;
551a5e72196SApple OSS Distributions 					}
55288cc0b97SApple OSS Distributions 				}
55388cc0b97SApple OSS Distributions 				DEBG("%s = %s\n", sym->getCStringNoCopy(), o->getMetaClass()->getClassName());
554a5e72196SApple OSS Distributions 				if (o != dict) {
555a5e72196SApple OSS Distributions 					ok = dict->setObject(sym, o);
556a3bb9fccSApple OSS Distributions 				}
557a5e72196SApple OSS Distributions 				if (sym && (sym != str)) {
558a5e72196SApple OSS Distributions 					sym->release();
559a3bb9fccSApple OSS Distributions 				}
560a5e72196SApple OSS Distributions 				sym = NULL;
561a5e72196SApple OSS Distributions 			}
562a5e72196SApple OSS Distributions 		} else if (array) {
563a5e72196SApple OSS Distributions 			ok = array->setObject(o);
564a5e72196SApple OSS Distributions 		} else if (set) {
565a5e72196SApple OSS Distributions 			ok = set->setObject(o);
566a5e72196SApple OSS Distributions 		} else if (result) {
567a5e72196SApple OSS Distributions 			ok = false;
568a5e72196SApple OSS Distributions 		} else {
569a3bb9fccSApple OSS Distributions 			assert(!parent);
570a3bb9fccSApple OSS Distributions 			result = o;
571a3bb9fccSApple OSS Distributions 		}
572a3bb9fccSApple OSS Distributions 
573a5e72196SApple OSS Distributions 		if (!ok) {
574a5e72196SApple OSS Distributions 			break;
575a5e72196SApple OSS Distributions 		}
576a3bb9fccSApple OSS Distributions 
577a5e72196SApple OSS Distributions 		if (end) {
578a5e72196SApple OSS Distributions 			parent = NULL;
579a5e72196SApple OSS Distributions 		}
580a5e72196SApple OSS Distributions 		if (newCollect) {
581a3bb9fccSApple OSS Distributions 			stackIdx++;
582a3bb9fccSApple OSS Distributions 			setAtIndex(stack, stackIdx, parent);
583a5e72196SApple OSS Distributions 			if (!ok) {
584a5e72196SApple OSS Distributions 				break;
585a5e72196SApple OSS Distributions 			}
586a3bb9fccSApple OSS Distributions 			DEBG("++stack[%d] %p\n", stackIdx, parent);
587a3bb9fccSApple OSS Distributions 			parent = o;
588a3bb9fccSApple OSS Distributions 			dict   = newDict;
589a3bb9fccSApple OSS Distributions 			array  = newArray;
590a3bb9fccSApple OSS Distributions 			set    = newSet;
591a3bb9fccSApple OSS Distributions 			end    = false;
592a3bb9fccSApple OSS Distributions 		}
593a3bb9fccSApple OSS Distributions 
594a5e72196SApple OSS Distributions 		if (end) {
595a5e72196SApple OSS Distributions 			while (stackIdx) {
596a3bb9fccSApple OSS Distributions 				parent = stackArray[stackIdx];
597a3bb9fccSApple OSS Distributions 				DEBG("--stack[%d] %p\n", stackIdx, parent);
598a3bb9fccSApple OSS Distributions 				stackIdx--;
599a5e72196SApple OSS Distributions 				if (parent) {
600a5e72196SApple OSS Distributions 					break;
60176e12aa3SApple OSS Distributions 				}
602a5e72196SApple OSS Distributions 			}
603a5e72196SApple OSS Distributions 			if (!parent) {
604a5e72196SApple OSS Distributions 				break;
605a5e72196SApple OSS Distributions 			}
606a5e72196SApple OSS Distributions 			set   = NULL;
607a5e72196SApple OSS Distributions 			dict  = NULL;
608a5e72196SApple OSS Distributions 			array = NULL;
609a5e72196SApple OSS Distributions 			if (!(dict = OSDynamicCast(OSDictionary, parent))) {
610a5e72196SApple OSS Distributions 				if (!(array = OSDynamicCast(OSArray, parent))) {
611a5e72196SApple OSS Distributions 					ok = (NULL != (set = OSDynamicCast(OSSet, parent)));
612a5e72196SApple OSS Distributions 				}
613a3bb9fccSApple OSS Distributions 			}
614a3bb9fccSApple OSS Distributions 		}
615a3bb9fccSApple OSS Distributions 	}
616a3bb9fccSApple OSS Distributions 	DEBG("ret %p\n", result);
617a3bb9fccSApple OSS Distributions 
618a5e72196SApple OSS Distributions 	if (!ok) {
619a5e72196SApple OSS Distributions 		result = NULL;
620a5e72196SApple OSS Distributions 	}
62188cc0b97SApple OSS Distributions 
622a5e72196SApple OSS Distributions 	if (objsCapacity) {
623a5e72196SApple OSS Distributions 		for (len = (result != NULL); len < objsIdx; len++) {
624a5e72196SApple OSS Distributions 			objsArray[len]->release();
625a5e72196SApple OSS Distributions 		}
62688cc0b97SApple OSS Distributions 		kfree(objsArray, objsCapacity  * sizeof(*objsArray));
62788cc0b97SApple OSS Distributions 	}
628a5e72196SApple OSS Distributions 	if (stackCapacity) {
629a5e72196SApple OSS Distributions 		kfree(stackArray, stackCapacity * sizeof(*stackArray));
630a5e72196SApple OSS Distributions 	}
631a3bb9fccSApple OSS Distributions 
632a5e72196SApple OSS Distributions 	return result;
633a3bb9fccSApple OSS Distributions }
634*bb611c8fSApple OSS Distributions 
635*bb611c8fSApple OSS Distributions OSObject*
636*bb611c8fSApple OSS Distributions OSUnserializeXML(
637*bb611c8fSApple OSS Distributions 	const char  * buffer,
638*bb611c8fSApple OSS Distributions 	OSSharedPtr<OSString>& errorString)
639*bb611c8fSApple OSS Distributions {
640*bb611c8fSApple OSS Distributions 	OSString* errorStringRaw = NULL;
641*bb611c8fSApple OSS Distributions 	OSObject* result = OSUnserializeXML(buffer, &errorStringRaw);
642*bb611c8fSApple OSS Distributions 	errorString.reset(errorStringRaw, OSNoRetain);
643*bb611c8fSApple OSS Distributions 	return result;
644*bb611c8fSApple OSS Distributions }
645*bb611c8fSApple OSS Distributions 
646*bb611c8fSApple OSS Distributions OSObject*
647*bb611c8fSApple OSS Distributions OSUnserializeXML(
648*bb611c8fSApple OSS Distributions 	const char  * buffer,
649*bb611c8fSApple OSS Distributions 	size_t        bufferSize,
650*bb611c8fSApple OSS Distributions 	OSSharedPtr<OSString> &errorString)
651*bb611c8fSApple OSS Distributions {
652*bb611c8fSApple OSS Distributions 	OSString* errorStringRaw = NULL;
653*bb611c8fSApple OSS Distributions 	OSObject* result = OSUnserializeXML(buffer, bufferSize, &errorStringRaw);
654*bb611c8fSApple OSS Distributions 	errorString.reset(errorStringRaw, OSNoRetain);
655*bb611c8fSApple OSS Distributions 	return result;
656*bb611c8fSApple OSS Distributions }
657*bb611c8fSApple OSS Distributions 
658*bb611c8fSApple OSS Distributions OSObject*
659*bb611c8fSApple OSS Distributions OSUnserializeBinary(const char *buffer, size_t bufferSize, OSSharedPtr<OSString>& errorString)
660*bb611c8fSApple OSS Distributions {
661*bb611c8fSApple OSS Distributions 	OSString* errorStringRaw = NULL;
662*bb611c8fSApple OSS Distributions 	OSObject* result = OSUnserializeBinary(buffer, bufferSize, &errorStringRaw);
663*bb611c8fSApple OSS Distributions 	errorString.reset(errorStringRaw, OSNoRetain);
664*bb611c8fSApple OSS Distributions 	return result;
665*bb611c8fSApple OSS Distributions }
666*bb611c8fSApple OSS Distributions 
667*bb611c8fSApple OSS Distributions OSObject*
668*bb611c8fSApple OSS Distributions OSUnserialize(const char *buffer, OSSharedPtr<OSString>& errorString)
669*bb611c8fSApple OSS Distributions {
670*bb611c8fSApple OSS Distributions 	OSString* errorStringRaw = NULL;
671*bb611c8fSApple OSS Distributions 	OSObject* result = OSUnserialize(buffer, &errorStringRaw);
672*bb611c8fSApple OSS Distributions 	errorString.reset(errorStringRaw, OSNoRetain);
673*bb611c8fSApple OSS Distributions 	return result;
674*bb611c8fSApple OSS Distributions }
675