1*a3bb9fccSApple OSS Distributions /*
2*a3bb9fccSApple OSS Distributions  * Copyright (c) 2014 Apple Computer, Inc. All rights reserved.
3*a3bb9fccSApple OSS Distributions  *
4*a3bb9fccSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*a3bb9fccSApple OSS Distributions  *
6*a3bb9fccSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*a3bb9fccSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*a3bb9fccSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*a3bb9fccSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*a3bb9fccSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*a3bb9fccSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*a3bb9fccSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*a3bb9fccSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*a3bb9fccSApple OSS Distributions  *
15*a3bb9fccSApple OSS Distributions  * Please obtain a copy of the License at
16*a3bb9fccSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*a3bb9fccSApple OSS Distributions  *
18*a3bb9fccSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*a3bb9fccSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*a3bb9fccSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*a3bb9fccSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*a3bb9fccSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*a3bb9fccSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*a3bb9fccSApple OSS Distributions  * limitations under the License.
25*a3bb9fccSApple OSS Distributions  *
26*a3bb9fccSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*a3bb9fccSApple OSS Distributions  */
28*a3bb9fccSApple OSS Distributions 
29*a3bb9fccSApple OSS Distributions 
30*a3bb9fccSApple OSS Distributions #include <libkern/c++/OSContainers.h>
31*a3bb9fccSApple OSS Distributions #include <libkern/c++/OSLib.h>
32*a3bb9fccSApple OSS Distributions #include <libkern/c++/OSDictionary.h>
33*a3bb9fccSApple OSS Distributions #include <libkern/OSSerializeBinary.h>
34*a3bb9fccSApple OSS Distributions 
35*a3bb9fccSApple OSS Distributions #include <IOKit/IOLib.h>
36*a3bb9fccSApple OSS Distributions 
37*a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
38*a3bb9fccSApple OSS Distributions 
39*a3bb9fccSApple OSS Distributions #if 0
40*a3bb9fccSApple OSS Distributions #define DEBG(fmt, args...)  { kprintf(fmt, args); }
41*a3bb9fccSApple OSS Distributions #else
42*a3bb9fccSApple OSS Distributions #define DEBG(fmt, args...)	{}
43*a3bb9fccSApple OSS Distributions #endif
44*a3bb9fccSApple OSS Distributions 
45*a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46*a3bb9fccSApple OSS Distributions 
47*a3bb9fccSApple OSS Distributions OSSerialize *OSSerialize::binaryWithCapacity(unsigned int inCapacity,
48*a3bb9fccSApple OSS Distributions 											 Editor editor, void * reference)
49*a3bb9fccSApple OSS Distributions {
50*a3bb9fccSApple OSS Distributions 	OSSerialize *me;
51*a3bb9fccSApple OSS Distributions 
52*a3bb9fccSApple OSS Distributions     if (inCapacity < sizeof(uint32_t)) return (0);
53*a3bb9fccSApple OSS Distributions 	me = OSSerialize::withCapacity(inCapacity);
54*a3bb9fccSApple OSS Distributions     if (!me) return (0);
55*a3bb9fccSApple OSS Distributions 
56*a3bb9fccSApple OSS Distributions     me->binary        = true;
57*a3bb9fccSApple OSS Distributions     me->endCollection = true;
58*a3bb9fccSApple OSS Distributions     me->editor        = editor;
59*a3bb9fccSApple OSS Distributions     me->editRef       = reference;
60*a3bb9fccSApple OSS Distributions 
61*a3bb9fccSApple OSS Distributions 	bcopy(kOSSerializeBinarySignature, &me->data[0], sizeof(kOSSerializeBinarySignature));
62*a3bb9fccSApple OSS Distributions 	me->length = sizeof(kOSSerializeBinarySignature);
63*a3bb9fccSApple OSS Distributions 
64*a3bb9fccSApple OSS Distributions     return (me);
65*a3bb9fccSApple OSS Distributions }
66*a3bb9fccSApple OSS Distributions 
67*a3bb9fccSApple OSS Distributions bool OSSerialize::addBinary(const void * bits, size_t size)
68*a3bb9fccSApple OSS Distributions {
69*a3bb9fccSApple OSS Distributions     unsigned int newCapacity;
70*a3bb9fccSApple OSS Distributions     size_t       alignSize;
71*a3bb9fccSApple OSS Distributions 
72*a3bb9fccSApple OSS Distributions 	alignSize = ((size + 3) & ~3L);
73*a3bb9fccSApple OSS Distributions 	newCapacity = length + alignSize;
74*a3bb9fccSApple OSS Distributions 	if (newCapacity >= capacity)
75*a3bb9fccSApple OSS Distributions 	{
76*a3bb9fccSApple OSS Distributions 	   newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement;
77*a3bb9fccSApple OSS Distributions 	   if (newCapacity < ensureCapacity(newCapacity)) return (false);
78*a3bb9fccSApple OSS Distributions     }
79*a3bb9fccSApple OSS Distributions 
80*a3bb9fccSApple OSS Distributions 	bcopy(bits, &data[length], size);
81*a3bb9fccSApple OSS Distributions 	length += alignSize;
82*a3bb9fccSApple OSS Distributions 
83*a3bb9fccSApple OSS Distributions 	return (true);
84*a3bb9fccSApple OSS Distributions }
85*a3bb9fccSApple OSS Distributions 
86*a3bb9fccSApple OSS Distributions bool OSSerialize::addBinaryObject(const OSMetaClassBase * o, uint32_t key,
87*a3bb9fccSApple OSS Distributions 								  const void * bits, size_t size)
88*a3bb9fccSApple OSS Distributions {
89*a3bb9fccSApple OSS Distributions     unsigned int newCapacity;
90*a3bb9fccSApple OSS Distributions     size_t       alignSize;
91*a3bb9fccSApple OSS Distributions 	OSNumber   * tagNum;
92*a3bb9fccSApple OSS Distributions 
93*a3bb9fccSApple OSS Distributions 	// build a tag
94*a3bb9fccSApple OSS Distributions 	tagNum = OSNumber::withNumber(tag, 32);
95*a3bb9fccSApple OSS Distributions 	tag++;
96*a3bb9fccSApple OSS Distributions     // add to tag dictionary
97*a3bb9fccSApple OSS Distributions 	tags->setObject((const OSSymbol *) o, tagNum);
98*a3bb9fccSApple OSS Distributions 	tagNum->release();
99*a3bb9fccSApple OSS Distributions 
100*a3bb9fccSApple OSS Distributions 	alignSize = ((size + sizeof(key) + 3) & ~3L);
101*a3bb9fccSApple OSS Distributions 	newCapacity = length + alignSize;
102*a3bb9fccSApple OSS Distributions 	if (newCapacity >= capacity)
103*a3bb9fccSApple OSS Distributions 	{
104*a3bb9fccSApple OSS Distributions 	   newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement;
105*a3bb9fccSApple OSS Distributions 	   if (newCapacity < ensureCapacity(newCapacity)) return (false);
106*a3bb9fccSApple OSS Distributions     }
107*a3bb9fccSApple OSS Distributions 
108*a3bb9fccSApple OSS Distributions     if (endCollection)
109*a3bb9fccSApple OSS Distributions     {
110*a3bb9fccSApple OSS Distributions          endCollection = false;
111*a3bb9fccSApple OSS Distributions          key |= kOSSerializeEndCollecton;
112*a3bb9fccSApple OSS Distributions     }
113*a3bb9fccSApple OSS Distributions 
114*a3bb9fccSApple OSS Distributions 	bcopy(&key, &data[length], sizeof(key));
115*a3bb9fccSApple OSS Distributions 	bcopy(bits, &data[length + sizeof(key)], size);
116*a3bb9fccSApple OSS Distributions 	length += alignSize;
117*a3bb9fccSApple OSS Distributions 
118*a3bb9fccSApple OSS Distributions 	return (true);
119*a3bb9fccSApple OSS Distributions }
120*a3bb9fccSApple OSS Distributions 
121*a3bb9fccSApple OSS Distributions bool OSSerialize::binarySerialize(const OSMetaClassBase *o)
122*a3bb9fccSApple OSS Distributions {
123*a3bb9fccSApple OSS Distributions     OSDictionary * dict;
124*a3bb9fccSApple OSS Distributions     OSArray      * array;
125*a3bb9fccSApple OSS Distributions     OSSet        * set;
126*a3bb9fccSApple OSS Distributions     OSNumber     * num;
127*a3bb9fccSApple OSS Distributions     OSSymbol     * sym;
128*a3bb9fccSApple OSS Distributions     OSString     * str;
129*a3bb9fccSApple OSS Distributions     OSData       * data;
130*a3bb9fccSApple OSS Distributions     OSBoolean    * boo;
131*a3bb9fccSApple OSS Distributions 
132*a3bb9fccSApple OSS Distributions 	OSNumber * tagNum;
133*a3bb9fccSApple OSS Distributions     uint32_t   i, key;
134*a3bb9fccSApple OSS Distributions     size_t     len;
135*a3bb9fccSApple OSS Distributions     bool       ok;
136*a3bb9fccSApple OSS Distributions 
137*a3bb9fccSApple OSS Distributions 	tagNum = (OSNumber *)tags->getObject((const OSSymbol *) o);
138*a3bb9fccSApple OSS Distributions 	// does it exist?
139*a3bb9fccSApple OSS Distributions 	if (tagNum)
140*a3bb9fccSApple OSS Distributions 	{
141*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeObject | tagNum->unsigned32BitValue());
142*a3bb9fccSApple OSS Distributions 		if (endCollection)
143*a3bb9fccSApple OSS Distributions 		{
144*a3bb9fccSApple OSS Distributions 			 endCollection = false;
145*a3bb9fccSApple OSS Distributions 			 key |= kOSSerializeEndCollecton;
146*a3bb9fccSApple OSS Distributions 		}
147*a3bb9fccSApple OSS Distributions 		ok = addBinary(&key, sizeof(key));
148*a3bb9fccSApple OSS Distributions 		return (ok);
149*a3bb9fccSApple OSS Distributions 	}
150*a3bb9fccSApple OSS Distributions 
151*a3bb9fccSApple OSS Distributions 	if ((dict = OSDynamicCast(OSDictionary, o)))
152*a3bb9fccSApple OSS Distributions 	{
153*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeDictionary | dict->count);
154*a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0);
155*a3bb9fccSApple OSS Distributions 		for (i = 0; ok && (i < dict->count);)
156*a3bb9fccSApple OSS Distributions 		{
157*a3bb9fccSApple OSS Distributions 			const OSSymbol        * dictKey;
158*a3bb9fccSApple OSS Distributions 			const OSMetaClassBase * dictValue;
159*a3bb9fccSApple OSS Distributions 			const OSMetaClassBase * nvalue = 0;
160*a3bb9fccSApple OSS Distributions 
161*a3bb9fccSApple OSS Distributions 			i++;
162*a3bb9fccSApple OSS Distributions 			dictKey = dict->dictionary[i-1].key;
163*a3bb9fccSApple OSS Distributions 			dictValue = dict->dictionary[i-1].value;
164*a3bb9fccSApple OSS Distributions 			if (editor)
165*a3bb9fccSApple OSS Distributions 			{
166*a3bb9fccSApple OSS Distributions 				dictValue = nvalue = (*editor)(editRef, this, dict, dictKey, dictValue);
167*a3bb9fccSApple OSS Distributions 				if (!dictValue) dictValue = dict;
168*a3bb9fccSApple OSS Distributions 			}
169*a3bb9fccSApple OSS Distributions 			ok = binarySerialize(dictKey);
170*a3bb9fccSApple OSS Distributions 			if (!ok) break;
171*a3bb9fccSApple OSS Distributions 			endCollection = (i == dict->count);
172*a3bb9fccSApple OSS Distributions 			ok = binarySerialize(dictValue);
173*a3bb9fccSApple OSS Distributions 			if (!ok) ok = dictValue->serialize(this);
174*a3bb9fccSApple OSS Distributions 			if (nvalue) nvalue->release();
175*a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
176*a3bb9fccSApple OSS Distributions 		}
177*a3bb9fccSApple OSS Distributions 	}
178*a3bb9fccSApple OSS Distributions 	else if ((array = OSDynamicCast(OSArray, o)))
179*a3bb9fccSApple OSS Distributions 	{
180*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeArray | array->count);
181*a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0);
182*a3bb9fccSApple OSS Distributions 		for (i = 0; ok && (i < array->count);)
183*a3bb9fccSApple OSS Distributions 		{
184*a3bb9fccSApple OSS Distributions 			i++;
185*a3bb9fccSApple OSS Distributions 			endCollection = (i == array->count);
186*a3bb9fccSApple OSS Distributions 			ok = binarySerialize(array->array[i-1]);
187*a3bb9fccSApple OSS Distributions 			if (!ok) ok = array->array[i-1]->serialize(this);
188*a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
189*a3bb9fccSApple OSS Distributions 		}
190*a3bb9fccSApple OSS Distributions 	}
191*a3bb9fccSApple OSS Distributions 	else if ((set = OSDynamicCast(OSSet, o)))
192*a3bb9fccSApple OSS Distributions 	{
193*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeSet | set->members->count);
194*a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0);
195*a3bb9fccSApple OSS Distributions 		for (i = 0; ok && (i < set->members->count);)
196*a3bb9fccSApple OSS Distributions 		{
197*a3bb9fccSApple OSS Distributions 			i++;
198*a3bb9fccSApple OSS Distributions 			endCollection = (i == set->members->count);
199*a3bb9fccSApple OSS Distributions 			ok = binarySerialize(set->members->array[i-1]);
200*a3bb9fccSApple OSS Distributions 			if (!ok) ok = set->members->array[i-1]->serialize(this);
201*a3bb9fccSApple OSS Distributions //			if (!ok) ok = binarySerialize(kOSBooleanFalse);
202*a3bb9fccSApple OSS Distributions 		}
203*a3bb9fccSApple OSS Distributions 	}
204*a3bb9fccSApple OSS Distributions 	else if ((num = OSDynamicCast(OSNumber, o)))
205*a3bb9fccSApple OSS Distributions 	{
206*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeNumber | num->size);
207*a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, &num->value, sizeof(num->value));
208*a3bb9fccSApple OSS Distributions 	}
209*a3bb9fccSApple OSS Distributions 	else if ((boo = OSDynamicCast(OSBoolean, o)))
210*a3bb9fccSApple OSS Distributions 	{
211*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeBoolean | (kOSBooleanTrue == boo));
212*a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, NULL, 0);
213*a3bb9fccSApple OSS Distributions 	}
214*a3bb9fccSApple OSS Distributions 	else if ((sym = OSDynamicCast(OSSymbol, o)))
215*a3bb9fccSApple OSS Distributions 	{
216*a3bb9fccSApple OSS Distributions 		len = (sym->getLength() + 1);
217*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeSymbol | len);
218*a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, sym->getCStringNoCopy(), len);
219*a3bb9fccSApple OSS Distributions 	}
220*a3bb9fccSApple OSS Distributions 	else if ((str = OSDynamicCast(OSString, o)))
221*a3bb9fccSApple OSS Distributions 	{
222*a3bb9fccSApple OSS Distributions 		len = (str->getLength() + 0);
223*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeString | len);
224*a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, str->getCStringNoCopy(), len);
225*a3bb9fccSApple OSS Distributions 	}
226*a3bb9fccSApple OSS Distributions 	else if ((data = OSDynamicCast(OSData, o)))
227*a3bb9fccSApple OSS Distributions 	{
228*a3bb9fccSApple OSS Distributions 		len = data->getLength();
229*a3bb9fccSApple OSS Distributions 		if (data->reserved && data->reserved->disableSerialization) len = 0;
230*a3bb9fccSApple OSS Distributions 		key = (kOSSerializeData | len);
231*a3bb9fccSApple OSS Distributions 		ok = addBinaryObject(o, key, data->getBytesNoCopy(), len);
232*a3bb9fccSApple OSS Distributions 	}
233*a3bb9fccSApple OSS Distributions 	else return (false);
234*a3bb9fccSApple OSS Distributions 
235*a3bb9fccSApple OSS Distributions     return (ok);
236*a3bb9fccSApple OSS Distributions }
237*a3bb9fccSApple OSS Distributions 
238*a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
239*a3bb9fccSApple OSS Distributions 
240*a3bb9fccSApple OSS Distributions #define setAtIndex(v, idx, o)													\
241*a3bb9fccSApple OSS Distributions 	if (idx >= v##Capacity)														\
242*a3bb9fccSApple OSS Distributions 	{																			\
243*a3bb9fccSApple OSS Distributions 		uint32_t ncap = v##Capacity + 64;										\
244*a3bb9fccSApple OSS Distributions 		typeof(v##Array) nbuf = (typeof(v##Array)) kalloc(ncap * sizeof(o));	\
245*a3bb9fccSApple OSS Distributions 		if (!nbuf) ok = false;													\
246*a3bb9fccSApple OSS Distributions 		if (v##Array)															\
247*a3bb9fccSApple OSS Distributions 		{																		\
248*a3bb9fccSApple OSS Distributions 			bcopy(v##Array, nbuf, v##Capacity * sizeof(o));						\
249*a3bb9fccSApple OSS Distributions 			kfree(v##Array, v##Capacity * sizeof(o));							\
250*a3bb9fccSApple OSS Distributions 		}																		\
251*a3bb9fccSApple OSS Distributions 		v##Array    = nbuf;														\
252*a3bb9fccSApple OSS Distributions 		v##Capacity = ncap;														\
253*a3bb9fccSApple OSS Distributions 	}																			\
254*a3bb9fccSApple OSS Distributions 	if (ok) v##Array[idx] = o;
255*a3bb9fccSApple OSS Distributions 
256*a3bb9fccSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
257*a3bb9fccSApple OSS Distributions 
258*a3bb9fccSApple OSS Distributions OSObject *
259*a3bb9fccSApple OSS Distributions OSUnserializeBinary(const char *buffer, size_t bufferSize, OSString **errorString)
260*a3bb9fccSApple OSS Distributions {
261*a3bb9fccSApple OSS Distributions 	OSObject ** objsArray;
262*a3bb9fccSApple OSS Distributions 	uint32_t    objsCapacity;
263*a3bb9fccSApple OSS Distributions 	uint32_t    objsIdx;
264*a3bb9fccSApple OSS Distributions 
265*a3bb9fccSApple OSS Distributions 	OSObject ** stackArray;
266*a3bb9fccSApple OSS Distributions 	uint32_t    stackCapacity;
267*a3bb9fccSApple OSS Distributions 	uint32_t    stackIdx;
268*a3bb9fccSApple OSS Distributions 
269*a3bb9fccSApple OSS Distributions     OSObject     * result;
270*a3bb9fccSApple OSS Distributions     OSObject     * parent;
271*a3bb9fccSApple OSS Distributions     OSDictionary * dict;
272*a3bb9fccSApple OSS Distributions     OSArray      * array;
273*a3bb9fccSApple OSS Distributions     OSSet        * set;
274*a3bb9fccSApple OSS Distributions     OSDictionary * newDict;
275*a3bb9fccSApple OSS Distributions     OSArray      * newArray;
276*a3bb9fccSApple OSS Distributions     OSSet        * newSet;
277*a3bb9fccSApple OSS Distributions     OSObject     * o;
278*a3bb9fccSApple OSS Distributions     OSSymbol     * sym;
279*a3bb9fccSApple OSS Distributions 
280*a3bb9fccSApple OSS Distributions     size_t           bufferPos;
281*a3bb9fccSApple OSS Distributions     const uint32_t * next;
282*a3bb9fccSApple OSS Distributions     uint32_t         key, len, wordLen;
283*a3bb9fccSApple OSS Distributions     bool             end, newCollect, isRef;
284*a3bb9fccSApple OSS Distributions     unsigned long long value;
285*a3bb9fccSApple OSS Distributions     bool ok;
286*a3bb9fccSApple OSS Distributions 
287*a3bb9fccSApple OSS Distributions 	if (errorString) *errorString = 0;
288*a3bb9fccSApple OSS Distributions 	if (0 != strcmp(kOSSerializeBinarySignature, buffer)) return (NULL);
289*a3bb9fccSApple OSS Distributions 	if (3 & ((uintptr_t) buffer)) return (NULL);
290*a3bb9fccSApple OSS Distributions 	if (bufferSize < sizeof(kOSSerializeBinarySignature)) return (NULL);
291*a3bb9fccSApple OSS Distributions 	bufferPos = sizeof(kOSSerializeBinarySignature);
292*a3bb9fccSApple OSS Distributions 	next = (typeof(next)) (((uintptr_t) buffer) + bufferPos);
293*a3bb9fccSApple OSS Distributions 
294*a3bb9fccSApple OSS Distributions 	DEBG("---------OSUnserializeBinary(%p)\n", buffer);
295*a3bb9fccSApple OSS Distributions 
296*a3bb9fccSApple OSS Distributions 	objsArray = stackArray    = NULL;
297*a3bb9fccSApple OSS Distributions 	objsIdx   = objsCapacity  = 0;
298*a3bb9fccSApple OSS Distributions 	stackIdx  = stackCapacity = 0;
299*a3bb9fccSApple OSS Distributions 
300*a3bb9fccSApple OSS Distributions     result   = 0;
301*a3bb9fccSApple OSS Distributions     parent   = 0;
302*a3bb9fccSApple OSS Distributions 	dict     = 0;
303*a3bb9fccSApple OSS Distributions 	array    = 0;
304*a3bb9fccSApple OSS Distributions 	set      = 0;
305*a3bb9fccSApple OSS Distributions 	sym      = 0;
306*a3bb9fccSApple OSS Distributions 
307*a3bb9fccSApple OSS Distributions 	ok = true;
308*a3bb9fccSApple OSS Distributions 	while (ok)
309*a3bb9fccSApple OSS Distributions 	{
310*a3bb9fccSApple OSS Distributions 		bufferPos += sizeof(*next);
311*a3bb9fccSApple OSS Distributions 		if (!(ok = (bufferPos <= bufferSize))) break;
312*a3bb9fccSApple OSS Distributions 		key = *next++;
313*a3bb9fccSApple OSS Distributions 
314*a3bb9fccSApple OSS Distributions         len = (key & kOSSerializeDataMask);
315*a3bb9fccSApple OSS Distributions         wordLen = (len + 3) >> 2;
316*a3bb9fccSApple OSS Distributions 		end = (0 != (kOSSerializeEndCollecton & key));
317*a3bb9fccSApple OSS Distributions         DEBG("key 0x%08x: 0x%04x, %d\n", key, len, end);
318*a3bb9fccSApple OSS Distributions 
319*a3bb9fccSApple OSS Distributions         newCollect = isRef = false;
320*a3bb9fccSApple OSS Distributions 		o = 0; newDict = 0; newArray = 0; newSet = 0;
321*a3bb9fccSApple OSS Distributions 
322*a3bb9fccSApple OSS Distributions 		switch (kOSSerializeTypeMask & key)
323*a3bb9fccSApple OSS Distributions 		{
324*a3bb9fccSApple OSS Distributions 		    case kOSSerializeDictionary:
325*a3bb9fccSApple OSS Distributions 				o = newDict = OSDictionary::withCapacity(len);
326*a3bb9fccSApple OSS Distributions 				newCollect = (len != 0);
327*a3bb9fccSApple OSS Distributions 		        break;
328*a3bb9fccSApple OSS Distributions 		    case kOSSerializeArray:
329*a3bb9fccSApple OSS Distributions 				o = newArray = OSArray::withCapacity(len);
330*a3bb9fccSApple OSS Distributions 				newCollect = (len != 0);
331*a3bb9fccSApple OSS Distributions 		        break;
332*a3bb9fccSApple OSS Distributions 		    case kOSSerializeSet:
333*a3bb9fccSApple OSS Distributions 				o = newSet = OSSet::withCapacity(len);
334*a3bb9fccSApple OSS Distributions 				newCollect = (len != 0);
335*a3bb9fccSApple OSS Distributions 		        break;
336*a3bb9fccSApple OSS Distributions 
337*a3bb9fccSApple OSS Distributions 		    case kOSSerializeObject:
338*a3bb9fccSApple OSS Distributions 				if (len >= objsIdx) break;
339*a3bb9fccSApple OSS Distributions 				o = objsArray[len];
340*a3bb9fccSApple OSS Distributions 				o->retain();
341*a3bb9fccSApple OSS Distributions 				isRef = true;
342*a3bb9fccSApple OSS Distributions 				break;
343*a3bb9fccSApple OSS Distributions 
344*a3bb9fccSApple OSS Distributions 		    case kOSSerializeNumber:
345*a3bb9fccSApple OSS Distributions 				bufferPos += sizeof(long long);
346*a3bb9fccSApple OSS Distributions 				if (bufferPos > bufferSize) break;
347*a3bb9fccSApple OSS Distributions 		    	value = next[1];
348*a3bb9fccSApple OSS Distributions 		    	value <<= 32;
349*a3bb9fccSApple OSS Distributions 		    	value |= next[0];
350*a3bb9fccSApple OSS Distributions 		    	o = OSNumber::withNumber(value, len);
351*a3bb9fccSApple OSS Distributions 		    	next += 2;
352*a3bb9fccSApple OSS Distributions 		        break;
353*a3bb9fccSApple OSS Distributions 
354*a3bb9fccSApple OSS Distributions 		    case kOSSerializeSymbol:
355*a3bb9fccSApple OSS Distributions 				bufferPos += (wordLen * sizeof(uint32_t));
356*a3bb9fccSApple OSS Distributions 				if (bufferPos > bufferSize)           break;
357*a3bb9fccSApple OSS Distributions 				if (0 != ((const char *)next)[len-1]) break;
358*a3bb9fccSApple OSS Distributions 		        o = (OSObject *) OSSymbol::withCString((const char *) next);
359*a3bb9fccSApple OSS Distributions 		        next += wordLen;
360*a3bb9fccSApple OSS Distributions 		        break;
361*a3bb9fccSApple OSS Distributions 
362*a3bb9fccSApple OSS Distributions 		    case kOSSerializeString:
363*a3bb9fccSApple OSS Distributions 				bufferPos += (wordLen * sizeof(uint32_t));
364*a3bb9fccSApple OSS Distributions 				if (bufferPos > bufferSize) break;
365*a3bb9fccSApple OSS Distributions 		        o = OSString::withStringOfLength((const char *) next, len);
366*a3bb9fccSApple OSS Distributions 		        next += wordLen;
367*a3bb9fccSApple OSS Distributions 		        break;
368*a3bb9fccSApple OSS Distributions 
369*a3bb9fccSApple OSS Distributions     	    case kOSSerializeData:
370*a3bb9fccSApple OSS Distributions 				bufferPos += (wordLen * sizeof(uint32_t));
371*a3bb9fccSApple OSS Distributions 				if (bufferPos > bufferSize) break;
372*a3bb9fccSApple OSS Distributions 		        o = OSData::withBytes(next, len);
373*a3bb9fccSApple OSS Distributions 		        next += wordLen;
374*a3bb9fccSApple OSS Distributions 		        break;
375*a3bb9fccSApple OSS Distributions 
376*a3bb9fccSApple OSS Distributions     	    case kOSSerializeBoolean:
377*a3bb9fccSApple OSS Distributions 				o = (len ? kOSBooleanTrue : kOSBooleanFalse);
378*a3bb9fccSApple OSS Distributions 		        break;
379*a3bb9fccSApple OSS Distributions 
380*a3bb9fccSApple OSS Distributions 		    default:
381*a3bb9fccSApple OSS Distributions 		        break;
382*a3bb9fccSApple OSS Distributions 		}
383*a3bb9fccSApple OSS Distributions 
384*a3bb9fccSApple OSS Distributions 		if (!(ok = (o != 0))) break;
385*a3bb9fccSApple OSS Distributions 
386*a3bb9fccSApple OSS Distributions 		if (!isRef)
387*a3bb9fccSApple OSS Distributions 		{
388*a3bb9fccSApple OSS Distributions 			setAtIndex(objs, objsIdx, o);
389*a3bb9fccSApple OSS Distributions 			if (!ok) break;
390*a3bb9fccSApple OSS Distributions 			objsIdx++;
391*a3bb9fccSApple OSS Distributions 		}
392*a3bb9fccSApple OSS Distributions 
393*a3bb9fccSApple OSS Distributions 		if (dict)
394*a3bb9fccSApple OSS Distributions 		{
395*a3bb9fccSApple OSS Distributions 			if (sym)
396*a3bb9fccSApple OSS Distributions 			{
397*a3bb9fccSApple OSS Distributions 				DEBG("%s = %s\n", sym->getCStringNoCopy(), o->getMetaClass()->getClassName());
398*a3bb9fccSApple OSS Distributions 				if (o != dict) ok = dict->setObject(sym, o);
399*a3bb9fccSApple OSS Distributions 				o->release();
400*a3bb9fccSApple OSS Distributions 				sym->release();
401*a3bb9fccSApple OSS Distributions 				sym = 0;
402*a3bb9fccSApple OSS Distributions 			}
403*a3bb9fccSApple OSS Distributions 			else
404*a3bb9fccSApple OSS Distributions 			{
405*a3bb9fccSApple OSS Distributions 				sym = OSDynamicCast(OSSymbol, o);
406*a3bb9fccSApple OSS Distributions 				ok = (sym != 0);
407*a3bb9fccSApple OSS Distributions 			}
408*a3bb9fccSApple OSS Distributions 		}
409*a3bb9fccSApple OSS Distributions 		else if (array)
410*a3bb9fccSApple OSS Distributions 		{
411*a3bb9fccSApple OSS Distributions 			ok = array->setObject(o);
412*a3bb9fccSApple OSS Distributions 		    o->release();
413*a3bb9fccSApple OSS Distributions 		}
414*a3bb9fccSApple OSS Distributions 		else if (set)
415*a3bb9fccSApple OSS Distributions 		{
416*a3bb9fccSApple OSS Distributions 		   ok = set->setObject(o);
417*a3bb9fccSApple OSS Distributions 		   o->release();
418*a3bb9fccSApple OSS Distributions 		}
419*a3bb9fccSApple OSS Distributions 		else
420*a3bb9fccSApple OSS Distributions 		{
421*a3bb9fccSApple OSS Distributions 		    assert(!parent);
422*a3bb9fccSApple OSS Distributions 		    result = o;
423*a3bb9fccSApple OSS Distributions 		}
424*a3bb9fccSApple OSS Distributions 
425*a3bb9fccSApple OSS Distributions 		if (!ok) break;
426*a3bb9fccSApple OSS Distributions 
427*a3bb9fccSApple OSS Distributions 		if (newCollect)
428*a3bb9fccSApple OSS Distributions 		{
429*a3bb9fccSApple OSS Distributions 			if (!end)
430*a3bb9fccSApple OSS Distributions 			{
431*a3bb9fccSApple OSS Distributions 				stackIdx++;
432*a3bb9fccSApple OSS Distributions 				setAtIndex(stack, stackIdx, parent);
433*a3bb9fccSApple OSS Distributions 				if (!ok) break;
434*a3bb9fccSApple OSS Distributions 			}
435*a3bb9fccSApple OSS Distributions 			DEBG("++stack[%d] %p\n", stackIdx, parent);
436*a3bb9fccSApple OSS Distributions 			parent = o;
437*a3bb9fccSApple OSS Distributions 			dict   = newDict;
438*a3bb9fccSApple OSS Distributions 			array  = newArray;
439*a3bb9fccSApple OSS Distributions 			set    = newSet;
440*a3bb9fccSApple OSS Distributions 			end    = false;
441*a3bb9fccSApple OSS Distributions 		}
442*a3bb9fccSApple OSS Distributions 
443*a3bb9fccSApple OSS Distributions 		if (end)
444*a3bb9fccSApple OSS Distributions 		{
445*a3bb9fccSApple OSS Distributions 			if (!stackIdx) break;
446*a3bb9fccSApple OSS Distributions 			parent = stackArray[stackIdx];
447*a3bb9fccSApple OSS Distributions 			DEBG("--stack[%d] %p\n", stackIdx, parent);
448*a3bb9fccSApple OSS Distributions 			stackIdx--;
449*a3bb9fccSApple OSS Distributions 			set   = 0;
450*a3bb9fccSApple OSS Distributions 			dict  = 0;
451*a3bb9fccSApple OSS Distributions 			array = 0;
452*a3bb9fccSApple OSS Distributions 			if (!(dict = OSDynamicCast(OSDictionary, parent)))
453*a3bb9fccSApple OSS Distributions 			{
454*a3bb9fccSApple OSS Distributions 				if (!(array = OSDynamicCast(OSArray, parent))) ok = (0 != (set = OSDynamicCast(OSSet, parent)));
455*a3bb9fccSApple OSS Distributions 			}
456*a3bb9fccSApple OSS Distributions 		}
457*a3bb9fccSApple OSS Distributions 	}
458*a3bb9fccSApple OSS Distributions 	DEBG("ret %p\n", result);
459*a3bb9fccSApple OSS Distributions 
460*a3bb9fccSApple OSS Distributions 	if (objsCapacity)  kfree(objsArray,  objsCapacity  * sizeof(*objsArray));
461*a3bb9fccSApple OSS Distributions 	if (stackCapacity) kfree(stackArray, stackCapacity * sizeof(*stackArray));
462*a3bb9fccSApple OSS Distributions 
463*a3bb9fccSApple OSS Distributions 	if (!ok && result)
464*a3bb9fccSApple OSS Distributions 	{
465*a3bb9fccSApple OSS Distributions 		result->release();
466*a3bb9fccSApple OSS Distributions 		result = 0;
467*a3bb9fccSApple OSS Distributions 	}
468*a3bb9fccSApple OSS Distributions 	return (result);
469*a3bb9fccSApple OSS Distributions }