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