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