]> git.saurik.com Git - apple/cf.git/blobdiff - Parsing.subproj/CFBinaryPList.c
CF-476.10.tar.gz
[apple/cf.git] / Parsing.subproj / CFBinaryPList.c
diff --git a/Parsing.subproj/CFBinaryPList.c b/Parsing.subproj/CFBinaryPList.c
deleted file mode 100644 (file)
index 9495ad1..0000000
+++ /dev/null
@@ -1,930 +0,0 @@
-/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*     CFBinaryPList.c
-       Copyright 2000-2002, Apple, Inc. All rights reserved.
-       Responsibility: Christopher Kane
-*/
-
-#include <CoreFoundation/CFBase.h>
-#include <CoreFoundation/CFString.h>
-#include <CoreFoundation/CFNumber.h>
-#include <CoreFoundation/CFDate.h>
-#include <CoreFoundation/CFData.h>
-#include <CoreFoundation/CFArray.h>
-#include <CoreFoundation/CFDictionary.h>
-#include <CoreFoundation/CFSet.h>
-#include <CoreFoundation/CFPropertyList.h>
-#include <CoreFoundation/CFByteOrder.h>
-#include <CoreFoundation/CFRuntime.h>
-#include <CoreFoundation/CFStream.h>
-#include <stdio.h>
-#include <limits.h>
-#include <string.h>
-#include "CFInternal.h"
-
-
-CF_INLINE CFTypeID __CFGenericTypeID_genericobj_inline(const void *cf) {
-    CFTypeID typeID = __CFBitfieldGetValue(((const CFRuntimeBase *)cf)->_info, 15, 8);
-    return CF_IS_OBJC(typeID, cf) ? CFGetTypeID(cf) : typeID;
-}
-
-struct __CFKeyedArchiverUID {
-    CFRuntimeBase _base;
-    uint32_t _value;
-};
-
-static CFStringRef __CFKeyedArchiverUIDCopyDescription(CFTypeRef cf) {
-    CFKeyedArchiverUIDRef uid = (CFKeyedArchiverUIDRef)cf;
-    return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("<CFKeyedArchiverUID %p [%p]>{value = %u}"), cf, CFGetAllocator(cf), uid->_value);
-}
-
-static CFStringRef __CFKeyedArchiverUIDCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
-    CFKeyedArchiverUIDRef uid = (CFKeyedArchiverUIDRef)cf;
-    return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("@%u@"), uid->_value);
-}
-
-static CFTypeID __kCFKeyedArchiverUIDTypeID = _kCFRuntimeNotATypeID;
-
-static const CFRuntimeClass __CFKeyedArchiverUIDClass = {
-    0,
-    "CFKeyedArchiverUID",
-    NULL,      // init
-    NULL,      // copy
-    NULL,      // finalize
-    NULL,      // equal -- pointer equality only
-    NULL,      // hash -- pointer hashing only
-    __CFKeyedArchiverUIDCopyFormattingDescription,
-    __CFKeyedArchiverUIDCopyDescription
-};
-
-__private_extern__ void __CFKeyedArchiverUIDInitialize(void) {
-    __kCFKeyedArchiverUIDTypeID = _CFRuntimeRegisterClass(&__CFKeyedArchiverUIDClass);
-}
-
-CFTypeID _CFKeyedArchiverUIDGetTypeID(void) {
-    return __kCFKeyedArchiverUIDTypeID;
-}
-
-CFKeyedArchiverUIDRef _CFKeyedArchiverUIDCreate(CFAllocatorRef allocator, uint32_t value) {
-    CFKeyedArchiverUIDRef uid;
-    uid = (CFKeyedArchiverUIDRef)_CFRuntimeCreateInstance(allocator, __kCFKeyedArchiverUIDTypeID, sizeof(struct __CFKeyedArchiverUID) - sizeof(CFRuntimeBase), NULL);
-    if (NULL == uid) {
-       return NULL;
-    }
-    ((struct __CFKeyedArchiverUID *)uid)->_value = value;
-    return uid;
-}
-
-
-uint32_t _CFKeyedArchiverUIDGetValue(CFKeyedArchiverUIDRef uid) {
-    return uid->_value;
-}
-
-
-typedef struct {
-    CFTypeRef stream;
-    bool streamIsData;
-    uint64_t written;
-    int32_t used;
-    uint8_t buffer[8192 - 16];
-} __CFBinaryPlistWriteBuffer;
-
-CF_INLINE void writeBytes(__CFBinaryPlistWriteBuffer *buf, const UInt8 *bytes, CFIndex length) {
-    if (buf->streamIsData) {
-        CFDataAppendBytes((CFMutableDataRef)buf->stream, bytes, length);
-    } else {
-        CFWriteStreamWrite((CFWriteStreamRef)buf->stream, bytes, length);
-    }
-}
-
-static void bufferWrite(__CFBinaryPlistWriteBuffer *buf, const uint8_t *buffer, CFIndex count) {
-    CFIndex copyLen;
-    if ((CFIndex)sizeof(buf->buffer) <= count) {
-       writeBytes(buf, buf->buffer, buf->used);
-       buf->written += buf->used;
-       buf->used = 0;
-       writeBytes(buf, buffer, count);
-       buf->written += count;
-       return;
-    }
-    copyLen = __CFMin(count, (CFIndex)sizeof(buf->buffer) - buf->used);
-    memmove(buf->buffer + buf->used, buffer, copyLen);
-    buf->used += copyLen;
-    if (sizeof(buf->buffer) == buf->used) {
-       writeBytes(buf, buf->buffer, sizeof(buf->buffer));
-       buf->written += sizeof(buf->buffer);
-       memmove(buf->buffer, buffer + copyLen, count - copyLen);
-       buf->used = count - copyLen;
-    }
-}
-
-static void bufferFlush(__CFBinaryPlistWriteBuffer *buf) {
-    writeBytes(buf, buf->buffer, buf->used);
-    buf->written += buf->used;
-    buf->used = 0;
-}
-
-/*
-HEADER
-       magic number ("bplist")
-       file format version
-
-OBJECT TABLE
-       variable-sized objects
-
-       Object Formats (marker byte followed by additional info in some cases)
-       null    0000 0000
-       bool    0000 1000                       // false
-       bool    0000 1001                       // true
-       fill    0000 1111                       // fill byte
-       int     0001 nnnn       ...             // # of bytes is 2^nnnn, big-endian bytes
-       real    0010 nnnn       ...             // # of bytes is 2^nnnn, big-endian bytes
-       date    0011 0011       ...             // 8 byte float follows, big-endian bytes
-       data    0100 nnnn       [int]   ...     // nnnn is number of bytes unless 1111 then int count follows, followed by bytes
-       string  0101 nnnn       [int]   ...     // ASCII string, nnnn is # of chars, else 1111 then int count, then bytes
-       string  0110 nnnn       [int]   ...     // Unicode string, nnnn is # of chars, else 1111 then int count, then big-endian 2-byte uint16_t
-               0111 xxxx                       // unused
-       uid     1000 nnnn       ...             // nnnn+1 is # of bytes
-               1001 xxxx                       // unused
-       array   1010 nnnn       [int]   objref* // nnnn is count, unless '1111', then int count follows
-               1011 xxxx                       // unused
-               1100 xxxx                       // unused
-       dict    1101 nnnn       [int]   keyref* objref* // nnnn is count, unless '1111', then int count follows
-               1110 xxxx                       // unused
-               1111 xxxx                       // unused
-
-OFFSET TABLE
-       list of ints, byte size of which is given in trailer
-       -- these are the byte offsets into the file
-       -- number of these is in the trailer
-
-TRAILER
-       byte size of offset ints in offset table
-       byte size of object refs in arrays and dicts
-       number of offsets in offset table (also is number of objects)
-       element # in offset table which is top level object
-
-*/
-
-
-static CFTypeID stringtype = -1, datatype = -1, numbertype = -1, datetype = -1;
-static CFTypeID booltype = -1, dicttype = -1, arraytype = -1;
-
-static void _appendInt(__CFBinaryPlistWriteBuffer *buf, uint64_t bigint) {
-    uint8_t marker;
-    uint8_t *bytes;
-    CFIndex nbytes;
-    if (bigint <= (uint64_t)0xff) {
-       nbytes = 1;
-       marker = kCFBinaryPlistMarkerInt | 0;
-    } else if (bigint <= (uint64_t)0xffff) {
-       nbytes = 2;
-       marker = kCFBinaryPlistMarkerInt | 1;
-    } else if (bigint <= (uint64_t)0xffffffff) {
-       nbytes = 4;
-       marker = kCFBinaryPlistMarkerInt | 2;
-    } else {
-       nbytes = 8;
-       marker = kCFBinaryPlistMarkerInt | 3;
-    }
-    bigint = CFSwapInt64HostToBig(bigint);
-    bytes = (uint8_t *)&bigint + sizeof(bigint) - nbytes;
-    bufferWrite(buf, &marker, 1);
-    bufferWrite(buf, bytes, nbytes);
-}
-
-static void _appendUID(__CFBinaryPlistWriteBuffer *buf, CFKeyedArchiverUIDRef uid) {
-    uint8_t marker;
-    uint8_t *bytes;
-    CFIndex nbytes;
-    uint64_t bigint = _CFKeyedArchiverUIDGetValue(uid);
-    if (bigint <= (uint64_t)0xff) {
-       nbytes = 1;
-    } else if (bigint <= (uint64_t)0xffff) {
-       nbytes = 2;
-    } else if (bigint <= (uint64_t)0xffffffff) {
-       nbytes = 4;
-    } else {
-       nbytes = 8;
-    }
-    marker = kCFBinaryPlistMarkerUID | (nbytes - 1);
-    bigint = CFSwapInt64HostToBig(bigint);
-    bytes = (uint8_t *)&bigint + sizeof(bigint) - nbytes;
-    bufferWrite(buf, &marker, 1);
-    bufferWrite(buf, bytes, nbytes);
-}
-
-static Boolean __plistUniquingEqual(CFTypeRef cf1, CFTypeRef cf2) {
-    // As long as this equals function is more restrictive than the
-    // existing one, for any given type, the hash function need not
-    // also be provided for the uniquing set.
-    if (__CFGenericTypeID_genericobj_inline(cf1) != __CFGenericTypeID_genericobj_inline(cf2)) return false;
-    if (__CFGenericTypeID_genericobj_inline(cf1) == numbertype) {
-       if (CFNumberIsFloatType(cf1) != CFNumberIsFloatType(cf2)) return false;
-       return CFEqual(cf1, cf2);
-    }
-    return CFEqual(cf1, cf2);
-}
-
-static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CFMutableDictionaryRef objtable, CFMutableSetRef uniquingsets[]) {
-    CFPropertyListRef unique;
-    uint32_t refnum;
-    CFTypeID type = __CFGenericTypeID_genericobj_inline(plist);
-    CFIndex idx;
-    CFPropertyListRef *list, buffer[256];
-
-    // Do not unique dictionaries or arrays, because: they
-    // are slow to compare, and have poor hash codes.
-    // Uniquing bools is unnecessary.
-    int which = -1;
-    if (stringtype == type) {
-       which = 0;
-    } else if (numbertype == type) {
-       which = 1;
-    } else if (datatype == type) {
-       which = 2;
-    } else if (datetype == type) {
-       which = 3;
-    }
-    if (1 && -1 != which) {
-       CFMutableSetRef uniquingset = uniquingsets[which];
-       CFIndex before = CFSetGetCount(uniquingset);
-       CFSetAddValue(uniquingset, plist);
-       CFIndex after = CFSetGetCount(uniquingset);
-       if (after == before) {  // already in set
-           unique = CFSetGetValue(uniquingset, plist);
-           if (unique != plist) {
-               refnum = (uint32_t)CFDictionaryGetValue(objtable, unique);
-               CFDictionaryAddValue(objtable, plist, (const void *)refnum);
-           }
-           return;
-       }
-    }
-    refnum = CFArrayGetCount(objlist);
-    CFArrayAppendValue(objlist, plist);
-    CFDictionaryAddValue(objtable, plist, (const void *)refnum);
-    if (dicttype == type) {
-       CFIndex count = CFDictionaryGetCount(plist);
-       list = (count <= 128) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), 0);
-        CFDictionaryGetKeysAndValues(plist, list, list + count);
-        for (idx = 0; idx < 2 * count; idx++) {
-            _flattenPlist(list[idx], objlist, objtable, uniquingsets);
-        }
-        if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
-    } else if (arraytype == type) {
-       CFIndex count = CFArrayGetCount(plist);
-       list = (count <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, count * sizeof(CFTypeRef), 0);
-        CFArrayGetValues(plist, CFRangeMake(0, count), list);
-        for (idx = 0; idx < count; idx++) {
-            _flattenPlist(list[idx], objlist, objtable, uniquingsets);
-        }
-        if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
-    }
-}
-
-// stream can be a CFWriteStreamRef or a CFMutableDataRef
-CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream) {
-    CFMutableDictionaryRef objtable;
-    CFMutableArrayRef objlist;
-    CFBinaryPlistTrailer trailer;
-    uint64_t *offsets, length_so_far;
-    uint64_t mask, refnum;
-    int64_t idx, idx2, cnt;
-    __CFBinaryPlistWriteBuffer *buf;
-    CFSetCallBacks cb = kCFTypeSetCallBacks;
-
-    if ((CFTypeID)-1 == stringtype) {
-       stringtype = CFStringGetTypeID();
-       datatype = CFDataGetTypeID();
-       numbertype = CFNumberGetTypeID();
-       booltype = CFBooleanGetTypeID();
-       datetype = CFDateGetTypeID();
-       dicttype = CFDictionaryGetTypeID();
-       arraytype = CFArrayGetTypeID();
-    }
-    objtable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, NULL);
-    _CFDictionarySetCapacity(objtable, 640);
-    objlist = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
-    _CFArraySetCapacity(objlist, 640);
-    cb.equal = __plistUniquingEqual;
-    CFMutableSetRef uniquingsets[4];
-    uniquingsets[0] = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
-    _CFSetSetCapacity(uniquingsets[0], 1000);
-    uniquingsets[1] = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
-    _CFSetSetCapacity(uniquingsets[1], 500);
-    uniquingsets[2] = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
-    _CFSetSetCapacity(uniquingsets[2], 250);
-    uniquingsets[3] = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
-    _CFSetSetCapacity(uniquingsets[3], 250);
-
-    _flattenPlist(plist, objlist, objtable, uniquingsets);
-    
-    CFRelease(uniquingsets[0]);
-    CFRelease(uniquingsets[1]);
-    CFRelease(uniquingsets[2]);
-    CFRelease(uniquingsets[3]);
-
-    cnt = CFArrayGetCount(objlist);
-    offsets = CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(*offsets), 0);
-
-    buf = CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__CFBinaryPlistWriteBuffer), 0);
-    buf->stream = stream;
-    buf->streamIsData = (CFGetTypeID(stream) == CFDataGetTypeID());
-    buf->written = 0;
-    buf->used = 0;
-    bufferWrite(buf, "bplist00", 8);   // header
-
-    memset(&trailer, 0, sizeof(trailer));
-    trailer._numObjects = CFSwapInt64HostToBig(cnt);
-    trailer._topObject = 0;    // true for this implementation
-    mask = ~(uint64_t)0;
-    while (cnt & mask) {
-       trailer._objectRefSize++;
-       mask = mask << 8;
-    }
-
-    for (idx = 0; idx < cnt; idx++) {
-       CFPropertyListRef obj = CFArrayGetValueAtIndex(objlist, idx);
-       CFTypeID type = CFGetTypeID(obj);
-       offsets[idx] = buf->written + buf->used;
-       if (stringtype == type) {
-           CFIndex ret, count = CFStringGetLength(obj);
-           CFIndex needed;
-           uint8_t *bytes, buffer[1024];
-           bytes = (count <= 1024) ? buffer : CFAllocatorAllocate(kCFAllocatorDefault, count, 0);
-           // presumption, believed to be true, is that ASCII encoding may need
-           // less bytes, but will not need greater, than the # of unichars
-           ret = CFStringGetBytes(obj, CFRangeMake(0, count), kCFStringEncodingASCII, 0, false, bytes, count, &needed);
-           if (ret == count) {
-               uint8_t marker = kCFBinaryPlistMarkerASCIIString | (needed < 15 ? needed : 0xf);
-               bufferWrite(buf, &marker, 1);
-               if (15 <= needed) {
-                   _appendInt(buf, (uint64_t)needed);
-               }
-               bufferWrite(buf, bytes, needed);
-           } else {
-               UniChar *chars;
-               uint8_t marker = kCFBinaryPlistMarkerUnicode16String | (count < 15 ? count : 0xf);
-               bufferWrite(buf, &marker, 1);
-               if (15 <= count) {
-                   _appendInt(buf, (uint64_t)count);
-               }
-               chars = CFAllocatorAllocate(kCFAllocatorDefault, count * sizeof(UniChar), 0);
-               CFStringGetCharacters(obj, CFRangeMake(0, count), chars);
-               for (idx2 = 0; idx2 < count; idx2++) {
-                   chars[idx2] = CFSwapInt16HostToBig(chars[idx2]);
-               }
-               bufferWrite(buf, (uint8_t *)chars, count * sizeof(UniChar));
-               CFAllocatorDeallocate(kCFAllocatorDefault, chars);
-           }
-           if (bytes != buffer) CFAllocatorDeallocate(kCFAllocatorDefault, bytes);
-       } else if (numbertype == type) {
-           uint8_t marker;
-           CFSwappedFloat64 swapped64;
-           CFSwappedFloat32 swapped32;
-           uint64_t bigint;
-           uint8_t *bytes;
-           CFIndex nbytes;
-           if (CFNumberIsFloatType(obj)) {
-               if (CFNumberGetByteSize(obj) <= (CFIndex)sizeof(float)) {
-                   float v;
-                   CFNumberGetValue(obj, kCFNumberFloat32Type, &v);
-                   swapped32 = CFConvertFloat32HostToSwapped(v);
-                   bytes = (uint8_t *)&swapped32;
-                   nbytes = sizeof(float);
-                   marker = kCFBinaryPlistMarkerReal | 2;
-               } else {
-                   double v;
-                   CFNumberGetValue(obj, kCFNumberFloat64Type, &v);
-                   swapped64 = CFConvertFloat64HostToSwapped(v);
-                   bytes = (uint8_t *)&swapped64;
-                   nbytes = sizeof(double);
-                   marker = kCFBinaryPlistMarkerReal | 3;
-               }
-               bufferWrite(buf, &marker, 1);
-               bufferWrite(buf, bytes, nbytes);
-           } else {
-               CFNumberGetValue(obj, kCFNumberSInt64Type, &bigint);
-               _appendInt(buf, bigint);
-           }
-       } else if (_CFKeyedArchiverUIDGetTypeID() == type) {
-           _appendUID(buf, (CFKeyedArchiverUIDRef)obj);
-       } else if (booltype == type) {
-           uint8_t marker = CFBooleanGetValue(obj) ? kCFBinaryPlistMarkerTrue : kCFBinaryPlistMarkerFalse;
-           bufferWrite(buf, &marker, 1);
-       } else if (datatype == type) {
-           CFIndex count = CFDataGetLength(obj);
-           uint8_t marker = kCFBinaryPlistMarkerData | (count < 15 ? count : 0xf);
-           bufferWrite(buf, &marker, 1);
-           if (15 <= count) {
-               _appendInt(buf, (uint64_t)count);
-           }
-           bufferWrite(buf, CFDataGetBytePtr(obj), count);
-       } else if (datetype == type) {
-           CFSwappedFloat64 swapped;
-           uint8_t marker = kCFBinaryPlistMarkerDate;
-           bufferWrite(buf, &marker, 1);
-           swapped = CFConvertFloat64HostToSwapped(CFDateGetAbsoluteTime(obj));
-           bufferWrite(buf, (uint8_t *)&swapped, sizeof(swapped));
-       } else if (dicttype == type) {
-           CFIndex count = CFDictionaryGetCount(obj);
-           CFPropertyListRef *list, buffer[512];
-           uint8_t marker = kCFBinaryPlistMarkerDict | (count < 15 ? count : 0xf);
-           bufferWrite(buf, &marker, 1);
-           if (15 <= count) {
-               _appendInt(buf, (uint64_t)count);
-           }
-           list = (count <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), 0);
-           CFDictionaryGetKeysAndValues(obj, list, list + count);
-           for (idx2 = 0; idx2 < 2 * count; idx2++) {
-               CFPropertyListRef value = list[idx2];
-               uint32_t swapped = 0;
-               uint8_t *source = (uint8_t *)&swapped;
-                refnum = (uint32_t)CFDictionaryGetValue(objtable, value);
-                swapped = CFSwapInt32HostToBig(refnum);
-               bufferWrite(buf, source + sizeof(swapped) - trailer._objectRefSize, trailer._objectRefSize);
-           }
-           if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
-       } else if (arraytype == type) {
-           CFIndex count = CFArrayGetCount(obj);
-           CFPropertyListRef *list, buffer[256];
-           uint8_t marker = kCFBinaryPlistMarkerArray | (count < 15 ? count : 0xf);
-           bufferWrite(buf, &marker, 1);
-           if (15 <= count) {
-               _appendInt(buf, (uint64_t)count);
-           }
-           list = (count <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, count * sizeof(CFTypeRef), 0);
-           CFArrayGetValues(obj, CFRangeMake(0, count), list);
-           for (idx2 = 0; idx2 < count; idx2++) {
-               CFPropertyListRef value = list[idx2];
-               uint32_t swapped = 0;
-               uint8_t *source = (uint8_t *)&swapped;
-                refnum = (uint32_t)CFDictionaryGetValue(objtable, value);
-                swapped = CFSwapInt32HostToBig(refnum);
-               bufferWrite(buf, source + sizeof(swapped) - trailer._objectRefSize, trailer._objectRefSize);
-           }
-           if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
-       } else {
-           CFRelease(objtable);
-           CFRelease(objlist);
-           CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf);
-            CFAllocatorDeallocate(kCFAllocatorSystemDefault, offsets);
-           return 0;
-       }
-    }
-    CFRelease(objtable);
-    CFRelease(objlist);
-
-    length_so_far = buf->written + buf->used;
-    trailer._offsetTableOffset = CFSwapInt64HostToBig(length_so_far);
-    trailer._offsetIntSize = 0;
-    mask = ~(uint64_t)0;
-    while (length_so_far & mask) {
-       trailer._offsetIntSize++;
-       mask = mask << 8;
-    }
-
-    for (idx = 0; idx < cnt; idx++) {
-       uint64_t swapped = CFSwapInt64HostToBig(offsets[idx]);
-       uint8_t *source = (uint8_t *)&swapped;
-       bufferWrite(buf, source + sizeof(*offsets) - trailer._offsetIntSize, trailer._offsetIntSize);
-    }
-    length_so_far += cnt * trailer._offsetIntSize;
-
-    bufferWrite(buf, (uint8_t *)&trailer, sizeof(trailer));
-    bufferFlush(buf);
-    length_so_far += sizeof(trailer);
-    CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf);
-    CFAllocatorDeallocate(kCFAllocatorSystemDefault, offsets);
-    return (CFIndex)length_so_far;
-}
-
-bool __CFBinaryPlistGetTopLevelInfo(const uint8_t *databytes, uint64_t datalen, uint8_t *marker, uint64_t *offset, CFBinaryPlistTrailer *trailer) {
-    const uint8_t *bytesptr;
-    CFBinaryPlistTrailer trail;
-    uint64_t off;
-    CFIndex idx;
-
-    if ((CFTypeID)-1 == stringtype) {
-       stringtype = CFStringGetTypeID();
-       datatype = CFDataGetTypeID();
-       numbertype = CFNumberGetTypeID();
-       booltype = CFBooleanGetTypeID();
-       datetype = CFDateGetTypeID();
-       dicttype = CFDictionaryGetTypeID();
-       arraytype = CFArrayGetTypeID();
-    }
-    if (!databytes || datalen < 8 || 0 != memcmp("bplist00", databytes, 8)) return false;
-    if (datalen < sizeof(trail) + 8 + 1) return false;
-    memmove(&trail, databytes + datalen - sizeof(trail), sizeof(trail));
-    trail._numObjects = CFSwapInt64BigToHost(trail._numObjects);
-    trail._topObject = CFSwapInt64BigToHost(trail._topObject);
-    if (trail._numObjects < trail._topObject) return false;
-    trail._offsetTableOffset = CFSwapInt64BigToHost(trail._offsetTableOffset);
-    if (datalen < trail._offsetTableOffset + trail._numObjects * trail._offsetIntSize + sizeof(trail)) return false;
-    bytesptr = databytes + trail._offsetTableOffset + trail._topObject * trail._offsetIntSize;
-    off = 0;
-    for (idx = 0; idx < trail._offsetIntSize; idx++) {
-       off = (off << 8) + bytesptr[idx];
-    }
-    if (trail._offsetTableOffset <= off) return false;
-    if (trailer) *trailer = trail;
-    if (offset) *offset = off;
-    if (marker) *marker = *(databytes + off);
-    return true;
-}
-
-static bool _readInt(const uint8_t *ptr, uint64_t *bigint, const uint8_t **newptr) {
-    uint8_t marker;
-    CFIndex idx, cnt;
-    marker = *ptr++;
-    if ((marker & 0xf0) != kCFBinaryPlistMarkerInt) return false;
-    cnt = 1 << (marker & 0xf);
-    *bigint = 0;
-    for (idx = 0; idx < cnt; idx++) {
-       *bigint = (*bigint << 8) + *ptr++;
-    }
-    if (newptr) *newptr = ptr;
-    return true;
-}
-
-static uint64_t _getOffsetOfRefAt(const uint8_t *databytes, const uint8_t *bytesptr, const CFBinaryPlistTrailer *trailer) {
-    uint64_t ref = 0, off = 0;
-    CFIndex idx;
-    for (idx = 0; idx < trailer->_objectRefSize; idx++) {
-       ref = (ref << 8) + bytesptr[idx];
-    }
-    bytesptr = databytes + trailer->_offsetTableOffset + ref * trailer->_offsetIntSize;
-    for (idx = 0; idx < trailer->_offsetIntSize; idx++) {
-       off = (off << 8) + bytesptr[idx];
-    }
-    return off;
-}
-
-bool __CFBinaryPlistGetOffsetForValueFromArray(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFIndex idx, uint64_t *offset) {
-    const uint8_t *bytesptr;
-    uint8_t marker;
-    CFIndex cnt;
-    uint64_t off;
-
-    marker = *(databytes + startOffset);
-    if ((marker & 0xf0) != kCFBinaryPlistMarkerArray) return false;
-    cnt = (marker & 0x0f);
-    if (cnt < 15 && cnt <= idx) return false;
-    bytesptr = databytes + startOffset + 1;
-    if (0xf == cnt) {
-       uint64_t bigint;
-       if (!_readInt(bytesptr, &bigint, &bytesptr)) return false;
-       if (INT_MAX < bigint) return false;
-       cnt = (CFIndex)bigint;
-    }
-    if (cnt <= idx) return false;
-    off = _getOffsetOfRefAt(databytes, bytesptr + idx * trailer->_objectRefSize, trailer);
-    if (datalen <= off) return false;
-    if (offset) *offset = off;
-    return true;
-}
-
-bool __CFBinaryPlistGetOffsetForValueFromDictionary(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFTypeRef key, uint64_t *koffset, uint64_t *voffset) {
-    const uint8_t *refsptr, *bytesptr;
-    uint64_t off;
-    uint8_t marker;
-    CFTypeID keytype = CFGetTypeID(key);
-    CFIndex idx, keyn, cnt, cnt2;
-
-    marker = *(databytes + startOffset);
-    if ((marker & 0xf0) != kCFBinaryPlistMarkerDict) return false;
-    cnt = (marker & 0x0f);
-    refsptr = databytes + startOffset + 1 + 0;
-    if (0xf == cnt) {
-       uint64_t bigint;
-       if (!_readInt(refsptr, &bigint, &refsptr)) return false;
-       if (INT_MAX < bigint) return false;
-       cnt = (CFIndex)bigint;
-    }
-    for (keyn = 0; keyn < cnt; keyn++) {
-       off = _getOffsetOfRefAt(databytes, refsptr, trailer);
-       if (datalen <= off) return false;
-       refsptr += trailer->_objectRefSize;
-       bytesptr = databytes + off;
-       marker = *bytesptr & 0xf0;
-       cnt2 = *bytesptr & 0x0f;
-       if (kCFBinaryPlistMarkerASCIIString == marker || kCFBinaryPlistMarkerUnicode16String == marker) {
-           CFStringInlineBuffer strbuf;
-           UniChar uchar;
-           if (keytype != stringtype) goto miss;
-            if (0xf == cnt2 && CFStringGetLength(key) < 15) goto miss;
-           bytesptr++;
-           if (0xf == cnt2) {
-               uint64_t bigint;
-               if (!_readInt(bytesptr, &bigint, &bytesptr)) return false;
-               if (INT_MAX < bigint) return false;
-               cnt2 = (CFIndex)bigint;
-           }
-           if (cnt2 != CFStringGetLength(key)) goto miss;
-           uchar = (kCFBinaryPlistMarkerASCIIString == marker) ? (UniChar)bytesptr[0] : (UniChar)(bytesptr[0] * 256 + bytesptr[1]);
-           if (uchar != CFStringGetCharacterAtIndex(key, 0)) goto miss;
-           bytesptr += (kCFBinaryPlistMarkerASCIIString == marker) ? 1 : 2;
-           CFStringInitInlineBuffer(key, &strbuf, CFRangeMake(0, cnt2));
-           for (idx = 1; idx < cnt2; idx++) {
-               uchar = (kCFBinaryPlistMarkerASCIIString == marker) ? (UniChar)bytesptr[0] : (UniChar)(bytesptr[0] * 256 + bytesptr[1]);
-               if (uchar != __CFStringGetCharacterFromInlineBufferQuick(&strbuf, idx)) goto miss;
-               bytesptr += (kCFBinaryPlistMarkerASCIIString == marker) ? 1 : 2;
-           }
-           if (koffset) *koffset = off;
-           off = _getOffsetOfRefAt(databytes, refsptr + (cnt - 1) * trailer->_objectRefSize, trailer);
-           if (datalen <= off) return false;
-           if (voffset) *voffset = off;
-           return true;
-       } else {
-//#warning the other primitive types should be allowed as keys in a binary plist dictionary, I think
-           return false;
-       }
-       miss: ;
-    }
-    return false;
-}
-
-extern CFArrayRef _CFArrayCreate_ex(CFAllocatorRef allocator, bool mutable, const void **values, CFIndex numValues);
-
-extern CFDictionaryRef _CFDictionaryCreate_ex(CFAllocatorRef allocator, bool mutable, const void **keys, const void **values, CFIndex numValues);
-
-#if 0
-static bool _getUIDFromData(const uint8_t *datap, uint64_t *vp) {
-    int32_t idx, cnt;
-    uint8_t marker = *datap;
-    uint64_t bigint;
-    if ((marker & 0xf0) != kCFBinaryPlistMarkerUID) return false;
-    cnt = (marker & 0x0f) + 1;
-    datap++;
-    bigint = 0;
-    for (idx = 0; idx < cnt; idx++) {
-       bigint = (bigint << 8) + *datap++;
-    }
-    *vp = bigint;
-    return true;
-}
-#endif
-
-static bool _getFloatFromData(const uint8_t *datap, float *vp) {
-    CFSwappedFloat32 swapped32;
-    if (*datap != (kCFBinaryPlistMarkerReal | 2)) return false;
-    datap++;
-    memmove(&swapped32, datap, sizeof(swapped32));
-    *vp = CFConvertFloat32SwappedToHost(swapped32);
-    return true;
-}
-
-static bool _getDoubleFromData(const uint8_t *datap, double *vp) {
-    CFSwappedFloat64 swapped64;
-    if (*datap != (kCFBinaryPlistMarkerReal | 3)) return false;
-    datap++;
-    memmove(&swapped64, datap, sizeof(swapped64));
-    *vp = CFConvertFloat64SwappedToHost(swapped64);
-    return true;
-}
-
-bool __CFBinaryPlistCreateObject(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFPropertyListRef *plist) {
-    const uint8_t *bytesptr;
-    uint64_t off;
-    uint8_t marker;
-    CFIndex idx, cnt;
-    uint64_t bigint;
-    UniChar *chars;
-    CFPropertyListRef *list, buffer[256];
-    CFAllocatorRef listAllocator;
-
-    if (objects) {
-       *plist = CFDictionaryGetValue(objects, (const void *)(intptr_t)startOffset);
-       if (*plist) {
-           CFRetain(*plist);
-           return true;
-       }
-    }
-
-    marker = *(databytes + startOffset);
-    switch (marker & 0xf0) {
-    case kCFBinaryPlistMarkerNull:
-       switch (marker) {
-       case kCFBinaryPlistMarkerNull:
-           *plist = NULL;
-           return true;
-       case kCFBinaryPlistMarkerFalse:
-           *plist = CFRetain(kCFBooleanFalse);
-           return true;
-       case kCFBinaryPlistMarkerTrue:
-           *plist = CFRetain(kCFBooleanTrue);
-           return true;
-       }
-       return false;
-    case kCFBinaryPlistMarkerInt:
-       if (!_readInt(databytes + startOffset, &bigint, NULL)) return false;
-       *plist = CFNumberCreate(allocator, kCFNumberSInt64Type, &bigint);
-       if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-       return (*plist) ? true : false;
-    case kCFBinaryPlistMarkerReal:
-       cnt = marker & 0x0f;
-       if (2 == cnt) {
-           float f;
-           _getFloatFromData(databytes + startOffset, &f);
-           *plist = CFNumberCreate(allocator, kCFNumberFloat32Type, &f);
-           if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-           return (*plist) ? true : false;
-       } else if (3 == cnt) {
-           double d;
-           _getDoubleFromData(databytes + startOffset, &d);
-           *plist = CFNumberCreate(allocator, kCFNumberFloat64Type, &d);
-           if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-           return (*plist) ? true : false;
-       }
-       return false;
-    case kCFBinaryPlistMarkerDate & 0xf0: {
-       CFSwappedFloat64 swapped64;
-       double d;
-       cnt = marker & 0x0f;
-       if (3 != cnt) return false;
-       memmove(&swapped64, databytes + startOffset + 1, sizeof(swapped64));
-       d = CFConvertFloat64SwappedToHost(swapped64);
-       *plist = CFDateCreate(allocator, d);
-       if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-       return (*plist) ? true : false;
-       }
-    case kCFBinaryPlistMarkerData: 
-       cnt = marker & 0x0f;
-       bytesptr = databytes + startOffset + 1;
-       if (0xf == cnt) {
-           if (!_readInt(bytesptr, &bigint, &bytesptr)) return false;
-           if (INT_MAX < bigint) return false;
-           cnt = (CFIndex)bigint;
-       }
-       if (mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
-           *plist = CFDataCreateMutable(allocator, 0);
-           CFDataAppendBytes((CFMutableDataRef)*plist, bytesptr, cnt);
-       } else {
-           *plist = CFDataCreate(allocator, bytesptr, cnt);
-       }
-       if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-       return (*plist) ? true : false;
-    case kCFBinaryPlistMarkerASCIIString:
-       cnt = marker & 0x0f;
-       bytesptr = databytes + startOffset + 1;
-       if (0xf == cnt) {
-           if (!_readInt(bytesptr, &bigint, &bytesptr)) return false;
-           if (INT_MAX < bigint) return false;
-           cnt = (CFIndex)bigint;
-       }
-       if (mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
-           CFStringRef str = CFStringCreateWithBytes(allocator, bytesptr, cnt, kCFStringEncodingASCII, false);
-           *plist = CFStringCreateMutableCopy(allocator, 0, str);
-           CFRelease(str);
-       } else {
-           *plist = CFStringCreateWithBytes(allocator, bytesptr, cnt, kCFStringEncodingASCII, false);
-       }
-       if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-       return (*plist) ? true : false;
-    case kCFBinaryPlistMarkerUnicode16String:
-       cnt = marker & 0x0f;
-       bytesptr = databytes + startOffset + 1;
-       if (0xf == cnt) {
-           if (!_readInt(bytesptr, &bigint, &bytesptr)) return false;
-           if (INT_MAX < bigint) return false;
-           cnt = (CFIndex)bigint;
-       }
-       chars = CFAllocatorAllocate(allocator, cnt * sizeof(UniChar), 0);
-       memmove(chars, bytesptr, cnt * sizeof(UniChar));
-       for (idx = 0; idx < cnt; idx++) {
-           chars[idx] = CFSwapInt16BigToHost(chars[idx]);
-       }
-       if (mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
-           CFStringRef str = CFStringCreateWithCharactersNoCopy(allocator, chars, cnt, allocator);
-           *plist = CFStringCreateMutableCopy(allocator, 0, str);
-           CFRelease(str);
-       } else {
-           *plist = CFStringCreateWithCharactersNoCopy(allocator, chars, cnt, allocator);
-       }
-       if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-       return (*plist) ? true : false;
-    case kCFBinaryPlistMarkerUID:
-       cnt = (marker & 0x0f) + 1;
-       bytesptr = databytes + startOffset + 1;
-       bigint = 0;
-       for (idx = 0; idx < cnt; idx++) {
-           bigint = (bigint << 8) + *bytesptr++;
-       }
-       if (UINT_MAX < bigint) return false;
-       *plist = _CFKeyedArchiverUIDCreate(allocator, (uint32_t)bigint);
-       if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-       return (*plist) ? true : false;
-    case kCFBinaryPlistMarkerArray:
-       cnt = marker & 0x0f;
-       bytesptr = databytes + startOffset + 1;
-       if (0xf == cnt) {
-           if (!_readInt(bytesptr, &bigint, &bytesptr)) return false;
-           if (INT_MAX < bigint) return false;
-           cnt = (CFIndex)bigint;
-       }
-       list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(CFPropertyListRef) * cnt, 0);
-       listAllocator = (list == buffer ? kCFAllocatorNull : kCFAllocatorSystemDefault);
-       for (idx = 0; idx < cnt; idx++) {
-           CFPropertyListRef pl;
-           off = _getOffsetOfRefAt(databytes, bytesptr, trailer);
-           if (datalen <= off) return false;
-           if (!__CFBinaryPlistCreateObject(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, &pl)) {
-               if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-                   while (idx--) {
-                       CFRelease(list[idx]);
-                   }
-               }
-               if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
-               return false;
-           }
-           if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-               CF_WRITE_BARRIER_BASE_ASSIGN(listAllocator, list, list[idx], CFMakeCollectable(pl));
-           } else {
-               list[idx] = pl;
-           }
-           bytesptr += trailer->_objectRefSize;
-       }
-       *plist = _CFArrayCreate_ex(allocator, (mutabilityOption != kCFPropertyListImmutable), list, cnt);
-       if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-       if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
-       return (*plist) ? true : false;
-    case kCFBinaryPlistMarkerDict:
-       cnt = marker & 0x0f;
-       bytesptr = databytes + startOffset + 1;
-       if (0xf == cnt) {
-           if (!_readInt(bytesptr, &bigint, &bytesptr)) return false;
-           if (INT_MAX < bigint) return false;
-           cnt = (CFIndex)bigint;
-       }
-       cnt *= 2;
-       list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(CFPropertyListRef) * cnt, 0);
-       listAllocator = (list == buffer ? kCFAllocatorNull : kCFAllocatorSystemDefault);
-       for (idx = 0; idx < cnt; idx++) {
-           CFPropertyListRef pl;
-           off = _getOffsetOfRefAt(databytes, bytesptr, trailer);
-           if (datalen <= off) return false;
-           if (!__CFBinaryPlistCreateObject(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, &pl)) {
-               if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-                   while (idx--) {
-                       CFRelease(list[idx]);
-                   }
-               }
-               if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
-               return false;
-           }
-           if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-               CF_WRITE_BARRIER_BASE_ASSIGN(listAllocator, list, list[idx], CFMakeCollectable(pl));
-           } else {
-               list[idx] = pl;
-           }
-           bytesptr += trailer->_objectRefSize;
-       }
-       *plist = _CFDictionaryCreate_ex(allocator, (mutabilityOption != kCFPropertyListImmutable), list, list + cnt / 2, cnt / 2);
-       if (objects) CFDictionarySetValue(objects, (const void *)(intptr_t)startOffset, *plist);
-       if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
-       return (*plist) ? true : false;
-    }
-    return false;
-}
-
-__private_extern__ bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFPropertyListRef *plist, CFStringRef *errorString) {
-    uint8_t marker;    
-    CFBinaryPlistTrailer trailer;
-    uint64_t offset;
-    CFPropertyListRef pl;
-    const uint8_t *databytes = CFDataGetBytePtr(data);
-    uint64_t datalen = CFDataGetLength(data);
-
-    if (8 <= datalen && __CFBinaryPlistGetTopLevelInfo(databytes, datalen, &marker, &offset, &trailer)) {
-        if (__CFBinaryPlistCreateObject(databytes, datalen, offset, &trailer, allocator, option, NULL, &pl)) {
-           if (plist) *plist = pl;
-        } else {
-           if (plist) *plist = NULL;
-            if (errorString) *errorString = CFRetain(CFSTR("binary data is corrupt"));
-       }
-        return true;
-    }
-    return false;
-}
-