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 
30a3bb9fccSApple OSS Distributions #include <libkern/c++/OSContainers.h>
31a3bb9fccSApple OSS Distributions #include <libkern/c++/OSLib.h>
32a3bb9fccSApple OSS Distributions #include <libkern/c++/OSDictionary.h>
33a3bb9fccSApple OSS Distributions #include <libkern/OSSerializeBinary.h>
34a3bb9fccSApple OSS Distributions 
35a3bb9fccSApple OSS Distributions #include <IOKit/IOLib.h>
36a3bb9fccSApple OSS Distributions 
37a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
38a3bb9fccSApple OSS Distributions 
39a3bb9fccSApple OSS Distributions #if 0
40a3bb9fccSApple OSS Distributions #define DEBG(fmt, args...)  { kprintf(fmt, args); }
41a3bb9fccSApple OSS Distributions #else
42a3bb9fccSApple OSS Distributions #define DEBG(fmt, args...)	{}
43a3bb9fccSApple OSS Distributions #endif
44a3bb9fccSApple OSS Distributions 
45a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46a3bb9fccSApple OSS Distributions 
47a3bb9fccSApple OSS Distributions OSSerialize *OSSerialize::binaryWithCapacity(unsigned int inCapacity,
48a3bb9fccSApple OSS Distributions 											 Editor editor, void * reference)
49a3bb9fccSApple OSS Distributions {
50a3bb9fccSApple OSS Distributions 	OSSerialize *me;
51a3bb9fccSApple OSS Distributions 
52a3bb9fccSApple OSS Distributions     if (inCapacity < sizeof(uint32_t)) return (0);
53a3bb9fccSApple OSS Distributions 	me = OSSerialize::withCapacity(inCapacity);
54a3bb9fccSApple OSS Distributions     if (!me) return (0);
55a3bb9fccSApple OSS Distributions 
56a3bb9fccSApple OSS Distributions     me->binary        = true;
57a3bb9fccSApple OSS Distributions     me->endCollection = true;
58a3bb9fccSApple OSS Distributions     me->editor        = editor;
59a3bb9fccSApple OSS Distributions     me->editRef       = reference;
60a3bb9fccSApple OSS Distributions 
61a3bb9fccSApple OSS Distributions 	bcopy(kOSSerializeBinarySignature, &me->data[0], sizeof(kOSSerializeBinarySignature));
62a3bb9fccSApple OSS Distributions 	me->length = sizeof(kOSSerializeBinarySignature);
63a3bb9fccSApple OSS Distributions 
64a3bb9fccSApple OSS Distributions     return (me);
65a3bb9fccSApple OSS Distributions }
66a3bb9fccSApple OSS Distributions 
67a3bb9fccSApple OSS Distributions bool OSSerialize::addBinary(const void * bits, size_t size)
68a3bb9fccSApple OSS Distributions {
69a3bb9fccSApple OSS Distributions     unsigned int newCapacity;
70a3bb9fccSApple OSS Distributions     size_t       alignSize;
71a3bb9fccSApple OSS Distributions 
72*76e12aa3SApple OSS Distributions 	if (os_add_overflow(size, 3, &alignSize)) return (false);
73*76e12aa3SApple OSS Distributions 	alignSize &= ~3L;
74*76e12aa3SApple OSS Distributions 	if (os_add_overflow(length, alignSize, &newCapacity)) return (false);
75a3bb9fccSApple OSS Distributions 	if (newCapacity >= capacity)
76a3bb9fccSApple OSS Distributions 	{
77a3bb9fccSApple OSS Distributions 	   newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement;
7888cc0b97SApple OSS Distributions 	   if (newCapacity > ensureCapacity(newCapacity)) return (false);
79a3bb9fccSApple OSS Distributions     }
80a3bb9fccSApple OSS Distributions 
81a3bb9fccSApple OSS Distributions 	bcopy(bits, &data[length], size);
82a3bb9fccSApple OSS Distributions 	length += alignSize;
83a3bb9fccSApple OSS Distributions 
84a3bb9fccSApple OSS Distributions 	return (true);
85a3bb9fccSApple OSS Distributions }
86a3bb9fccSApple OSS Distributions 
87a3bb9fccSApple OSS Distributions bool OSSerialize::addBinaryObject(const OSMetaClassBase * o, uint32_t key,
88a3bb9fccSApple OSS Distributions 								  const void * bits, size_t size)
89a3bb9fccSApple OSS Distributions {
90a3bb9fccSApple OSS Distributions     unsigned int newCapacity;
91a3bb9fccSApple OSS Distributions     size_t       alignSize;
92a3bb9fccSApple OSS Distributions 
9388cc0b97SApple OSS Distributions     // add to tag array
9488cc0b97SApple OSS Distributions 	tags->setObject(o);
95a3bb9fccSApple OSS Distributions 
96*76e12aa3SApple OSS Distributions 	if (os_add3_overflow(size, sizeof(key), 3, &alignSize)) return (false);
97*76e12aa3SApple OSS Distributions 	alignSize &= ~3L;
98*76e12aa3SApple OSS Distributions 	if (os_add_overflow(length, alignSize, &newCapacity)) return (false);
99a3bb9fccSApple OSS Distributions 	if (newCapacity >= capacity)
100a3bb9fccSApple OSS Distributions 	{
101a3bb9fccSApple OSS Distributions 	   newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement;
10288cc0b97SApple OSS Distributions 	   if (newCapacity > ensureCapacity(newCapacity)) return (false);
103a3bb9fccSApple OSS Distributions     }
104a3bb9fccSApple OSS Distributions 
105a3bb9fccSApple OSS Distributions     if (endCollection)
106a3bb9fccSApple OSS Distributions     {
107a3bb9fccSApple OSS Distributions          endCollection = false;
108a3bb9fccSApple OSS Distributions          key |= kOSSerializeEndCollecton;
109a3bb9fccSApple OSS Distributions     }
110a3bb9fccSApple OSS Distributions 
111a3bb9fccSApple OSS Distributions 	bcopy(&key, &data[length], sizeof(key));
112a3bb9fccSApple OSS Distributions 	bcopy(bits, &data[length + sizeof(key)], size);
113a3bb9fccSApple OSS Distributions 	length += alignSize;
114a3bb9fccSApple OSS Distributions 
115a3bb9fccSApple OSS Distributions 	return (true);
116a3bb9fccSApple OSS Distributions }
117a3bb9fccSApple OSS Distributions 
118a3bb9fccSApple OSS Distributions bool OSSerialize::binarySerialize(const OSMetaClassBase *o)
119a3bb9fccSApple OSS Distributions {
120a3bb9fccSApple OSS Distributions     OSDictionary * dict;
121a3bb9fccSApple OSS Distributions     OSArray      * array;
122a3bb9fccSApple OSS Distributions     OSSet        * set;
123a3bb9fccSApple OSS Distributions     OSNumber     * num;
124a3bb9fccSApple OSS Distributions     OSSymbol     * sym;
125a3bb9fccSApple OSS Distributions     OSString     * str;
12688cc0b97SApple OSS Distributions     OSData       * ldata;
127a3bb9fccSApple OSS Distributions     OSBoolean    * boo;
128a3bb9fccSApple OSS Distributions 
12988cc0b97SApple OSS Distributions 	unsigned int  tagIdx;
130a3bb9fccSApple OSS Distributions     uint32_t   i, key;
131a3bb9fccSApple OSS Distributions     size_t     len;
132a3bb9fccSApple OSS Distributions     bool       ok;
133a3bb9fccSApple OSS Distributions 
13488cc0b97SApple OSS Distributions 	tagIdx = tags->getNextIndexOfObject(o, 0);
135a3bb9fccSApple OSS Distributions 	// does it exist?
13688cc0b97SApple OSS Distributions 	if (-1U != tagIdx)
137a3bb9fccSApple OSS Distributions 	{
13888cc0b97SApple OSS Distributions 		key = (kOSSerializeObject | tagIdx);
139a3bb9fccSApple OSS Distributions 		if (endCollection)
140a3bb9fccSApple OSS Distributions 		{
141a3bb9fccSApple OSS Distributions 			 endCollection = false;
142a3bb9fccSApple OSS Distributions 			 key |= kOSSerializeEndCollecton;
143a3bb9fccSApple OSS Distributions 		}
144a3bb9fccSApple OSS Distributions 		ok = addBinary(&key, sizeof(key));
145a3bb9fccSApple OSS Distributions 		return (ok);
146a3bb9fccSApple OSS Distributions 	}
147a3bb9fccSApple OSS Distributions 
148a3bb9fccSApple OSS Distributions 	if ((dict = OSDynamicCast(OSDictionary, o)))
149a3bb9fccSApple OSS Distributions 	{
150a3bb9fccSApple OSS Distributions 		key = (kOSSerializeDictionary | dict->count);
151a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0);
152a3bb9fccSApple OSS Distributions 		for (i = 0; ok && (i < dict->count);)
153a3bb9fccSApple OSS Distributions 		{
154a3bb9fccSApple OSS Distributions 			const OSSymbol        * dictKey;
155a3bb9fccSApple OSS Distributions 			const OSMetaClassBase * dictValue;
156a3bb9fccSApple OSS Distributions 			const OSMetaClassBase * nvalue = 0;
157a3bb9fccSApple OSS Distributions 
15888cc0b97SApple OSS Distributions 			dictKey = dict->dictionary[i].key;
15988cc0b97SApple OSS Distributions 			dictValue = dict->dictionary[i].value;
160a3bb9fccSApple OSS Distributions 			i++;
161a3bb9fccSApple OSS Distributions 			if (editor)
162a3bb9fccSApple OSS Distributions 			{
163a3bb9fccSApple OSS Distributions 				dictValue = nvalue = (*editor)(editRef, this, dict, dictKey, dictValue);
164a3bb9fccSApple OSS Distributions 				if (!dictValue) dictValue = dict;
165a3bb9fccSApple OSS Distributions 			}
166a3bb9fccSApple OSS Distributions 			ok = binarySerialize(dictKey);
167a3bb9fccSApple OSS Distributions 			if (!ok) break;
168a3bb9fccSApple OSS Distributions 			endCollection = (i == dict->count);
169a3bb9fccSApple OSS Distributions 			ok = binarySerialize(dictValue);
170a3bb9fccSApple OSS Distributions 			if (!ok) ok = dictValue->serialize(this);
171a3bb9fccSApple OSS Distributions 			if (nvalue) nvalue->release();
172a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
173a3bb9fccSApple OSS Distributions 		}
174a3bb9fccSApple OSS Distributions 	}
175a3bb9fccSApple OSS Distributions 	else if ((array = OSDynamicCast(OSArray, o)))
176a3bb9fccSApple OSS Distributions 	{
177a3bb9fccSApple OSS Distributions 		key = (kOSSerializeArray | array->count);
178a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0);
179a3bb9fccSApple OSS Distributions 		for (i = 0; ok && (i < array->count);)
180a3bb9fccSApple OSS Distributions 		{
181a3bb9fccSApple OSS Distributions 			i++;
182a3bb9fccSApple OSS Distributions 			endCollection = (i == array->count);
183a3bb9fccSApple OSS Distributions 			ok = binarySerialize(array->array[i-1]);
184a3bb9fccSApple OSS Distributions 			if (!ok) ok = array->array[i-1]->serialize(this);
185a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
186a3bb9fccSApple OSS Distributions 		}
187a3bb9fccSApple OSS Distributions 	}
188a3bb9fccSApple OSS Distributions 	else if ((set = OSDynamicCast(OSSet, o)))
189a3bb9fccSApple OSS Distributions 	{
190a3bb9fccSApple OSS Distributions 		key = (kOSSerializeSet | set->members->count);
191a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0);
192a3bb9fccSApple OSS Distributions 		for (i = 0; ok && (i < set->members->count);)
193a3bb9fccSApple OSS Distributions 		{
194a3bb9fccSApple OSS Distributions 			i++;
195a3bb9fccSApple OSS Distributions 			endCollection = (i == set->members->count);
196a3bb9fccSApple OSS Distributions 			ok = binarySerialize(set->members->array[i-1]);
197a3bb9fccSApple OSS Distributions 			if (!ok) ok = set->members->array[i-1]->serialize(this);
198a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
199a3bb9fccSApple OSS Distributions 		}
200a3bb9fccSApple OSS Distributions 	}
201a3bb9fccSApple OSS Distributions 	else if ((num = OSDynamicCast(OSNumber, o)))
202a3bb9fccSApple OSS Distributions 	{
203a3bb9fccSApple OSS Distributions 		key = (kOSSerializeNumber | num->size);
204a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, &num->value, sizeof(num->value));
205a3bb9fccSApple OSS Distributions 	}
206a3bb9fccSApple OSS Distributions 	else if ((boo = OSDynamicCast(OSBoolean, o)))
207a3bb9fccSApple OSS Distributions 	{
208a3bb9fccSApple OSS Distributions 		key = (kOSSerializeBoolean | (kOSBooleanTrue == boo));
209a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0);
210a3bb9fccSApple OSS Distributions 	}
211a3bb9fccSApple OSS Distributions 	else if ((sym = OSDynamicCast(OSSymbol, o)))
212a3bb9fccSApple OSS Distributions 	{
213a3bb9fccSApple OSS Distributions 		len = (sym->getLength() + 1);
214a3bb9fccSApple OSS Distributions 		key = (kOSSerializeSymbol | len);
215a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, sym->getCStringNoCopy(), len);
216a3bb9fccSApple OSS Distributions 	}
217a3bb9fccSApple OSS Distributions 	else if ((str = OSDynamicCast(OSString, o)))
218a3bb9fccSApple OSS Distributions 	{
219a3bb9fccSApple OSS Distributions 		len = (str->getLength() + 0);
220a3bb9fccSApple OSS Distributions 		key = (kOSSerializeString | len);
221a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, str->getCStringNoCopy(), len);
222a3bb9fccSApple OSS Distributions 	}
22388cc0b97SApple OSS Distributions 	else if ((ldata = OSDynamicCast(OSData, o)))
224a3bb9fccSApple OSS Distributions 	{
22588cc0b97SApple OSS Distributions 		len = ldata->getLength();
22688cc0b97SApple OSS Distributions 		if (ldata->reserved && ldata->reserved->disableSerialization) len = 0;
227a3bb9fccSApple OSS Distributions 		key = (kOSSerializeData | len);
22888cc0b97SApple OSS Distributions 		ok = addBinaryObject(o, key, ldata->getBytesNoCopy(), len);
229a3bb9fccSApple OSS Distributions 	}
230a3bb9fccSApple OSS Distributions 	else return (false);
231a3bb9fccSApple OSS Distributions 
232a3bb9fccSApple OSS Distributions     return (ok);
233a3bb9fccSApple OSS Distributions }
234a3bb9fccSApple OSS Distributions 
235a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
236a3bb9fccSApple OSS Distributions 
237a3bb9fccSApple OSS Distributions #define setAtIndex(v, idx, o)													        \
238a3bb9fccSApple OSS Distributions 	if (idx >= v##Capacity)														        \
239a3bb9fccSApple OSS Distributions 	{																			        \
24088cc0b97SApple OSS Distributions         if (v##Capacity >= v##CapacityMax) ok = false;                                  \
24188cc0b97SApple OSS Distributions         else																			\
24288cc0b97SApple OSS Distributions         {																			    \
243a3bb9fccSApple OSS Distributions             uint32_t ncap = v##Capacity + 64;										    \
2440f3703acSApple OSS Distributions             typeof(v##Array) nbuf = (typeof(v##Array)) kalloc_container(ncap * sizeof(o)); \
245a3bb9fccSApple OSS Distributions             if (!nbuf) ok = false;													    \
24688cc0b97SApple OSS Distributions             else															            \
24788cc0b97SApple OSS Distributions             {															                \
248a3bb9fccSApple OSS Distributions                 if (v##Array)															\
249a3bb9fccSApple OSS Distributions                 {																		\
250a3bb9fccSApple OSS Distributions                     bcopy(v##Array, nbuf, v##Capacity * sizeof(o));						\
251a3bb9fccSApple OSS Distributions                     kfree(v##Array, v##Capacity * sizeof(o));							\
252a3bb9fccSApple OSS Distributions                 }																		\
253a3bb9fccSApple OSS Distributions                 v##Array    = nbuf;														\
254a3bb9fccSApple OSS Distributions                 v##Capacity = ncap;														\
255a3bb9fccSApple OSS Distributions             }															                \
25688cc0b97SApple OSS Distributions 	    }																			    \
25788cc0b97SApple OSS Distributions 	}																			        \
258a3bb9fccSApple OSS Distributions 	if (ok) v##Array[idx] = o;
259a3bb9fccSApple OSS Distributions 
260a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
261a3bb9fccSApple OSS Distributions 
262a3bb9fccSApple OSS Distributions OSObject *
263a3bb9fccSApple OSS Distributions OSUnserializeBinary(const char *buffer, size_t bufferSize, OSString **errorString)
264a3bb9fccSApple OSS Distributions {
265a3bb9fccSApple OSS Distributions 	OSObject ** objsArray;
266a3bb9fccSApple OSS Distributions 	uint32_t    objsCapacity;
26788cc0b97SApple OSS Distributions 	enum      { objsCapacityMax = 16*1024*1024 };
268a3bb9fccSApple OSS Distributions 	uint32_t    objsIdx;
269a3bb9fccSApple OSS Distributions 
270a3bb9fccSApple OSS Distributions 	OSObject ** stackArray;
271a3bb9fccSApple OSS Distributions 	uint32_t    stackCapacity;
272*76e12aa3SApple OSS Distributions 	enum      { stackCapacityMax = 64 };
273a3bb9fccSApple OSS Distributions 	uint32_t    stackIdx;
274a3bb9fccSApple OSS Distributions 
275a3bb9fccSApple OSS Distributions     OSObject     * result;
276a3bb9fccSApple OSS Distributions     OSObject     * parent;
277a3bb9fccSApple OSS Distributions     OSDictionary * dict;
278a3bb9fccSApple OSS Distributions     OSArray      * array;
279a3bb9fccSApple OSS Distributions     OSSet        * set;
280a3bb9fccSApple OSS Distributions     OSDictionary * newDict;
281a3bb9fccSApple OSS Distributions     OSArray      * newArray;
282a3bb9fccSApple OSS Distributions     OSSet        * newSet;
283a3bb9fccSApple OSS Distributions     OSObject     * o;
284a3bb9fccSApple OSS Distributions     OSSymbol     * sym;
2850f3703acSApple OSS Distributions     OSString     * str;
286a3bb9fccSApple OSS Distributions 
287a3bb9fccSApple OSS Distributions     size_t           bufferPos;
288a3bb9fccSApple OSS Distributions     const uint32_t * next;
289a3bb9fccSApple OSS Distributions     uint32_t         key, len, wordLen;
290a3bb9fccSApple OSS Distributions     bool             end, newCollect, isRef;
291a3bb9fccSApple OSS Distributions     unsigned long long value;
292a3bb9fccSApple OSS Distributions     bool ok;
293a3bb9fccSApple OSS Distributions 
294a3bb9fccSApple OSS Distributions 	if (errorString) *errorString = 0;
29588cc0b97SApple OSS Distributions 	if (bufferSize < sizeof(kOSSerializeBinarySignature)) return (NULL);
296a3bb9fccSApple OSS Distributions 	if (0 != strcmp(kOSSerializeBinarySignature, buffer)) return (NULL);
297a3bb9fccSApple OSS Distributions 	if (3 & ((uintptr_t) buffer)) return (NULL);
298a3bb9fccSApple OSS Distributions 	bufferPos = sizeof(kOSSerializeBinarySignature);
299a3bb9fccSApple OSS Distributions 	next = (typeof(next)) (((uintptr_t) buffer) + bufferPos);
300a3bb9fccSApple OSS Distributions 
301a3bb9fccSApple OSS Distributions 	DEBG("---------OSUnserializeBinary(%p)\n", buffer);
302a3bb9fccSApple OSS Distributions 
303a3bb9fccSApple OSS Distributions 	objsArray = stackArray    = NULL;
304a3bb9fccSApple OSS Distributions 	objsIdx   = objsCapacity  = 0;
305a3bb9fccSApple OSS Distributions 	stackIdx  = stackCapacity = 0;
306a3bb9fccSApple OSS Distributions 
307a3bb9fccSApple OSS Distributions     result   = 0;
308a3bb9fccSApple OSS Distributions     parent   = 0;
309a3bb9fccSApple OSS Distributions 	dict     = 0;
310a3bb9fccSApple OSS Distributions 	array    = 0;
311a3bb9fccSApple OSS Distributions 	set      = 0;
312a3bb9fccSApple OSS Distributions 	sym      = 0;
313a3bb9fccSApple OSS Distributions 
314a3bb9fccSApple OSS Distributions 	ok = true;
315a3bb9fccSApple OSS Distributions 	while (ok)
316a3bb9fccSApple OSS Distributions 	{
317a3bb9fccSApple OSS Distributions 		bufferPos += sizeof(*next);
318a3bb9fccSApple OSS Distributions 		if (!(ok = (bufferPos <= bufferSize))) break;
319a3bb9fccSApple OSS Distributions 		key = *next++;
320a3bb9fccSApple OSS Distributions 
321a3bb9fccSApple OSS Distributions         len = (key & kOSSerializeDataMask);
322a3bb9fccSApple OSS Distributions         wordLen = (len + 3) >> 2;
323a3bb9fccSApple OSS Distributions 		end = (0 != (kOSSerializeEndCollecton & key));
324a3bb9fccSApple OSS Distributions         DEBG("key 0x%08x: 0x%04x, %d\n", key, len, end);
325a3bb9fccSApple OSS Distributions 
326a3bb9fccSApple OSS Distributions         newCollect = isRef = false;
327a3bb9fccSApple OSS Distributions 		o = 0; newDict = 0; newArray = 0; newSet = 0;
328a3bb9fccSApple OSS Distributions 
329a3bb9fccSApple OSS Distributions 		switch (kOSSerializeTypeMask & key)
330a3bb9fccSApple OSS Distributions 		{
331a3bb9fccSApple OSS Distributions 		    case kOSSerializeDictionary:
332a3bb9fccSApple OSS Distributions 				o = newDict = OSDictionary::withCapacity(len);
333a3bb9fccSApple OSS Distributions 				newCollect = (len != 0);
334a3bb9fccSApple OSS Distributions 		        break;
335a3bb9fccSApple OSS Distributions 		    case kOSSerializeArray:
336a3bb9fccSApple OSS Distributions 				o = newArray = OSArray::withCapacity(len);
337a3bb9fccSApple OSS Distributions 				newCollect = (len != 0);
338a3bb9fccSApple OSS Distributions 		        break;
339a3bb9fccSApple OSS Distributions 		    case kOSSerializeSet:
340a3bb9fccSApple OSS Distributions 				o = newSet = OSSet::withCapacity(len);
341a3bb9fccSApple OSS Distributions 				newCollect = (len != 0);
342a3bb9fccSApple OSS Distributions 		        break;
343a3bb9fccSApple OSS Distributions 
344a3bb9fccSApple OSS Distributions 		    case kOSSerializeObject:
345a3bb9fccSApple OSS Distributions 				if (len >= objsIdx) break;
346a3bb9fccSApple OSS Distributions 				o = objsArray[len];
347a3bb9fccSApple OSS Distributions 				isRef = true;
348a3bb9fccSApple OSS Distributions 				break;
349a3bb9fccSApple OSS Distributions 
350a3bb9fccSApple OSS Distributions 		    case kOSSerializeNumber:
351a3bb9fccSApple OSS Distributions 				bufferPos += sizeof(long long);
352a3bb9fccSApple OSS Distributions 				if (bufferPos > bufferSize) break;
35388cc0b97SApple OSS Distributions 		        if ((len != 32) && (len != 64) && (len != 16) && (len != 8)) break;
354a3bb9fccSApple OSS Distributions 		    	value = next[1];
355a3bb9fccSApple OSS Distributions 		    	value <<= 32;
356a3bb9fccSApple OSS Distributions 		    	value |= next[0];
357a3bb9fccSApple OSS Distributions 		    	o = OSNumber::withNumber(value, len);
358a3bb9fccSApple OSS Distributions 		    	next += 2;
359a3bb9fccSApple OSS Distributions 		        break;
360a3bb9fccSApple OSS Distributions 
361a3bb9fccSApple OSS Distributions 		    case kOSSerializeSymbol:
362a3bb9fccSApple OSS Distributions 				bufferPos += (wordLen * sizeof(uint32_t));
363a3bb9fccSApple OSS Distributions 				if (bufferPos > bufferSize)           break;
36488cc0b97SApple OSS Distributions 				if (len < 2)                          break;
365a3bb9fccSApple OSS Distributions 				if (0 != ((const char *)next)[len-1]) break;
366a3bb9fccSApple OSS Distributions 		        o = (OSObject *) OSSymbol::withCString((const char *) next);
367a3bb9fccSApple OSS Distributions 		        next += wordLen;
368a3bb9fccSApple OSS Distributions 		        break;
369a3bb9fccSApple OSS Distributions 
370a3bb9fccSApple OSS Distributions 		    case kOSSerializeString:
371a3bb9fccSApple OSS Distributions 				bufferPos += (wordLen * sizeof(uint32_t));
372a3bb9fccSApple OSS Distributions 				if (bufferPos > bufferSize) break;
373a3bb9fccSApple OSS Distributions 		        o = OSString::withStringOfLength((const char *) next, len);
374a3bb9fccSApple OSS Distributions 		        next += wordLen;
375a3bb9fccSApple OSS Distributions 		        break;
376a3bb9fccSApple OSS Distributions 
377a3bb9fccSApple OSS Distributions     	    case kOSSerializeData:
378a3bb9fccSApple OSS Distributions 				bufferPos += (wordLen * sizeof(uint32_t));
379a3bb9fccSApple OSS Distributions 				if (bufferPos > bufferSize) break;
380a3bb9fccSApple OSS Distributions 		        o = OSData::withBytes(next, len);
381a3bb9fccSApple OSS Distributions 		        next += wordLen;
382a3bb9fccSApple OSS Distributions 		        break;
383a3bb9fccSApple OSS Distributions 
384a3bb9fccSApple OSS Distributions     	    case kOSSerializeBoolean:
385a3bb9fccSApple OSS Distributions 				o = (len ? kOSBooleanTrue : kOSBooleanFalse);
386a3bb9fccSApple OSS Distributions 		        break;
387a3bb9fccSApple OSS Distributions 
388a3bb9fccSApple OSS Distributions 		    default:
389a3bb9fccSApple OSS Distributions 		        break;
390a3bb9fccSApple OSS Distributions 		}
391a3bb9fccSApple OSS Distributions 
392a3bb9fccSApple OSS Distributions 		if (!(ok = (o != 0))) break;
393a3bb9fccSApple OSS Distributions 
394a3bb9fccSApple OSS Distributions 		if (!isRef)
395a3bb9fccSApple OSS Distributions 		{
396a3bb9fccSApple OSS Distributions 			setAtIndex(objs, objsIdx, o);
39788cc0b97SApple OSS Distributions 			if (!ok)
39888cc0b97SApple OSS Distributions 			{
39988cc0b97SApple OSS Distributions 			    o->release();
40088cc0b97SApple OSS Distributions                 break;
40188cc0b97SApple OSS Distributions             }
402a3bb9fccSApple OSS Distributions 			objsIdx++;
403a3bb9fccSApple OSS Distributions 		}
404a3bb9fccSApple OSS Distributions 
405a3bb9fccSApple OSS Distributions 		if (dict)
406a3bb9fccSApple OSS Distributions 		{
40788cc0b97SApple OSS Distributions 			if (!sym) sym = (OSSymbol *) o;
408a3bb9fccSApple OSS Distributions 			else
409a3bb9fccSApple OSS Distributions 			{
41088cc0b97SApple OSS Distributions                 str = sym;
41188cc0b97SApple OSS Distributions 				sym = OSDynamicCast(OSSymbol, sym);
41288cc0b97SApple OSS Distributions 				if (!sym && (str = OSDynamicCast(OSString, str)))
4130f3703acSApple OSS Distributions 				{
4140f3703acSApple OSS Distributions 				    sym = (OSSymbol *) OSSymbol::withString(str);
415a3bb9fccSApple OSS Distributions                     ok = (sym != 0);
41688cc0b97SApple OSS Distributions                     if (!ok) break;
41788cc0b97SApple OSS Distributions 				}
41888cc0b97SApple OSS Distributions 				DEBG("%s = %s\n", sym->getCStringNoCopy(), o->getMetaClass()->getClassName());
41988cc0b97SApple OSS Distributions 				if (o != dict) ok = dict->setObject(sym, o);
42088cc0b97SApple OSS Distributions                 if (sym && (sym != str)) sym->release();
42188cc0b97SApple OSS Distributions 				sym = 0;
422a3bb9fccSApple OSS Distributions 			}
423a3bb9fccSApple OSS Distributions 		}
42488cc0b97SApple OSS Distributions 		else if (array)  ok = array->setObject(o);
42588cc0b97SApple OSS Distributions 		else if (set)    ok = set->setObject(o);
42688cc0b97SApple OSS Distributions 		else if (result) ok = false;
427a3bb9fccSApple OSS Distributions 		else
428a3bb9fccSApple OSS Distributions 		{
429a3bb9fccSApple OSS Distributions 		    assert(!parent);
430a3bb9fccSApple OSS Distributions 		    result = o;
431a3bb9fccSApple OSS Distributions 		}
432a3bb9fccSApple OSS Distributions 
433a3bb9fccSApple OSS Distributions 		if (!ok) break;
434a3bb9fccSApple OSS Distributions 
435*76e12aa3SApple OSS Distributions         if (end) parent = 0;
436a3bb9fccSApple OSS Distributions 		if (newCollect)
437a3bb9fccSApple OSS Distributions 		{
438a3bb9fccSApple OSS Distributions             stackIdx++;
439a3bb9fccSApple OSS Distributions             setAtIndex(stack, stackIdx, parent);
440a3bb9fccSApple OSS Distributions             if (!ok) break;
441a3bb9fccSApple OSS Distributions 			DEBG("++stack[%d] %p\n", stackIdx, parent);
442a3bb9fccSApple OSS Distributions 			parent = o;
443a3bb9fccSApple OSS Distributions 			dict   = newDict;
444a3bb9fccSApple OSS Distributions 			array  = newArray;
445a3bb9fccSApple OSS Distributions 			set    = newSet;
446a3bb9fccSApple OSS Distributions 			end    = false;
447a3bb9fccSApple OSS Distributions 		}
448a3bb9fccSApple OSS Distributions 
449a3bb9fccSApple OSS Distributions 		if (end)
450a3bb9fccSApple OSS Distributions 		{
451*76e12aa3SApple OSS Distributions             while (stackIdx)
452*76e12aa3SApple OSS Distributions             {
453a3bb9fccSApple OSS Distributions                 parent = stackArray[stackIdx];
454a3bb9fccSApple OSS Distributions                 DEBG("--stack[%d] %p\n", stackIdx, parent);
455a3bb9fccSApple OSS Distributions                 stackIdx--;
456*76e12aa3SApple OSS Distributions                 if (parent) break;
457*76e12aa3SApple OSS Distributions             }
458*76e12aa3SApple OSS Distributions             if (!parent) break;
459a3bb9fccSApple OSS Distributions 			set   = 0;
460a3bb9fccSApple OSS Distributions 			dict  = 0;
461a3bb9fccSApple OSS Distributions 			array = 0;
462a3bb9fccSApple OSS Distributions 			if (!(dict = OSDynamicCast(OSDictionary, parent)))
463a3bb9fccSApple OSS Distributions 			{
464a3bb9fccSApple OSS Distributions 				if (!(array = OSDynamicCast(OSArray, parent))) ok = (0 != (set = OSDynamicCast(OSSet, parent)));
465a3bb9fccSApple OSS Distributions 			}
466a3bb9fccSApple OSS Distributions 		}
467a3bb9fccSApple OSS Distributions 	}
468a3bb9fccSApple OSS Distributions 	DEBG("ret %p\n", result);
469a3bb9fccSApple OSS Distributions 
47088cc0b97SApple OSS Distributions 	if (!ok) result = 0;
47188cc0b97SApple OSS Distributions 
47288cc0b97SApple OSS Distributions 	if (objsCapacity)
47388cc0b97SApple OSS Distributions 	{
47488cc0b97SApple OSS Distributions         for (len = (result != 0); len < objsIdx; len++) objsArray[len]->release();
47588cc0b97SApple OSS Distributions 	    kfree(objsArray,  objsCapacity  * sizeof(*objsArray));
47688cc0b97SApple OSS Distributions     }
477a3bb9fccSApple OSS Distributions 	if (stackCapacity) kfree(stackArray, stackCapacity * sizeof(*stackArray));
478a3bb9fccSApple OSS Distributions 
479a3bb9fccSApple OSS Distributions 	return (result);
480a3bb9fccSApple OSS Distributions }
481