]> git.saurik.com Git - apple/cf.git/commitdiff
CF-550.tar.gz mac-os-x-106 mac-os-x-1061 v550
authorApple <opensource@apple.com>
Tue, 24 Nov 2009 17:42:47 +0000 (17:42 +0000)
committerApple <opensource@apple.com>
Tue, 24 Nov 2009 17:42:47 +0000 (17:42 +0000)
147 files changed:
APPLE_LICENSE [changed mode: 0755->0644]
BuildCFLite
CFApplicationPreferences.c
CFArray.c
CFArray.h
CFBag.c
CFBag.h
CFBase.c
CFBase.h
CFBasicHash.h [new file with mode: 0644]
CFBasicHash.m [new file with mode: 0644]
CFBinaryHeap.c
CFBinaryHeap.h
CFBinaryPList.c
CFBitVector.c
CFBitVector.h
CFBuiltinConverters.c
CFBundle.c
CFBundle.h
CFBundlePriv.h
CFBundle_BinaryTypes.h
CFBundle_Internal.h
CFBundle_Resources.c
CFByteOrder.h
CFCalendar.c
CFCalendar.h
CFCharacterSet.c
CFCharacterSet.h
CFCharacterSetBitmaps.bitmap
CFCharacterSetPriv.h
CFConcreteStreams.c
CFData.c
CFData.h
CFDate.c
CFDate.h
CFDateFormatter.c
CFDateFormatter.h
CFDictionary.c
CFDictionary.h
CFError.c
CFError.h
CFError_Private.h
CFFileUtilities.c
CFICUConverters.c [new file with mode: 0644]
CFICUConverters.h [new file with mode: 0644]
CFInternal.h
CFLocale.c
CFLocale.h
CFLocaleIdentifier.c
CFLocaleInternal.h [new file with mode: 0644]
CFLocaleKeys.m [new file with mode: 0644]
CFLogUtilities.h
CFMachPort.c
CFMachPort.h
CFMessagePort.c
CFMessagePort.h
CFNumber.c
CFNumber.h
CFNumberFormatter.c
CFNumberFormatter.h
CFPlatform.c
CFPlatformConverters.c [new file with mode: 0644]
CFPlugIn.c
CFPlugIn.h
CFPlugInCOM.h
CFPlugIn_Factory.c
CFPlugIn_Factory.h
CFPlugIn_Instance.c
CFPlugIn_PlugIn.c
CFPreferences.c
CFPreferences.h
CFPriv.h
CFPropertyList.c
CFPropertyList.h
CFRunLoop.c
CFRunLoop.h
CFRunLoopPriv.h [deleted file]
CFRuntime.c
CFRuntime.h
CFSet.c
CFSet.h
CFSocket.c
CFSocket.h
CFSocketStream.c
CFSortFunctions.c
CFStorage.c
CFStorage.h
CFStream.c
CFStream.h
CFStreamAbstract.h
CFStreamInternal.h
CFStreamPriv.h
CFString.c
CFString.h
CFStringDefaultEncoding.h
CFStringEncodingConverter.c
CFStringEncodingConverter.h
CFStringEncodingConverterExt.h
CFStringEncodingConverterPriv.h
CFStringEncodingDatabase.c [new file with mode: 0644]
CFStringEncodingDatabase.h [new file with mode: 0644]
CFStringEncodingExt.h
CFStringEncodings.c
CFStringScanner.c
CFStringUtilities.c
CFSystemDirectories.c
CFTimeZone.c
CFTimeZone.h
CFTree.c
CFTree.h
CFURL.c
CFURL.h
CFURLAccess.c
CFURLAccess.h
CFUUID.c
CFUUID.h
CFUniChar.c
CFUniChar.h
CFUniCharPriv.h
CFUniCharPropertyDatabase.data
CFUnicodeData-B.mapping
CFUnicodeData-L.mapping
CFUnicodeDecomposition.c
CFUnicodeDecomposition.h
CFUnicodePrecomposition.c
CFUnicodePrecomposition.h
CFUserNotification.c
CFUserNotification.h
CFUtilities.c
CFVersion.c
CFWindowsMessageQueue.c
CFWindowsMessageQueue.h
CFXMLInputStream.c
CFXMLInputStream.h
CFXMLNode.c
CFXMLNode.h
CFXMLParser.c
CFXMLParser.h
CFXMLPreferencesDomain.c
CFXMLTree.c
CoreFoundation.h
CoreFoundation_Prefix.h [new file with mode: 0644]
ForFoundationOnly.h
Info.plist
README [deleted file]
SymbolAliases [new file with mode: 0644]
auto_stubs.h [deleted file]

old mode 100755 (executable)
new mode 100644 (file)
index fe81a60..71fe6fd
 APPLE PUBLIC SOURCE LICENSE
-Version 2.0 - August 6, 2003
-
-Please read this License carefully before downloading this software.
-By downloading or using this software, you are agreeing to be bound by
-the terms of this License. If you do not or cannot agree to the terms
-of this License, please do not download or use the software.
-
-1. General; Definitions. This License applies to any program or other
-work which Apple Computer, Inc. ("Apple") makes publicly available and
-which contains a notice placed by Apple identifying such program or
-work as "Original Code" and stating that it is subject to the terms of
-this Apple Public Source License version 2.0 ("License"). As used in
-this License:
-
-1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
-the grantor of rights, (i) claims of patents that are now or hereafter
-acquired, owned by or assigned to Apple and (ii) that cover subject
-matter contained in the Original Code, but only to the extent
-necessary to use, reproduce and/or distribute the Original Code
-without infringement; and (b) in the case where You are the grantor of
-rights, (i) claims of patents that are now or hereafter acquired,
-owned by or assigned to You and (ii) that cover subject matter in Your
-Modifications, taken alone or in combination with Original Code.
-
-1.2 "Contributor" means any person or entity that creates or
-contributes to the creation of Modifications.
-
-1.3 "Covered Code" means the Original Code, Modifications, the
-combination of Original Code and any Modifications, and/or any
-respective portions thereof.
-
-1.4 "Externally Deploy" means: (a) to sublicense, distribute or
-otherwise make Covered Code available, directly or indirectly, to
-anyone other than You; and/or (b) to use Covered Code, alone or as
-part of a Larger Work, in any way to provide a service, including but
-not limited to delivery of content, through electronic communication
-with a client other than You.
-
-1.5 "Larger Work" means a work which combines Covered Code or portions
+Version 2.0 -  August 6, 2003
+
+Please read this License carefully before downloading this software.  By
+downloading or using this software, you are agreeing to be bound by the terms
+of this License.  If you do not or cannot agree to the terms of this License,
+please do not download or use the software.
+
+Apple Note:  In January 2007, Apple changed its corporate name from "Apple
+Computer, Inc." to "Apple Inc."  This change has been reflected below and
+copyright years updated, but no other changes have been made to the APSL 2.0.
+
+1.     General; Definitions.  This License applies to any program or other
+work which Apple Inc. ("Apple") makes publicly available and which contains a
+notice placed by Apple identifying such program or work as "Original Code" and
+stating that it is subject to the terms of this Apple Public Source License
+version 2.0 ("License").  As used in this License:
+
+1.1     "Applicable Patent Rights" mean:  (a) in the case where Apple is the
+grantor of rights, (i) claims of patents that are now or hereafter acquired,
+owned by or assigned to Apple and (ii) that cover subject matter contained in
+the Original Code, but only to the extent necessary to use, reproduce and/or
+distribute the Original Code without infringement; and (b) in the case where
+You are the grantor of rights, (i) claims of patents that are now or hereafter
+acquired, owned by or assigned to You and (ii) that cover subject matter in
+Your Modifications, taken alone or in combination with Original Code.
+
+1.2    "Contributor" means any person or entity that creates or contributes to
+the creation of Modifications.
+
+1.3     "Covered Code" means the Original Code, Modifications, the combination
+of Original Code and any Modifications, and/or any respective portions thereof.
+
+1.4    "Externally Deploy" means: (a) to sublicense, distribute or otherwise
+make Covered Code available, directly or indirectly, to anyone other than You;
+and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way
+to provide a service, including but not limited to delivery of content, through
+electronic communication with a client other than You.
+
+1.5    "Larger Work" means a work which combines Covered Code or portions
 thereof with code not governed by the terms of this License.
 
-1.6 "Modifications" mean any addition to, deletion from, and/or change
-to, the substance and/or structure of the Original Code, any previous
-Modifications, the combination of Original Code and any previous
-Modifications, and/or any respective portions thereof. When code is
-released as a series of files, a Modification is: (a) any addition to
-or deletion from the contents of a file containing Covered Code;
-and/or (b) any new file or other representation of computer program
-statements that contains any part of Covered Code.
-
-1.7 "Original Code" means (a) the Source Code of a program or other
-work as originally made available by Apple under this License,
-including the Source Code of any updates or upgrades to such programs
-or works made available by Apple under this License, and that has been
-expressly identified by Apple as such in the header file(s) of such
-work; and (b) the object code compiled from such Source Code and
-originally made available by Apple under this License.
-
-1.8 "Source Code" means the human readable form of a program or other
-work that is suitable for making modifications to it, including all
-modules it contains, plus any associated interface definition files,
-scripts used to control compilation and installation of an executable
-(object code).
-
-1.9 "You" or "Your" means an individual or a legal entity exercising
-rights under this License. For legal entities, "You" or "Your"
-includes any entity which controls, is controlled by, or is under
-common control with, You, where "control" means (a) the power, direct
-or indirect, to cause the direction or management of such entity,
-whether by contract or otherwise, or (b) ownership of fifty percent
-(50%) or more of the outstanding shares or beneficial ownership of
-such entity.
-
-2. Permitted Uses; Conditions & Restrictions. Subject to the terms
-and conditions of this License, Apple hereby grants You, effective on
-the date You accept this License and download the Original Code, a
-world-wide, royalty-free, non-exclusive license, to the extent of
-Apple's Applicable Patent Rights and copyrights covering the Original
-Code, to do the following:
-
-2.1 Unmodified Code. You may use, reproduce, display, perform,
-internally distribute within Your organization, and Externally Deploy
-verbatim, unmodified copies of the Original Code, for commercial or
-non-commercial purposes, provided that in each instance:
-
-(a) You must retain and reproduce in all copies of Original Code the
-copyright and other proprietary notices and disclaimers of Apple as
-they appear in the Original Code, and keep intact all notices in the
-Original Code that refer to this License; and
-
-(b) You must include a copy of this License with every copy of Source
-Code of Covered Code and documentation You distribute or Externally
-Deploy, and You may not offer or impose any terms on such Source Code
-that alter or restrict this License or the recipients' rights
-hereunder, except as permitted under Section 6.
-
-2.2 Modified Code. You may modify Covered Code and use, reproduce,
+1.6    "Modifications" mean any addition to, deletion from, and/or change to,
+the substance and/or structure of the Original Code, any previous
+Modifications, the combination of Original Code and any previous Modifications,
+and/or any respective portions thereof.  When code is released as a series of
+files, a Modification is:  (a) any addition to or deletion from the contents of
+a file containing Covered Code; and/or (b) any new file or other representation
+of computer program statements that contains any part of Covered Code. 
+
+1.7    "Original Code" means (a) the Source Code of a program or other work as
+originally made available by Apple under this License, including the Source
+Code of any updates or upgrades to such programs or works made available by
+Apple under this License, and that has been expressly identified by Apple as
+such in the header file(s) of such work; and (b) the object code compiled from
+such Source Code and originally made available by Apple under this License
+
+1.8    "Source Code" means the human readable form of a program or other work
+that is suitable for making modifications to it, including all modules it
+contains, plus any associated interface definition files, scripts used to
+control compilation and installation of an executable (object code).
+
+1.9    "You" or "Your" means an individual or a legal entity exercising rights
+under this License.  For legal entities, "You" or "Your" includes any entity
+which controls, is controlled by, or is under common control with, You, where
+"control" means (a) the power, direct or indirect, to cause the direction or
+management of such entity, whether by contract or otherwise, or (b) ownership
+of fifty percent (50%) or more of the outstanding shares or beneficial
+ownership of such entity.
+
+2.     Permitted Uses; Conditions & Restrictions.   Subject to the terms and
+conditions of this License, Apple hereby grants You, effective on the date You
+accept this License and download the Original Code, a world-wide, royalty-free,
+non-exclusive license, to the extent of Apple's Applicable Patent Rights and
+copyrights covering the Original Code, to do the following:
+
+2.1    Unmodified Code.  You may use, reproduce, display, perform, internally
+distribute within Your organization, and Externally Deploy verbatim, unmodified
+copies of the Original Code, for commercial or non-commercial purposes,
+provided that in each instance:
+
+(a)    You must retain and reproduce in all copies of Original Code the
+copyright and other proprietary notices and disclaimers of Apple as they appear
+in the Original Code, and keep intact all notices in the Original Code that
+refer to this License; and
+
+(b)    You must include a copy of this License with every copy of Source Code
+of Covered Code and documentation You distribute or Externally Deploy, and You
+may not offer or impose any terms on such Source Code that alter or restrict
+this License or the recipients' rights hereunder, except as permitted under
+Section 6.
+
+2.2    Modified Code.  You may modify Covered Code and use, reproduce,
 display, perform, internally distribute within Your organization, and
-Externally Deploy Your Modifications and Covered Code, for commercial
-or non-commercial purposes, provided that in each instance You also
-meet all of these conditions:
-
-(a) You must satisfy all the conditions of Section 2.1 with respect to
-the Source Code of the Covered Code;
-
-(b) You must duplicate, to the extent it does not already exist, the
-notice in Exhibit A in each file of the Source Code of all Your
-Modifications, and cause the modified files to carry prominent notices
-stating that You changed the files and the date of any change; and
-
-(c) If You Externally Deploy Your Modifications, You must make
-Source Code of all Your Externally Deployed Modifications either
-available to those to whom You have Externally Deployed Your
-Modifications, or publicly available. Source Code of Your Externally
-Deployed Modifications must be released under the terms set forth in
-this License, including the license grants set forth in Section 3
-below, for as long as you Externally Deploy the Covered Code or twelve
-(12) months from the date of initial External Deployment, whichever is
-longer. You should preferably distribute the Source Code of Your
-Externally Deployed Modifications electronically (e.g. download from a
-web site).
-
-2.3 Distribution of Executable Versions. In addition, if You
-Externally Deploy Covered Code (Original Code and/or Modifications) in
-object code, executable form only, You must include a prominent
-notice, in the code itself as well as in related documentation,
-stating that Source Code of the Covered Code is available under the
-terms of this License with information on how and where to obtain such
-Source Code.
-
-2.4 Third Party Rights. You expressly acknowledge and agree that
-although Apple and each Contributor grants the licenses to their
-respective portions of the Covered Code set forth herein, no
-assurances are provided by Apple or any Contributor that the Covered
-Code does not infringe the patent or other intellectual property
-rights of any other entity. Apple and each Contributor disclaim any
-liability to You for claims brought by any other entity based on
-infringement of intellectual property rights or otherwise. As a
-condition to exercising the rights and licenses granted hereunder, You
-hereby assume sole responsibility to secure any other intellectual
-property rights needed, if any. For example, if a third party patent
-license is required to allow You to distribute the Covered Code, it is
-Your responsibility to acquire that license before distributing the
-Covered Code.
-
-3. Your Grants. In consideration of, and as a condition to, the
-licenses granted to You under this License, You hereby grant to any
-person or entity receiving or distributing Covered Code under this
-License a non-exclusive, royalty-free, perpetual, irrevocable license,
-under Your Applicable Patent Rights and other intellectual property
-rights (other than patent) owned or controlled by You, to use,
-reproduce, display, perform, modify, sublicense, distribute and
-Externally Deploy Your Modifications of the same scope and extent as
-Apple's licenses under Sections 2.1 and 2.2 above.
-
-4. Larger Works. You may create a Larger Work by combining Covered
-Code with other code not governed by the terms of this License and
-distribute the Larger Work as a single product. In each such instance,
-You must make sure the requirements of this License are fulfilled for
-the Covered Code or any portion thereof.
-
-5. Limitations on Patent License. Except as expressly stated in
-Section 2, no other patent rights, express or implied, are granted by
-Apple herein. Modifications and/or Larger Works may require additional
-patent licenses from Apple which Apple may grant in its sole
-discretion.
-
-6. Additional Terms. You may choose to offer, and to charge a fee for,
-warranty, support, indemnity or liability obligations and/or other
-rights consistent with the scope of the license granted herein
-("Additional Terms") to one or more recipients of Covered Code.
-However, You may do so only on Your own behalf and as Your sole
-responsibility, and not on behalf of Apple or any Contributor. You
-must obtain the recipient's agreement that any such Additional Terms
-are offered by You alone, and You hereby agree to indemnify, defend
-and hold Apple and every Contributor harmless for any liability
-incurred by or claims asserted against Apple or such Contributor by
-reason of any such Additional Terms.
-
-7. Versions of the License. Apple may publish revised and/or new
-versions of this License from time to time. Each version will be given
-a distinguishing version number. Once Original Code has been published
-under a particular version of this License, You may continue to use it
-under the terms of that version. You may also choose to use such
-Original Code under the terms of any subsequent version of this
-License published by Apple. No one other than Apple has the right to
-modify the terms applicable to Covered Code created under this
-License.
-
-8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
-part pre-release, untested, or not fully tested works. The Covered
-Code may contain errors that could cause failures or loss of data, and
-may be incomplete or contain inaccuracies. You expressly acknowledge
-and agree that use of the Covered Code, or any portion thereof, is at
-Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
-WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
-APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
-PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
-ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
-NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
-MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
-PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
-PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
-INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
-FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
-THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
-ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
-ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
-AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
-You acknowledge that the Covered Code is not intended for use in the
-operation of nuclear facilities, aircraft navigation, communication
-systems, or air traffic control machines in which case the failure of
-the Covered Code could lead to death, personal injury, or severe
-physical or environmental damage.
-
-9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
-EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
-TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
-ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
-TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
-APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
-REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
-INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
-TO YOU. In no event shall Apple's total liability to You for all
-damages (other than as may be required by applicable law) under this
-License exceed the amount of fifty dollars ($50.00).
-
-10. Trademarks. This License does not grant any rights to use the
-trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
-"QuickTime", "QuickTime Streaming Server" or any other trademarks,
-service marks, logos or trade names belonging to Apple (collectively
-"Apple Marks") or to any trademark, service mark, logo or trade name
-belonging to any Contributor. You agree not to use any Apple Marks in
-or as part of the name of products derived from the Original Code or
-to endorse or promote products derived from the Original Code other
-than as expressly permitted by and in strict compliance at all times
-with Apple's third party trademark usage guidelines which are posted
-at http://www.apple.com/legal/guidelinesfor3rdparties.html.
-
-11. Ownership. Subject to the licenses granted under this License,
-each Contributor retains all rights, title and interest in and to any
-Modifications made by such Contributor. Apple retains all rights,
-title and interest in and to the Original Code and any Modifications
-made by or on behalf of Apple ("Apple Modifications"), and such Apple
-Modifications will not be automatically subject to this License. Apple
-may, at its sole discretion, choose to license such Apple
-Modifications under this License, or on different terms from those
-contained in this License or may choose not to license them at all.
-
-12. Termination.
-
-12.1 Termination. This License and the rights granted hereunder will
+Externally Deploy Your Modifications and Covered Code, for commercial or
+non-commercial purposes, provided that in each instance You also meet all of
+these conditions:
+
+(a)    You must satisfy all the conditions of Section 2.1 with respect to the
+Source Code of the Covered Code; 
+
+(b)    You must duplicate, to the extent it does not already exist, the notice
+in Exhibit A in each file of the Source Code of all Your Modifications, and
+cause the modified files to carry prominent notices stating that You changed
+the files and the date of any change; and
+
+(c)    If You Externally Deploy Your Modifications, You must make Source Code
+of all Your Externally Deployed Modifications either available to those to whom
+You have Externally Deployed Your Modifications, or publicly available.  Source
+Code of Your Externally Deployed Modifications must be released under the terms
+set forth in this License, including the license grants set forth in Section 3
+below, for as long as you Externally Deploy the Covered Code or twelve (12)
+months from the date of initial External Deployment, whichever is longer. You
+should preferably distribute the Source Code of Your Externally Deployed
+Modifications electronically (e.g. download from a web site).
+
+2.3    Distribution of Executable Versions.  In addition, if You Externally
+Deploy Covered Code (Original Code and/or Modifications) in object code,
+executable form only, You must include a prominent notice, in the code itself
+as well as in related documentation, stating that Source Code of the Covered
+Code is available under the terms of this License with information on how and
+where to obtain such Source Code.  
+
+2.4    Third Party Rights.  You expressly acknowledge and agree that although
+Apple and each Contributor grants the licenses to their respective portions of
+the Covered Code set forth herein, no assurances are provided by Apple or any
+Contributor that the Covered Code does not infringe the patent or other
+intellectual property rights of any other entity. Apple and each Contributor
+disclaim any liability to You for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a condition to
+exercising the rights and licenses granted hereunder, You hereby assume sole
+responsibility to secure any other intellectual property rights needed, if any.
+For example, if a third party patent license is required to allow You to
+distribute the Covered Code, it is Your responsibility to acquire that license
+before distributing the Covered Code.
+
+3.     Your Grants.  In consideration of, and as a condition to, the licenses
+granted to You under this License, You hereby grant to any person or entity
+receiving or distributing Covered Code under this License a non-exclusive,
+royalty-free, perpetual, irrevocable license, under Your Applicable Patent
+Rights and other intellectual property rights (other than patent) owned or
+controlled by You, to use, reproduce, display, perform, modify, sublicense,
+distribute and Externally Deploy Your Modifications of the same scope and
+extent as Apple's licenses under Sections 2.1 and 2.2 above.  
+
+4.     Larger Works.  You may create a Larger Work by combining Covered Code
+with other code not governed by the terms of this License and distribute the
+Larger Work as a single product.  In each such instance, You must make sure the
+requirements of this License are fulfilled for the Covered Code or any portion
+thereof. 
+
+5.     Limitations on Patent License.   Except as expressly stated in Section
+2, no other patent rights, express or implied, are granted by Apple herein.
+Modifications and/or Larger Works may require additional patent licenses from
+Apple which Apple may grant in its sole discretion.  
+
+6.     Additional Terms.  You may choose to offer, and to charge a fee for,
+warranty, support, indemnity or liability obligations and/or other rights
+consistent with the scope of the license granted herein ("Additional Terms") to
+one or more recipients of Covered Code. However, You may do so only on Your own
+behalf and as Your sole responsibility, and not on behalf of Apple or any
+Contributor. You must obtain the recipient's agreement that any such Additional
+Terms are offered by You alone, and You hereby agree to indemnify, defend and
+hold Apple and every Contributor harmless for any liability incurred by or
+claims asserted against Apple or such Contributor by reason of any such
+Additional Terms. 
+
+7.     Versions of the License.  Apple may publish revised and/or new versions
+of this License from time to time.  Each version will be given a distinguishing
+version number.  Once Original Code has been published under a particular
+version of this License, You may continue to use it under the terms of that
+version. You may also choose to use such Original Code under the terms of any
+subsequent version of this License published by Apple.  No one other than Apple
+has the right to modify the terms applicable to Covered Code created under this
+License.  
+
+8.     NO WARRANTY OR SUPPORT.  The Covered Code may contain in whole or in
+part pre-release, untested, or not fully tested works.  The Covered Code may
+contain errors that could cause failures or loss of data, and may be incomplete
+or contain inaccuracies.  You expressly acknowledge and agree that use of the
+Covered Code, or any portion thereof, is at Your sole and entire risk.  THE
+COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF
+ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE"
+FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
+ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF
+SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF
+QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  APPLE AND EACH
+CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE
+COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR
+REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
+ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED.  NO ORAL OR
+WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED
+REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.  You acknowledge
+that the Covered Code is not intended for use in the operation of nuclear
+facilities, aircraft navigation, communication systems, or air traffic control
+machines in which case the failure of the Covered Code could lead to death,
+personal injury, or severe physical or environmental damage.
+
+9.     LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
+INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR
+YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER
+UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS
+LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL
+PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF
+LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT
+APPLY TO YOU. In no event shall Apple's total liability to You for all damages
+(other than as may be required by applicable law) under this License exceed the
+amount of fifty dollars ($50.00).
+
+10.    Trademarks.  This License does not grant any rights to use the
+trademarks or trade names  "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime
+Streaming Server" or any other trademarks, service marks, logos or trade names
+belonging to Apple (collectively "Apple Marks") or to any trademark, service
+mark, logo or trade name belonging to any Contributor.  You agree not to use
+any Apple Marks in or as part of the name of products derived from the Original
+Code or to endorse or promote products derived from the Original Code other
+than as expressly permitted by and in strict compliance at all times with
+Apple's third party trademark usage guidelines which are posted at
+http://www.apple.com/legal/guidelinesfor3rdparties.html.  
+
+11.    Ownership. Subject to the licenses granted under this License, each
+Contributor retains all rights, title and interest in and to any Modifications
+made by such Contributor.  Apple retains all rights, title and interest in and
+to the Original Code and any Modifications made by or on behalf of Apple
+("Apple Modifications"), and such Apple Modifications will not be automatically
+subject to this License.  Apple may, at its sole discretion, choose to license
+such Apple Modifications under this License, or on different terms from those
+contained in this License or may choose not to license them at all.  
+
+12.    Termination.  
+
+12.1   Termination.  This License and the rights granted hereunder will
 terminate:
 
-(a) automatically without notice from Apple if You fail to comply with
-any term(s) of this License and fail to cure such breach within 30
-days of becoming aware of such breach;
-
-(b) immediately in the event of the circumstances described in Section
+(a)    automatically without notice from Apple if You fail to comply with any
+term(s) of this License and fail to cure such breach within 30 days of becoming
+aware of such breach;
+(b)    immediately in the event of the circumstances described in Section
 13.5(b); or
-
-(c) automatically without notice from Apple if You, at any time during
-the term of this License, commence an action for patent infringement
-against Apple; provided that Apple did not first commence
-an action for patent infringement against You in that instance.
-
-12.2 Effect of Termination. Upon termination, You agree to immediately
-stop any further use, reproduction, modification, sublicensing and
-distribution of the Covered Code. All sublicenses to the Covered Code
-which have been properly granted prior to termination shall survive
-any termination of this License. Provisions which, by their nature,
-should remain in effect beyond the termination of this License shall
-survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
-12.2 and 13. No party will be liable to any other for compensation,
-indemnity or damages of any sort solely as a result of terminating
-this License in accordance with its terms, and termination of this
-License will be without prejudice to any other right or remedy of
-any party.
-
-13. Miscellaneous.
-
-13.1 Government End Users. The Covered Code is a "commercial item" as
-defined in FAR 2.101. Government software and technical data rights in
-the Covered Code include only those rights customarily provided to the
-public as defined in this License. This customary commercial license
-in technical data and software is provided in accordance with FAR
-12.211 (Technical Data) and 12.212 (Computer Software) and, for
-Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
-Commercial Items) and 227.7202-3 (Rights in Commercial Computer
-Software or Computer Software Documentation). Accordingly, all U.S.
-Government End Users acquire Covered Code with only those rights set
+(c)    automatically without notice from Apple if You, at any time during the
+term of this License, commence an action for patent infringement against Apple;
+provided that Apple did not first commence an action for patent infringement
+against You in that instance.
+
+12.2   Effect of Termination.  Upon termination, You agree to immediately stop
+any further use, reproduction, modification, sublicensing and distribution of
+the Covered Code.  All sublicenses to the Covered Code which have been properly
+granted prior to termination shall survive any termination of this License.
+Provisions which, by their nature, should remain in effect beyond the
+termination of this License shall survive, including but not limited to
+Sections 3, 5, 8, 9, 10, 11, 12.2 and 13.  No party will be liable to any other
+for compensation, indemnity or damages of any sort solely as a result of
+terminating this License in accordance with its terms, and termination of this
+License will be without prejudice to any other right or remedy of any party.
+
+13.    Miscellaneous.
+
+13.1   Government End Users.   The Covered Code is a "commercial item" as
+defined in FAR 2.101.  Government software and technical data rights in the
+Covered Code include only those rights customarily provided to the public as
+defined in this License. This customary commercial license in technical data
+and software is provided in accordance with FAR 12.211 (Technical Data) and
+12.212 (Computer Software) and, for Department of Defense purchases, DFAR
+252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in
+Commercial Computer Software or Computer Software Documentation).  Accordingly,
+all U.S. Government End Users acquire Covered Code with only those rights set
 forth herein.
 
-13.2 Relationship of Parties. This License will not be construed as
-creating an agency, partnership, joint venture or any other form of
-legal association between or among You, Apple or any Contributor, and
-You will not represent to the contrary, whether expressly, by
-implication, appearance or otherwise.
-
-13.3 Independent Development. Nothing in this License will impair
-Apple's right to acquire, license, develop, have others develop for
-it, market and/or distribute technology or products that perform the
-same or similar functions as, or otherwise compete with,
-Modifications, Larger Works, technology or products that You may
-develop, produce, market or distribute.
-
-13.4 Waiver; Construction. Failure by Apple or any Contributor to
-enforce any provision of this License will not be deemed a waiver of
-future enforcement of that or any other provision. Any law or
-regulation which provides that the language of a contract shall be
-construed against the drafter will not apply to this License.
-
-13.5 Severability. (a) If for any reason a court of competent
-jurisdiction finds any provision of this License, or portion thereof,
-to be unenforceable, that provision of the License will be enforced to
-the maximum extent permissible so as to effect the economic benefits
-and intent of the parties, and the remainder of this License will
-continue in full force and effect. (b) Notwithstanding the foregoing,
-if applicable law prohibits or restricts You from fully and/or
-specifically complying with Sections 2 and/or 3 or prevents the
-enforceability of either of those Sections, this License will
-immediately terminate and You must immediately discontinue any use of
-the Covered Code and destroy all copies of it that are in your
-possession or control.
-
-13.6 Dispute Resolution. Any litigation or other dispute resolution
-between You and Apple relating to this License shall take place in the
-Northern District of California, and You and Apple hereby consent to
-the personal jurisdiction of, and venue in, the state and federal
-courts within that District with respect to this License. The
-application of the United Nations Convention on Contracts for the
-International Sale of Goods is expressly excluded.
-
-13.7 Entire Agreement; Governing Law. This License constitutes the
-entire agreement between the parties with respect to the subject
-matter hereof. This License shall be governed by the laws of the
-United States and the State of California, except that body of
-California law concerning conflicts of law.
-
-Where You are located in the province of Quebec, Canada, the following
-clause applies: The parties hereby confirm that they have requested
-that this License and all related documents be drafted in English. Les
-parties ont exige que le present contrat et tous les documents
-connexes soient rediges en anglais.
-
-EXHIBIT A.
-
-"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
-Reserved.
-
-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.
+13.2   Relationship of Parties.  This License will not be construed as
+creating an agency, partnership, joint venture or any other form of legal
+association between or among You, Apple or any Contributor, and You will not
+represent to the contrary, whether expressly, by implication, appearance or
+otherwise.
+
+13.3   Independent Development.   Nothing in this License will impair Apple's
+right to acquire, license, develop, have others develop for it, market and/or
+distribute technology or products that perform the same or similar functions
+as, or otherwise compete with, Modifications, Larger Works, technology or
+products that You may develop, produce, market or distribute.
+
+13.4   Waiver; Construction.  Failure by Apple or any Contributor to enforce
+any provision of this License will not be deemed a waiver of future enforcement
+of that or any other provision.  Any law or regulation which provides that the
+language of a contract shall be construed against the drafter will not apply to
+this License.
+
+13.5   Severability.  (a) If for any reason a court of competent jurisdiction
+finds any provision of this License, or portion thereof, to be unenforceable,
+that provision of the License will be enforced to the maximum extent
+permissible so as to effect the economic benefits and intent of the parties,
+and the remainder of this License will continue in full force and effect.  (b)
+Notwithstanding the foregoing, if applicable law prohibits or restricts You
+from fully and/or specifically complying with Sections 2 and/or 3 or prevents
+the enforceability of either of those Sections, this License will immediately
+terminate and You must immediately discontinue any use of the Covered Code and
+destroy all copies of it that are in your possession or control.
+
+13.6   Dispute Resolution.  Any litigation or other dispute resolution between
+You and Apple relating to this License shall take place in the Northern
+District of California, and You and Apple hereby consent to the personal
+jurisdiction of, and venue in, the state and federal courts within that
+District with respect to this License. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is expressly
+excluded.
+
+13.7   Entire Agreement; Governing Law.  This License constitutes the entire
+agreement between the parties with respect to the subject matter hereof.  This
+License shall be governed by the laws of the United States and the State of
+California, except that body of California law concerning conflicts of law. 
+
+Where You are located in the province of Quebec, Canada, the following clause
+applies:  The parties hereby confirm that they have requested that this License
+and all related documents be drafted in English. Les parties ont exigé que le
+présent contrat et tous les documents connexes soient rédigés en anglais. 
+
+EXHIBIT A. 
+
+"Portions Copyright (c) 1999-2007 Apple Inc.  All Rights Reserved.
+
+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."
+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." 
+
index a96da5c1261550a23aee70dfb9b4134ce0892e89..c368273ac1f3be754d520077136ced5a193fdc00 100755 (executable)
@@ -4,27 +4,30 @@ echo "Setup ..."
 
 ALL_CFILES=`ls *.c`
 ALL_HFILES=`ls *.h`
+ALL_MFILES=`ls *.m`
 
 MACHINE_TYPE=`uname -p`
 UNICODE_DATA_FILE="UNKNOWN"
 
 if [ "$MACHINE_TYPE" == "i386" ]; then
-       UNICODE_DATA_FILE="CFUnicodeData-L.mapping"
+        UNICODE_DATA_FILE="CFUnicodeData-L.mapping"
 fi
 
-if [ "$MACHINE_TYPE" == "powerpc" ]; then
-       UNICODE_DATA_FILE="CFUnicodeData-B.mapping"
+if [ "$MACHINE_TYPE" == "i686" ]; then
+        UNICODE_DATA_FILE="CFUnicodeData-L.mapping"
 fi
 
-
+if [ "$MACHINE_TYPE" == "powerpc" ]; then
+        UNICODE_DATA_FILE="CFUnicodeData-B.mapping"
+fi
 
 PUBLIC_HEADERS="CFArray.h CFBag.h CFBase.h CFBinaryHeap.h CFBitVector.h CFBundle.h CFByteOrder.h CFCalendar.h CFCharacterSet.h CFData.h CFDate.h CFDateFormatter.h CFDictionary.h CFError.h CFLocale.h CFMachPort.h CFMessagePort.h CFNumber.h CFNumberFormatter.h CFPlugIn.h CFPlugInCOM.h CFPreferences.h CFPropertyList.h CFRunLoop.h CFSet.h CFSocket.h CFStream.h CFString.h CFStringEncodingExt.h CFTimeZone.h CFTree.h CFURL.h CFURLAccess.h CFUUID.h CFUserNotification.h CFXMLNode.h CFXMLParser.h CoreFoundation.h"
 PRIVATE_HEADERS="CFBundlePriv.h CFCharacterSetPriv.h CFError_Private.h CFLogUtilities.h CFPriv.h CFRuntime.h CFStorage.h CFStreamAbstract.h CFStreamPriv.h CFStreamInternal.h CFStringDefaultEncoding.h CFStringEncodingConverter.h CFStringEncodingConverterExt.h CFUniChar.h CFUnicodeDecomposition.h CFUnicodePrecomposition.h ForFoundationOnly.h"
 
-OBJBASE=../CF-Objects
-ARCHFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
-CFLAGS="-c -pipe -std=gnu99 -g -Wmost -Wno-trigraphs -mmacosx-version-min=10.5 -fconstant-cfstrings -fexceptions -DCF_BUILDING_CF=1 -DDEPLOYMENT_TARGET_MACOSX=1 -DMAC_OS_X_VERSION_MAX_ALLOWED=MAC_OS_X_VERSION_10_5 -DU_SHOW_DRAFT_API=1 -I$OBJBASE -DVERSION=476.10"
-LFLAGS="-dynamiclib -mmacosx-version-min=10.5 -twolevel_namespace -init ___CFInitialize -compatibility_version 150 -current_version 476 -sectcreate __UNICODE __csbitmaps CFCharacterSetBitmaps.bitmap -sectcreate __UNICODE __properties CFUniCharPropertyDatabase.data -sectcreate __UNICODE __data $UNICODE_DATA_FILE -segprot __UNICODE r r"
+OBJBASE=./CF-Objects
+ARCHFLAGS="-arch i386 -arch x86_64"
+CFLAGS="-c -x objective-c -pipe -std=gnu99 -g -Wmost -Wno-trigraphs -mmacosx-version-min=10.6 -fconstant-cfstrings -fexceptions -DCF_BUILDING_CF=1 -DDEPLOYMENT_TARGET_MACOSX=1 -DMAC_OS_X_VERSION_MAX_ALLOWED=MAC_OS_X_VERSION_10_6 -DU_SHOW_DRAFT_API=1 -I$OBJBASE -DVERSION=535 -include CoreFoundation_Prefix.h"
+LFLAGS="-dynamiclib -mmacosx-version-min=10.6 -twolevel_namespace -init ___CFInitialize -compatibility_version 150 -current_version 535 -sectcreate __UNICODE __csbitmaps CFCharacterSetBitmaps.bitmap -Wl,-alias_list,SymbolAliases -sectcreate __UNICODE __properties CFUniCharPropertyDatabase.data -sectcreate __UNICODE __data $UNICODE_DATA_FILE -segprot __UNICODE r r"
 
 /bin/rm -rf $OBJBASE
 /bin/mkdir -p $OBJBASE
@@ -46,6 +49,14 @@ Build () {
                        exit 1
                fi
        done
+       for F in $ALL_MFILES ; do
+               echo /usr/bin/gcc $STYLE_CFLAGS $ARCHFLAGS $CFLAGS $F -o $OBJBASE/$STYLE/`basename $F .m`.o
+               /usr/bin/gcc $STYLE_CFLAGS $ARCHFLAGS $CFLAGS $F -o $OBJBASE/$STYLE/`basename $F .m`.o
+               if [ $? -ne 0 ]; then
+                       echo "*** Compiling $STYLE failed ***"
+                       exit 1
+               fi
+       done
        echo "Linking $STYLE ..."
        echo /usr/bin/gcc $STYLE_LFLAGS -install_name /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation_$STYLE $ARCHFLAGS $LFLAGS $OBJBASE/$STYLE/*.o -licucore.A -lobjc -o $OBJBASE/CoreFoundation_$STYLE
        /usr/bin/gcc $STYLE_LFLAGS -install_name /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation_$STYLE $ARCHFLAGS $LFLAGS $OBJBASE/$STYLE/*.o -licucore.A -lobjc -o $OBJBASE/CoreFoundation_$STYLE
index 4fd73e99b6c785f67470ddd5af20597d69291d16..7133c231cf26809afaceb3035ab4b667f778acfd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFApplicationPreferences.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Chris Parker
 */
 
@@ -34,7 +34,7 @@
 #include <CoreFoundation/CFNumberFormatter.h>
 #include <CoreFoundation/CFDateFormatter.h>
 #include <sys/types.h>
-#if __MACH__
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <unistd.h>
 #endif
 
index 075f19201048dc74bbd01295d45006608dd7300f..bbb2ad3cfb7aaa2258a2ab6f65976fe1cf6e1fdf 100644 (file)
--- a/CFArray.c
+++ b/CFArray.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFArray.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #include <CoreFoundation/CFArray.h>
 #include "CFStorage.h"
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
 #include <string.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#include <libkern/OSAtomic.h>
+#endif
 
 __private_extern__ void _CFStorageSetWeak(CFStorageRef storage);
 
@@ -63,6 +66,7 @@ struct __CFArray {
     CFRuntimeBase _base;
     CFIndex _count;            /* number of objects */
     CFIndex _mutations;
+    int32_t _mutInProgress;
     void *_store;           /* can be NULL when MutableDeque */
 };
 
@@ -188,6 +192,16 @@ CF_INLINE bool __CFArrayCallBacksMatchCFType(const CFArrayCallBacks *c) {
         c->equal == kCFTypeArrayCallBacks.equal));
 }
 
+#if 0
+#define CHECK_FOR_MUTATION(A) do { if ((A)->_mutInProgress) CFLog(3, CFSTR("*** %s: function called while the array (%p) is being mutated in this or another thread"), __PRETTY_FUNCTION__, (A)); } while (0)
+#define BEGIN_MUTATION(A) do { OSAtomicAdd32Barrier(1, &((struct __CFArray *)(A))->_mutInProgress); } while (0)
+#define END_MUTATION(A) do { OSAtomicAdd32Barrier(-1, &((struct __CFArray *)(A))->_mutInProgress); } while (0)
+#else
+#define CHECK_FOR_MUTATION(A) do { } while (0)
+#define BEGIN_MUTATION(A) do { } while (0)
+#define END_MUTATION(A) do { } while (0)
+#endif
+
 struct _releaseContext {
     void (*release)(CFAllocatorRef, const void *);
     CFAllocatorRef allocator; 
@@ -310,13 +324,13 @@ static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) {
     result = CFStringCreateMutable(allocator, 0);
     switch (__CFArrayGetType(array)) {
     case __kCFArrayImmutable:
-       CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = immutable, count = %u, values = (\n"), cf, allocator, cnt);
+       CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = immutable, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
        break;
     case __kCFArrayDeque:
-       CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-small, count = %u, values = (\n"), cf, allocator, cnt);
+       CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-small, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
        break;
     case __kCFArrayStorage:
-       CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-large, count = %u, values = (\n"), cf, allocator, cnt);
+       CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-large, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
        break;
     }
     cb = __CFArrayGetCallBacks(array);
@@ -338,27 +352,31 @@ static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) {
 }
 
 
-static void __CFResourceRelease(CFTypeRef cf, const void *ignored) {
-    kCFTypeArrayCallBacks.release(kCFAllocatorSystemDefault, cf);
-}
-
 static void __CFArrayDeallocate(CFTypeRef cf) {
     CFArrayRef array = (CFArrayRef)cf;
+    BEGIN_MUTATION(array);
     // Under GC, keep contents alive when we know we can, either standard callbacks or NULL
     // if (__CFBitfieldGetValue(cf->info, 5, 4)) return; // bits only ever set under GC
     CFAllocatorRef allocator = __CFGetAllocator(array);
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
        // XXX_PCB keep array intact during finalization.
        const CFArrayCallBacks *cb = __CFArrayGetCallBacks(array);
-       if (cb->retain == NULL && cb->release == NULL)
+       if (cb->retain == NULL && cb->release == NULL) {
+           END_MUTATION(array);
             return;
+       }
         if (cb == &kCFTypeArrayCallBacks || cb->release == kCFTypeArrayCallBacks.release) {
             markFinalized(cf);
-            CFArrayApplyFunction((CFArrayRef)cf, CFRangeMake(0, __CFArrayGetCount(array)), (CFArrayApplierFunction)__CFResourceRelease, 0);
+            for (CFIndex idx = 0; idx < __CFArrayGetCount(array); idx++) {
+                const void *item = __CFArrayGetBucketAtIndex(array, 0 + idx)->_item;
+               kCFTypeArrayCallBacks.release(kCFAllocatorSystemDefault, item);
+            }
+           END_MUTATION(array);
             return;
         }
     }
     __CFArrayReleaseValues(array, CFRangeMake(0, __CFArrayGetCount(array)), true);
+    END_MUTATION(array);
 }
 
 static CFTypeID __kCFArrayTypeID = _kCFRuntimeNotATypeID;
@@ -417,7 +435,7 @@ static CFArrayRef __CFArrayInit(CFAllocatorRef allocator, UInt32 flags, CFIndex
     switch (__CFBitfieldGetValue(flags, 1, 0)) {
     case __kCFArrayImmutable:
         if (isWeakMemory(memory)) {  // if weak, don't scan
-            auto_zone_set_layout_type(__CFCollectableZone, memory, AUTO_OBJECT_UNSCANNED);
+            auto_zone_set_unscanned(auto_zone(), memory);
         }
        if (__CFOASafe) __CFSetLastAllocationEventName(memory, "CFArray (immutable)");
        break;
@@ -425,6 +443,7 @@ static CFArrayRef __CFArrayInit(CFAllocatorRef allocator, UInt32 flags, CFIndex
     case __kCFArrayStorage:
        if (__CFOASafe) __CFSetLastAllocationEventName(memory, "CFArray (mutable-variable)");
        ((struct __CFArray *)memory)->_mutations = 1;
+       ((struct __CFArray *)memory)->_mutInProgress = 0;
        ((struct __CFArray*)memory)->_store = NULL;
        break;
     }
@@ -451,17 +470,17 @@ CFArrayRef CFArrayCreate(CFAllocatorRef allocator, const void **values, CFIndex
     cb = __CFArrayGetCallBacks(result);
     buckets = __CFArrayGetBucketsPtr(result);
     bucketsAllocator = isStrongMemory(result) ? allocator : kCFAllocatorNull;
-    bucketsBase = CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator) ? (void *)auto_zone_base_pointer(__CFCollectableZone, buckets) : NULL;
+    bucketsBase = CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator) ? (void *)auto_zone_base_pointer(auto_zone(), buckets) : NULL;
     if (NULL != cb->retain) {
         for (idx = 0; idx < numValues; idx++) {
-           CF_WRITE_BARRIER_BASE_ASSIGN(bucketsAllocator, bucketsBase, buckets->_item, (void *)INVOKE_CALLBACK2(cb->retain, allocator, *values));
+           __CFAssignWithWriteBarrier((void **)&buckets->_item, (void *)INVOKE_CALLBACK2(cb->retain, allocator, *values));
             values++;
             buckets++;
         }
     }
     else {
         for (idx = 0; idx < numValues; idx++) {
-            CF_WRITE_BARRIER_BASE_ASSIGN(bucketsAllocator, bucketsBase, buckets->_item, *values);
+            __CFAssignWithWriteBarrier((void **)&buckets->_item, (void *)*values);
             values++;
             buckets++;
         }
@@ -476,43 +495,6 @@ CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacit
     return (CFMutableArrayRef)__CFArrayInit(allocator, __kCFArrayDeque, capacity, callBacks);
 }
 
-// This creates an array which is for CFTypes or NSObjects, with an ownership transfer --
-// the array does not take a retain, and the caller does not need to release the inserted objects.
-// The incoming objects must also be collectable if allocated out of a collectable allocator.
-CFArrayRef _CFArrayCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const void **values, CFIndex numValues) {
-    CFArrayRef result;
-    result = __CFArrayInit(allocator, isMutable ? __kCFArrayDeque : __kCFArrayImmutable, numValues, &kCFTypeArrayCallBacks);
-    if (!isMutable) {
-       struct __CFArrayBucket *buckets = __CFArrayGetBucketsPtr(result);
-       CF_WRITE_BARRIER_MEMMOVE(buckets, values, numValues * sizeof(struct __CFArrayBucket));
-    } else {
-       if (__CF_MAX_BUCKETS_PER_DEQUE <= numValues) {
-           CFStorageRef store = (CFStorageRef)CFMakeCollectable(CFStorageCreate(allocator, sizeof(const void *)));
-           if (__CFOASafe) __CFSetLastAllocationEventName(store, "CFArray (store-storage)");
-           CF_WRITE_BARRIER_BASE_ASSIGN(allocator, result, result->_store, store);
-           CFStorageInsertValues(store, CFRangeMake(0, numValues));
-           CFStorageReplaceValues(store, CFRangeMake(0, numValues), values);
-           __CFBitfieldSetValue(((CFRuntimeBase *)result)->_cfinfo[CF_INFO_BITS], 1, 0, __kCFArrayStorage);
-       } else if (0 <= numValues) {
-           struct __CFArrayDeque *deque;
-           struct __CFArrayBucket *raw_buckets;
-           CFIndex capacity = __CFArrayDequeRoundUpCapacity(numValues);
-           CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket);
-           deque = (struct __CFArrayDeque *)_CFAllocatorAllocateGC(allocator, size, isStrongMemory(result) ? __kCFAllocatorGCScannedMemory : 0);
-           if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)");
-           deque->_leftIdx = (capacity - numValues) / 2;
-           deque->_capacity = capacity;
-           deque->_bias = 0;
-           CF_WRITE_BARRIER_BASE_ASSIGN(allocator, result, result->_store, deque);
-           raw_buckets = (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque));
-           CF_WRITE_BARRIER_MEMMOVE(raw_buckets + deque->_leftIdx + 0, values, numValues * sizeof(struct __CFArrayBucket));
-           __CFBitfieldSetValue(((CFRuntimeBase *)result)->_cfinfo[CF_INFO_BITS], 1, 0, __kCFArrayDeque);
-       }
-    }
-    __CFArraySetCount(result, numValues);
-    return result;
-}
-
 CFArrayRef CFArrayCreateCopy(CFAllocatorRef allocator, CFArrayRef array) {
     CFArrayRef result;
     const CFArrayCallBacks *cb;
@@ -530,13 +512,13 @@ CFArrayRef CFArrayCreateCopy(CFAllocatorRef allocator, CFArrayRef array) {
     cb = __CFArrayGetCallBacks(result); // GC: use the new array's callbacks so we don't leak.
     buckets = __CFArrayGetBucketsPtr(result);
     bucketsAllocator = isStrongMemory(result) ? allocator : kCFAllocatorNull;
-       bucketsBase = CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator) ? (void *)auto_zone_base_pointer(__CFCollectableZone, buckets) : NULL;
+       bucketsBase = CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator) ? (void *)auto_zone_base_pointer(auto_zone(), buckets) : NULL;
     for (idx = 0; idx < numValues; idx++) {
        const void *value = CFArrayGetValueAtIndex(array, idx);
        if (NULL != cb->retain) {
            value = (void *)INVOKE_CALLBACK2(cb->retain, allocator, value);
        }
-       CF_WRITE_BARRIER_BASE_ASSIGN(bucketsAllocator, bucketsBase, buckets->_item, value);
+       __CFAssignWithWriteBarrier((void **)&buckets->_item, (void *)value);
        buckets++;
     }
     __CFArraySetCount(result, numValues);
@@ -567,6 +549,7 @@ CFMutableArrayRef CFArrayCreateMutableCopy(CFAllocatorRef allocator, CFIndex cap
 CFIndex CFArrayGetCount(CFArrayRef array) {
     CF_OBJC_FUNCDISPATCH0(__kCFArrayTypeID, CFIndex, array, "count");
     __CFGenericValidateType(array, __kCFArrayTypeID);
+    CHECK_FOR_MUTATION(array);
     return __CFArrayGetCount(array);
 }
 
@@ -575,9 +558,10 @@ CFIndex CFArrayGetCountOfValue(CFArrayRef array, CFRange range, const void *valu
     const CFArrayCallBacks *cb;
     CFIndex idx, count = 0;
 // CF: this ignores range
-    CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID, CFIndex, array, "countOccurrences:", value);
+    CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID, CFIndex, array, "_cfcountOccurrences:", value);
     __CFGenericValidateType(array, __kCFArrayTypeID);    
     __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
     cb = __CFArrayGetCallBacks(array);
     for (idx = 0; idx < range.length; idx++) {
        const void *item = __CFArrayGetBucketAtIndex(array, range.location + idx)->_item;
@@ -593,21 +577,14 @@ Boolean CFArrayContainsValue(CFArrayRef array, CFRange range, const void *value)
     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, char, array, "containsObject:inRange:", value, range);
     __CFGenericValidateType(array, __kCFArrayTypeID);
     __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
+    const CFArrayCallBacks *cb = __CFArrayGetCallBacks(array);
     for (idx = 0; idx < range.length; idx++) {
        const void *item = __CFArrayGetBucketAtIndex(array, range.location + idx)->_item;
-       if (value == item) {
+       if (value == item || (cb->equal && INVOKE_CALLBACK2(cb->equal, value, item))) {
            return true;
        }
     }
-    const CFArrayCallBacks *cb = __CFArrayGetCallBacks(array);
-    if (cb->equal) {
-       for (idx = 0; idx < range.length; idx++) {
-           const void *item = __CFArrayGetBucketAtIndex(array, range.location + idx)->_item;
-           if (INVOKE_CALLBACK2(cb->equal, value, item)) {
-               return true;
-           }
-       }
-    }
     return false;
 }
 
@@ -615,11 +592,13 @@ const void *CFArrayGetValueAtIndex(CFArrayRef array, CFIndex idx) {
     CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID, void *, array, "objectAtIndex:", idx);
     __CFGenericValidateType(array, __kCFArrayTypeID);
     CFAssert2(0 <= idx && idx < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
+    CHECK_FOR_MUTATION(array);
     return __CFArrayGetBucketAtIndex(array, idx)->_item;
 }
 
 // This is for use by NSCFArray; it avoids ObjC dispatch, and checks for out of bounds
 const void *_CFArrayCheckAndGetValueAtIndex(CFArrayRef array, CFIndex idx) {
+    CHECK_FOR_MUTATION(array);
     if (0 <= idx && idx < __CFArrayGetCount(array)) return __CFArrayGetBucketAtIndex(array, idx)->_item;
     return (void *)(-1);
 }
@@ -630,11 +609,12 @@ void CFArrayGetValues(CFArrayRef array, CFRange range, const void **values) {
     __CFGenericValidateType(array, __kCFArrayTypeID);
     __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
     CFAssert1(NULL != values, __kCFLogAssertion, "%s(): pointer to values may not be NULL", __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
     if (0 < range.length) {
        switch (__CFArrayGetType(array)) {
        case __kCFArrayImmutable:
        case __kCFArrayDeque:
-           CF_WRITE_BARRIER_MEMMOVE(values, __CFArrayGetBucketsPtr(array) + range.location, range.length * sizeof(struct __CFArrayBucket));
+           objc_memmove_collectable(values, __CFArrayGetBucketsPtr(array) + range.location, range.length * sizeof(struct __CFArrayBucket));
            break;
        case __kCFArrayStorage: {
            CFStorageRef store = (CFStorageRef)array->_store;
@@ -646,7 +626,8 @@ void CFArrayGetValues(CFArrayRef array, CFRange range, const void **values) {
 }
 
 
-unsigned long _CFArrayFastEnumeration(CFArrayRef array, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
+CF_EXPORT unsigned long _CFArrayFastEnumeration(CFArrayRef array, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
+    CHECK_FOR_MUTATION(array);
     if (array->_count == 0) return 0;
     enum { ATSTART = 0, ATEND = 1 };
     switch (__CFArrayGetType(array)) {
@@ -678,10 +659,11 @@ unsigned long _CFArrayFastEnumeration(CFArrayRef array, struct __objcFastEnumera
 void CFArrayApplyFunction(CFArrayRef array, CFRange range, CFArrayApplierFunction applier, void *context) {
     CFIndex idx;
     FAULT_CALLBACK((void **)&(applier));
-    CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, void, array, "apply:context:", applier, context);
+    CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, void, array, "_cfapply:context:", applier, context);
     __CFGenericValidateType(array, __kCFArrayTypeID);
     __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
     CFAssert1(NULL != applier, __kCFLogAssertion, "%s(): pointer to applier function may not be NULL", __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
     for (idx = 0; idx < range.length; idx++) {
        const void *item = __CFArrayGetBucketAtIndex(array, range.location + idx)->_item;
        INVOKE_CALLBACK2(applier, item, context);
@@ -694,6 +676,7 @@ CFIndex CFArrayGetFirstIndexOfValue(CFArrayRef array, CFRange range, const void
     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, CFIndex, array, "_cfindexOfObject:inRange:", value, range);
     __CFGenericValidateType(array, __kCFArrayTypeID);
     __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
     cb = __CFArrayGetCallBacks(array);
     for (idx = 0; idx < range.length; idx++) {
        const void *item = __CFArrayGetBucketAtIndex(array, range.location + idx)->_item;
@@ -709,6 +692,7 @@ CFIndex CFArrayGetLastIndexOfValue(CFArrayRef array, CFRange range, const void *
     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, CFIndex, array, "_cflastIndexOfObject:inRange:", value, range);
     __CFGenericValidateType(array, __kCFArrayTypeID);
     __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
     cb = __CFArrayGetCallBacks(array);
     for (idx = range.length; idx--;) {
        const void *item = __CFArrayGetBucketAtIndex(array, range.location + idx)->_item;
@@ -722,6 +706,7 @@ void CFArrayAppendValue(CFMutableArrayRef array, const void *value) {
     CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID, void, array, "addObject:", value);
     __CFGenericValidateType(array, __kCFArrayTypeID);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
     _CFArrayReplaceValues(array, CFRangeMake(__CFArrayGetCount(array), 0), &value, 1);
 }
 
@@ -730,23 +715,25 @@ void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *va
     __CFGenericValidateType(array, __kCFArrayTypeID);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
     CFAssert2(0 <= idx && idx <= __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
+    CHECK_FOR_MUTATION(array);
     if (idx == __CFArrayGetCount(array)) {
        _CFArrayReplaceValues(array, CFRangeMake(idx, 0), &value, 1);
     } else {
+       BEGIN_MUTATION(array);
        const void *old_value;
        const CFArrayCallBacks *cb = __CFArrayGetCallBacks(array);
        CFAllocatorRef allocator = __CFGetAllocator(array);
-        CFAllocatorRef bucketsAllocator = isStrongMemory(array) ? allocator : kCFAllocatorNull;
        struct __CFArrayBucket *bucket = __CFArrayGetBucketAtIndex(array, idx);
        if (NULL != cb->retain && !hasBeenFinalized(array)) {
            value = (void *)INVOKE_CALLBACK2(cb->retain, allocator, value);
        }
        old_value = bucket->_item;
-       CF_WRITE_BARRIER_ASSIGN(bucketsAllocator, bucket->_item, value); // GC: handles deque/CFStorage cases.
+       __CFAssignWithWriteBarrier((void **)&bucket->_item, (void *)value); // GC: handles deque/CFStorage cases.
        if (NULL != cb->release && !hasBeenFinalized(array)) {
            INVOKE_CALLBACK2(cb->release, allocator, old_value);
        }
        array->_mutations++;
+        END_MUTATION(array);
     }
 }
 
@@ -755,6 +742,7 @@ void CFArrayInsertValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void
     __CFGenericValidateType(array, __kCFArrayTypeID);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
     CFAssert2(0 <= idx && idx <= __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
+    CHECK_FOR_MUTATION(array);
     _CFArrayReplaceValues(array, CFRangeMake(idx, 0), &value, 1);
 }
 
@@ -762,20 +750,22 @@ void CFArrayExchangeValuesAtIndices(CFMutableArrayRef array, CFIndex idx1, CFInd
     const void *tmp;
     struct __CFArrayBucket *bucket1, *bucket2;
     CFAllocatorRef bucketsAllocator;
-    CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, void, array, "exchange::", idx1, idx2);
+    CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, void, array, "_cfexchange::", idx1, idx2);
     __CFGenericValidateType(array, __kCFArrayTypeID);
     CFAssert2(0 <= idx1 && idx1 < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index #1 (%d) out of bounds", __PRETTY_FUNCTION__, idx1);
     CFAssert2(0 <= idx2 && idx2 < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index #2 (%d) out of bounds", __PRETTY_FUNCTION__, idx2);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
+    BEGIN_MUTATION(array);
     bucket1 = __CFArrayGetBucketAtIndex(array, idx1);
     bucket2 = __CFArrayGetBucketAtIndex(array, idx2);
     tmp = bucket1->_item;
     bucketsAllocator = isStrongMemory(array) ? __CFGetAllocator(array) : kCFAllocatorNull;
     // XXX these aren't needed.
-    CF_WRITE_BARRIER_ASSIGN(bucketsAllocator, bucket1->_item, bucket2->_item);
-    CF_WRITE_BARRIER_ASSIGN(bucketsAllocator, bucket2->_item, tmp);
+    __CFAssignWithWriteBarrier((void **)&bucket1->_item, (void *)bucket2->_item);
+    __CFAssignWithWriteBarrier((void **)&bucket2->_item, (void *)tmp);
     array->_mutations++;
-
+    END_MUTATION(array);
 }
 
 void CFArrayRemoveValueAtIndex(CFMutableArrayRef array, CFIndex idx) {
@@ -783,6 +773,7 @@ void CFArrayRemoveValueAtIndex(CFMutableArrayRef array, CFIndex idx) {
     __CFGenericValidateType(array, __kCFArrayTypeID);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
     CFAssert2(0 <= idx && idx < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
+    CHECK_FOR_MUTATION(array);
     _CFArrayReplaceValues(array, CFRangeMake(idx, 1), NULL, 0);
 }
 
@@ -790,23 +781,29 @@ void CFArrayRemoveAllValues(CFMutableArrayRef array) {
     CF_OBJC_FUNCDISPATCH0(__kCFArrayTypeID, void, array, "removeAllObjects");
     __CFGenericValidateType(array, __kCFArrayTypeID);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
+    BEGIN_MUTATION(array);
     __CFArrayReleaseValues(array, CFRangeMake(0, __CFArrayGetCount(array)), true);
     __CFArraySetCount(array, 0);
     array->_mutations++;
+    END_MUTATION(array);
 }
 
 static void __CFArrayConvertDequeToStore(CFMutableArrayRef array) {
     struct __CFArrayDeque *deque = (struct __CFArrayDeque *)array->_store;
     struct __CFArrayBucket *raw_buckets = (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque));
     CFStorageRef store;
-    CFIndex count = CFArrayGetCount(array);
+    CFIndex count = __CFArrayGetCount(array);
     CFAllocatorRef allocator = __CFGetAllocator(array);
-    store = (CFStorageRef)CFMakeCollectable(CFStorageCreate(allocator, sizeof(const void *)));
+    Boolean collectableMemory = CF_IS_COLLECTABLE_ALLOCATOR(allocator);
+    if (collectableMemory) auto_zone_retain(auto_zone(), deque);
+    store = CFStorageCreate(allocator, sizeof(const void *));
     if (__CFOASafe) __CFSetLastAllocationEventName(store, "CFArray (store-storage)");
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, array, array->_store, store);
+    __CFAssignWithWriteBarrier((void **)&array->_store, (void *)store);
+    CFMakeCollectable(store);   // GC: now safe to unroot the store.
     CFStorageInsertValues(store, CFRangeMake(0, count));
     CFStorageReplaceValues(store, CFRangeMake(0, count), raw_buckets + deque->_leftIdx);
-    _CFAllocatorDeallocateGC(__CFGetAllocator(array), deque);
+    CFAllocatorDeallocate(__CFGetAllocator(array), deque);
     __CFBitfieldSetValue(((CFRuntimeBase *)array)->_cfinfo[CF_INFO_BITS], 1, 0, __kCFArrayStorage);
 }
 
@@ -819,15 +816,18 @@ static void __CFArrayConvertStoreToDeque(CFMutableArrayRef array) {
     CFIndex capacity = __CFArrayDequeRoundUpCapacity(count + 6);
     CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket);
     CFAllocatorRef allocator = __CFGetAllocator(array);
-    deque = (struct __CFArrayDeque *)_CFAllocatorAllocateGC(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
+    Boolean collectableMemory = CF_IS_COLLECTABLE_ALLOCATOR(allocator);
+    if (collectableMemory) CFRetain(store); // GC:  need to root the CFStorage
+    deque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
     if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)");
     deque->_leftIdx = (capacity - count) / 2;
     deque->_capacity = capacity;
     deque->_bias = 0;
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, array, array->_store, deque);
+    __CFAssignWithWriteBarrier((void **)&array->_store, (void *)deque);
+    if (collectableMemory) auto_zone_release(auto_zone(), deque);
     raw_buckets = (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque));
     CFStorageGetValues(store, CFRangeMake(0, count), raw_buckets + deque->_leftIdx);
-    _CFReleaseGC(store); // GC:  balances CFMakeCollectable() above.
+    CFRelease(store);
     __CFBitfieldSetValue(((CFRuntimeBase *)array)->_cfinfo[CF_INFO_BITS], 1, 0, __kCFArrayDeque);
 }
 
@@ -857,7 +857,7 @@ static void __CFArrayRepositionDequeRegions(CFMutableArrayRef array, CFRange ran
        CFIndex capacity = __CFArrayDequeRoundUpCapacity(futureCnt + wiggle);
        CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket);
        CFAllocatorRef allocator = __CFGetAllocator(array);
-       struct __CFArrayDeque *newDeque = (struct __CFArrayDeque *)_CFAllocatorAllocateGC(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
+       struct __CFArrayDeque *newDeque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
        if (__CFOASafe) __CFSetLastAllocationEventName(newDeque, "CFArray (store-deque)");
        struct __CFArrayBucket *newBuckets = (struct __CFArrayBucket *)((uint8_t *)newDeque + sizeof(struct __CFArrayDeque));
        CFIndex oldL = L;
@@ -867,10 +867,11 @@ static void __CFArrayRepositionDequeRegions(CFMutableArrayRef array, CFRange ran
        newDeque->_leftIdx = newL;
        newDeque->_capacity = capacity;
        newDeque->_bias = 0;
-       if (0 < A) CF_WRITE_BARRIER_MEMMOVE(newBuckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket));
-       if (0 < C) CF_WRITE_BARRIER_MEMMOVE(newBuckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket));
+       if (0 < A) objc_memmove_collectable(newBuckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket));
+       if (0 < C) objc_memmove_collectable(newBuckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket));
        if (deque) _CFAllocatorDeallocateGC(allocator, deque);
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, array, array->_store, newDeque);
+       __CFAssignWithWriteBarrier((void **)&array->_store, (void *)newDeque);
+       if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) auto_zone_release(auto_zone(), newDeque);
        return;
     }
 
@@ -879,18 +880,18 @@ static void __CFArrayRepositionDequeRegions(CFMutableArrayRef array, CFRange ran
        // inserting: C is smaller and R has room
        CFIndex oldC0 = L + A + B;
        CFIndex newC0 = L + A + newCount;
-       if (0 < C) CF_WRITE_BARRIER_MEMMOVE(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket));
+       if (0 < C) objc_memmove_collectable(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket));
        // GrP GC: zero-out newly exposed space on the right, if any
-       if (oldC0 > newC0) bzero(buckets + newC0 + C, (oldC0 - newC0) * sizeof(struct __CFArrayBucket));
+       if (oldC0 > newC0) memset(buckets + newC0 + C, 0, (oldC0 - newC0) * sizeof(struct __CFArrayBucket));
     } else if ((numNewElems < 0) || (numNewElems <= L && A <= C)) {    // move A
        // deleting: A is smaller or equal (covers remaining delete cases)
        // inserting: A is smaller and L has room
        CFIndex oldL = L;
        CFIndex newL = L - numNewElems;
        deque->_leftIdx = newL;
-       if (0 < A) CF_WRITE_BARRIER_MEMMOVE(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket));
+       if (0 < A) objc_memmove_collectable(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket));
        // GrP GC: zero-out newly exposed space on the left, if any
-       if (newL > oldL) bzero(buckets + oldL, (newL - oldL) * sizeof(struct __CFArrayBucket));
+       if (newL > oldL) memset(buckets + oldL, 0, (newL - oldL) * sizeof(struct __CFArrayBucket));
     } else {
        // now, must be inserting, and either:
        //    A<=C, but L doesn't have room (R might have, but don't care)
@@ -909,23 +910,22 @@ static void __CFArrayRepositionDequeRegions(CFMutableArrayRef array, CFRange ran
        CFIndex newC0 = newL + A + newCount;
        deque->_leftIdx = newL;
        if (newL < oldL) {
-           if (0 < A) CF_WRITE_BARRIER_MEMMOVE(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket));
-           if (0 < C) CF_WRITE_BARRIER_MEMMOVE(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket));
+           if (0 < A) objc_memmove_collectable(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket));
+           if (0 < C) objc_memmove_collectable(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket));
            // GrP GC: zero-out newly exposed space on the right, if any
-           if (oldC0 > newC0) bzero(buckets + newC0 + C, (oldC0 - newC0) * sizeof(struct __CFArrayBucket));
+           if (oldC0 > newC0) memset(buckets + newC0 + C, 0, (oldC0 - newC0) * sizeof(struct __CFArrayBucket));
        } else {
-           if (0 < C) CF_WRITE_BARRIER_MEMMOVE(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket));
-           if (0 < A) CF_WRITE_BARRIER_MEMMOVE(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket));
+           if (0 < C) objc_memmove_collectable(buckets + newC0, buckets + oldC0, C * sizeof(struct __CFArrayBucket));
+           if (0 < A) objc_memmove_collectable(buckets + newL, buckets + oldL, A * sizeof(struct __CFArrayBucket));
            // GrP GC: zero-out newly exposed space on the left, if any
-           if (newL > oldL) bzero(buckets + oldL, (newL - oldL) * sizeof(struct __CFArrayBucket));
+           if (newL > oldL) memset(buckets + oldL, 0, (newL - oldL) * sizeof(struct __CFArrayBucket));
        }
     }
 }
 
 static void __CFArrayHandleOutOfMemory(CFTypeRef obj, CFIndex numBytes) {
     CFStringRef msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for CFArray failed"), numBytes);
-    CFBadErrorCallBack cb = _CFGetOutOfMemoryErrorCallBack();
-    if (NULL == cb || !cb(obj, CFSTR("NS/CFArray"), msg)) {
+    {
         CFLog(kCFLogLevelCritical, CFSTR("%@"), msg);
         HALT;
     }
@@ -938,6 +938,8 @@ void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap) {
     __CFGenericValidateType(array, __kCFArrayTypeID);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
     CFAssert3(__CFArrayGetCount(array) <= cap, __kCFLogAssertion, "%s(): desired capacity (%d) is less than count (%d)", __PRETTY_FUNCTION__, cap, __CFArrayGetCount(array));
+    CHECK_FOR_MUTATION(array);
+    BEGIN_MUTATION(array);
     // Currently, attempting to set the capacity of an array which is the CFStorage
     // variant, or set the capacity larger than __CF_MAX_BUCKETS_PER_DEQUE, has no
     // effect.  The primary purpose of this API is to help avoid a bunch of the
@@ -947,24 +949,27 @@ void _CFArraySetCapacity(CFMutableArrayRef array, CFIndex cap) {
        CFIndex capacity = __CFArrayDequeRoundUpCapacity(cap);
        CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket);
        CFAllocatorRef allocator = __CFGetAllocator(array);
+       Boolean collectableMemory = CF_IS_COLLECTABLE_ALLOCATOR(allocator);
        if (NULL == deque) {
-           deque = (struct __CFArrayDeque *)_CFAllocatorAllocateGC(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
+           deque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
            if (NULL == deque) __CFArrayHandleOutOfMemory(array, size);
            if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)");
            deque->_leftIdx = capacity / 2; 
        } else {
            struct __CFArrayDeque *olddeque = deque;
            CFIndex oldcap = deque->_capacity;
-           deque = (struct __CFArrayDeque *)_CFAllocatorAllocateGC(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
+           deque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
            if (NULL == deque) __CFArrayHandleOutOfMemory(array, size);
-           CF_WRITE_BARRIER_MEMMOVE(deque, olddeque, sizeof(struct __CFArrayDeque) + oldcap * sizeof(struct __CFArrayBucket));
+           objc_memmove_collectable(deque, olddeque, sizeof(struct __CFArrayDeque) + oldcap * sizeof(struct __CFArrayBucket));
            _CFAllocatorDeallocateGC(allocator, olddeque);
            if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)");
        }
        deque->_capacity = capacity;
        deque->_bias = 0;
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, array, array->_store, deque);
+       __CFAssignWithWriteBarrier((void **)&array->_store, (void *)deque);
+       if (collectableMemory) auto_zone_release(auto_zone(), deque);
     }    
+    END_MUTATION(array);
 }
 
 
@@ -974,12 +979,15 @@ void CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void **n
     __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
     CFAssert2(0 <= newCount, __kCFLogAssertion, "%s(): newCount (%d) cannot be less than zero", __PRETTY_FUNCTION__, newCount);
+    CHECK_FOR_MUTATION(array);
     return _CFArrayReplaceValues(array, range, newValues, newCount);
 }
 
 // This function does no ObjC dispatch or argument checking;
 // It should only be called from places where that dispatch and check has already been done, or NSCFArray
 void _CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void **newValues, CFIndex newCount) {
+    CHECK_FOR_MUTATION(array);
+    BEGIN_MUTATION(array);
     const CFArrayCallBacks *cb;
     CFAllocatorRef allocator;
     CFIndex idx, cnt, futureCnt;
@@ -989,6 +997,7 @@ void _CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void **
     CFAssert1(newCount <= futureCnt, __kCFLogAssertion, "%s(): internal error 1", __PRETTY_FUNCTION__);
     cb = __CFArrayGetCallBacks(array);
     allocator = __CFGetAllocator(array);
+
     /* Retain new values if needed, possibly allocating a temporary buffer for them */
     if (NULL != cb->retain && !hasBeenFinalized(array)) {
        newv = (newCount <= 256) ? (const void **)buffer : (const void **)CFAllocatorAllocate(allocator, newCount * sizeof(void *), 0); // GC OK
@@ -1028,22 +1037,24 @@ void _CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void **
        }
     } else if (NULL == array->_store) {
        if (__CF_MAX_BUCKETS_PER_DEQUE <= futureCnt) {
-           CFStorageRef store = (CFStorageRef)CFMakeCollectable(CFStorageCreate(allocator, sizeof(const void *)));
+           CFStorageRef store = CFStorageCreate(allocator, sizeof(const void *));
            if (! isStrongMemory(array)) _CFStorageSetWeak(store);
            if (__CFOASafe) __CFSetLastAllocationEventName(store, "CFArray (store-storage)");
-           CF_WRITE_BARRIER_BASE_ASSIGN(allocator, array, array->_store, store);
+           __CFAssignWithWriteBarrier((void **)&array->_store, (void *)store);
+           CFMakeCollectable(store);
            CFStorageInsertValues(store, CFRangeMake(0, newCount));
            __CFBitfieldSetValue(((CFRuntimeBase *)array)->_cfinfo[CF_INFO_BITS], 1, 0, __kCFArrayStorage);
        } else if (0 <= futureCnt) {
            struct __CFArrayDeque *deque;
            CFIndex capacity = __CFArrayDequeRoundUpCapacity(futureCnt);
            CFIndex size = sizeof(struct __CFArrayDeque) + capacity * sizeof(struct __CFArrayBucket);
-           deque = (struct __CFArrayDeque *)_CFAllocatorAllocateGC(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
+           deque = (struct __CFArrayDeque *)CFAllocatorAllocate(allocator, size, isStrongMemory(array) ? __kCFAllocatorGCScannedMemory : 0);
            if (__CFOASafe) __CFSetLastAllocationEventName(deque, "CFArray (store-deque)");
            deque->_leftIdx = (capacity - newCount) / 2;
            deque->_capacity = capacity;
            deque->_bias = 0;
-           CF_WRITE_BARRIER_BASE_ASSIGN(allocator, array, array->_store, deque);
+           __CFAssignWithWriteBarrier((void **)&array->_store, (void *)deque);
+           if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) auto_zone_release(auto_zone(), deque); // GC: now safe to unroot the array body.
        }
     } else {           // Deque
        // reposition regions A and C for new region B elements in gap
@@ -1068,15 +1079,12 @@ void _CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void **
        } else {        // Deque
            struct __CFArrayDeque *deque = (struct __CFArrayDeque *)array->_store;
            struct __CFArrayBucket *raw_buckets = (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque));
-            CFAllocatorRef bucketsAllocator = isStrongMemory(array) ? allocator : kCFAllocatorNull;
-           if (newCount == 1)
-               CF_WRITE_BARRIER_ASSIGN(bucketsAllocator, *((const void **)raw_buckets + deque->_leftIdx + range.location), newv[0]);
-           else
-               CF_WRITE_BARRIER_MEMMOVE(raw_buckets + deque->_leftIdx + range.location, newv, newCount * sizeof(struct __CFArrayBucket));
+           objc_memmove_collectable(raw_buckets + deque->_leftIdx + range.location, newv, newCount * sizeof(struct __CFArrayBucket));
        }
     }
     __CFArraySetCount(array, futureCnt);
     if (newv != buffer && newv != newValues) CFAllocatorDeallocate(allocator, newv);
+    END_MUTATION(array);
 }
 
 struct _acompareContext {
@@ -1097,6 +1105,8 @@ void CFArraySortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunct
     __CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
     CFAssert1(NULL != comparator, __kCFLogAssertion, "%s(): pointer to comparator function may not be NULL", __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
+    BEGIN_MUTATION(array);
     array->_mutations++;
 
     if (1 < range.length) {
@@ -1107,28 +1117,22 @@ void CFArraySortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunct
        switch (__CFArrayGetType(array)) {
        case __kCFArrayDeque:
            bucket = __CFArrayGetBucketsPtr(array) + range.location;
-           if (CF_USING_COLLECTABLE_MEMORY && isStrongMemory(array)) {
-                size_t size = range.length * sizeof(void*);
-                __CFObjCWriteBarrierRange(bucket, size);
-                CFQSortArray(bucket, range.length, sizeof(void *), (CFComparatorFunction)__CFArrayCompareValues, &ctx);
-            } else {
-                CFQSortArray(bucket, range.length, sizeof(void *), (CFComparatorFunction)__CFArrayCompareValues, &ctx);
-            }
+            CFQSortArray(bucket, range.length, sizeof(void *), (CFComparatorFunction)__CFArrayCompareValues, &ctx);
            break;
        case __kCFArrayStorage: {
            CFStorageRef store = (CFStorageRef)array->_store;
-           CFAllocatorRef allocator = __CFGetAllocator(array);
            const void **values, *buffer[256];
-           values = (range.length <= 256) ? (const void **)buffer : (const void **)CFAllocatorAllocate(allocator, range.length * sizeof(void *), 0); // GC OK
+           values = (range.length <= 256) ? (const void **)buffer : (const void **)CFAllocatorAllocate(kCFAllocatorSystemDefault, range.length * sizeof(void *), 0); // GC OK
            if (values != buffer && __CFOASafe) __CFSetLastAllocationEventName(values, "CFArray (temp)");
            CFStorageGetValues(store, range, values);
            CFQSortArray(values, range.length, sizeof(void *), (CFComparatorFunction)__CFArrayCompareValues, &ctx);
            CFStorageReplaceValues(store, range, values);
-           if (values != buffer) CFAllocatorDeallocate(allocator, values);  // GC OK
+           if (values != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, values);  // GC OK
            break;
        }
        }
     }
+    END_MUTATION(array);
 }
 
 CFIndex CFArrayBSearchValues(CFArrayRef array, CFRange range, const void *value, CFComparatorFunction comparator, void *context) {
@@ -1137,6 +1141,7 @@ CFIndex CFArrayBSearchValues(CFArrayRef array, CFRange range, const void *value,
     CFAssert1(NULL != comparator, __kCFLogAssertion, "%s(): pointer to comparator function may not be NULL", __PRETTY_FUNCTION__);
     bool isObjC = CF_IS_OBJC(__kCFArrayTypeID, array);
     FAULT_CALLBACK((void **)&(comparator));
+    if (!isObjC) CHECK_FOR_MUTATION(array);
     CFIndex idx = 0;
     if (range.length <= 0) return range.location;
     if (isObjC || __kCFArrayStorage == __CFArrayGetType(array)) {
@@ -1175,7 +1180,41 @@ void CFArrayAppendArray(CFMutableArrayRef array, CFArrayRef otherArray, CFRange
     __CFGenericValidateType(otherArray, __kCFArrayTypeID);
     CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
     __CFArrayValidateRange(otherArray, otherRange, __PRETTY_FUNCTION__);
+    CHECK_FOR_MUTATION(array);
     for (idx = otherRange.location; idx < otherRange.location + otherRange.length; idx++) {
        CFArrayAppendValue(array, CFArrayGetValueAtIndex(otherArray, idx));
     }
 }
+
+// ----====---- ----====---- ----====---- ----====----
+
+__private_extern__ Boolean __CFArray6130(CFMutableArrayRef array, CFIndex *p, void **list) {
+    if (CF_IS_OBJC(__kCFArrayTypeID, array)) return false;
+    CHECK_FOR_MUTATION(array);
+    if (__kCFArrayStorage == __CFArrayGetType(array)) {
+       CFStorageRef store = (CFStorageRef)array->_store;
+        CFRange range = {0, 0};
+        void *bytes = NULL;
+       for (CFIndex idx = 0; idx < __CFArrayGetCount(array); idx++) {
+            if (range.location + range.length - 1 < idx) {
+               bytes = CFStorageGetValueAtIndex(store, idx, &range);
+            }
+           ((void **)bytes)[idx - range.location] = list[p[idx]];
+       }
+    } else if (kCFUseCollectableAllocator) {        // Deque
+       struct __CFArrayDeque *deque = (struct __CFArrayDeque *)array->_store;
+       struct __CFArrayBucket *raw_buckets = (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque)) + deque->_leftIdx;
+       for (CFIndex idx = 0; idx < __CFArrayGetCount(array); idx++) {
+           struct __CFArrayBucket *dest = raw_buckets + idx;
+           objc_memmove_collectable(dest, list + p[idx], sizeof(struct __CFArrayBucket));
+       }
+    } else {        // Deque
+       struct __CFArrayDeque *deque = (struct __CFArrayDeque *)array->_store;
+       struct __CFArrayBucket *raw_buckets = (struct __CFArrayBucket *)((uint8_t *)deque + sizeof(struct __CFArrayDeque)) + deque->_leftIdx;
+       for (CFIndex idx = 0; idx < __CFArrayGetCount(array); idx++) {
+           raw_buckets[idx]._item = list[p[idx]];
+       }
+    }
+    return true;
+}
+
index 1e68a76140135b2c7ffbcc8d183890d0555453d4..7118d04ce12a85cbebb80f6181fcaee53c9b2190 100644 (file)
--- a/CFArray.h
+++ b/CFArray.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFArray.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 /*!
diff --git a/CFBag.c b/CFBag.c
index d4a63fae097393f0331cf5a7a5507e8bec96a733..4c4019eca69af36939f16c76bab2de6dc8d07385 100644 (file)
--- a/CFBag.c
+++ b/CFBag.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBag.c
-       Copyright 1998-2006, Apple, Inc. All rights reserved.
+       Copyright 1998-2008, Apple, Inc. All rights reserved.
        Responsibility: Christopher Kane
-        Machine generated from Notes/HashingCode.template
+       Machine generated from Notes/HashingCode.template
 */
 
 
 
 
+
 #include <CoreFoundation/CFBag.h>
 #include "CFInternal.h"
-#include <mach-o/dyld.h>
+#include "CFBasicHash.h"
+#include <CoreFoundation/CFString.h>
 
 #define CFDictionary 0
 #define CFSet 0
@@ -48,7 +50,8 @@ static const CFBagValueCallBacks __kCFNullBagValueCallBacks = {0, NULL, NULL, NU
 
 #define CFHashRef CFDictionaryRef
 #define CFMutableHashRef CFMutableDictionaryRef
-#define __kCFHashTypeID __kCFDictionaryTypeID
+#define CFHashKeyCallBacks CFBagKeyCallBacks
+#define CFHashValueCallBacks CFBagValueCallBacks
 #endif
 
 #if CFSet
@@ -65,7 +68,8 @@ static const CFBagCallBacks __kCFNullBagCallBacks = {0, NULL, NULL, NULL, NULL,
 
 #define CFHashRef CFSetRef
 #define CFMutableHashRef CFMutableSetRef
-#define __kCFHashTypeID __kCFSetTypeID
+#define CFHashKeyCallBacks CFBagCallBacks
+#define CFHashValueCallBacks CFBagCallBacks
 #endif
 
 #if CFBag
@@ -82,566 +86,29 @@ static const CFBagCallBacks __kCFNullBagCallBacks = {0, NULL, NULL, NULL, NULL,
 
 #define CFHashRef CFBagRef
 #define CFMutableHashRef CFMutableBagRef
-#define __kCFHashTypeID __kCFBagTypeID
-#endif
-
-#define GETNEWKEY(newKey, oldKey) \
-        any_t (*kretain)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))__CFBagGetKeyCallBacks(hc)->retain \
-            : (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        any_t newKey = kretain ? (any_t)INVOKE_CALLBACK3(kretain, allocator, (any_t)key, hc->_context) : (any_t)oldKey
-
-#define RELEASEKEY(oldKey) \
-        void (*krelease)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (void (*)(CFAllocatorRef,any_t,any_pointer_t))__CFBagGetKeyCallBacks(hc)->release \
-            : (void (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        if (krelease) INVOKE_CALLBACK3(krelease, allocator, oldKey, hc->_context)
-        
-#if CFDictionary
-#define GETNEWVALUE(newValue) \
-        any_t (*vretain)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))__CFBagGetValueCallBacks(hc)->retain \
-            : (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        any_t newValue = vretain ? (any_t)INVOKE_CALLBACK3(vretain, allocator, (any_t)value, hc->_context) : (any_t)value
-
-#define RELEASEVALUE(oldValue) \
-    void (*vrelease)(CFAllocatorRef, any_t, any_pointer_t) = \
-      !hasBeenFinalized(hc) \
-        ? (void (*)(CFAllocatorRef,any_t,any_pointer_t))__CFBagGetValueCallBacks(hc)->release \
-        : (void (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-    if (vrelease) INVOKE_CALLBACK3(vrelease, allocator, oldValue, hc->_context)
-
+#define CFHashKeyCallBacks CFBagCallBacks
+#define CFHashValueCallBacks CFBagCallBacks
 #endif
 
-static void __CFBagHandleOutOfMemory(CFTypeRef obj, CFIndex numBytes) {
-    CFStringRef msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFBag failed"), numBytes);
-    CFBadErrorCallBack cb = _CFGetOutOfMemoryErrorCallBack();
-    if (NULL == cb || !cb(obj, CFSTR("NS/CFBag"), msg)) {
-        CFLog(kCFLogLevelCritical, CFSTR("%@"), msg);
-       HALT;
-    }
-    CFRelease(msg);
-}
-
-
-// Max load is 3/4 number of buckets
-CF_INLINE CFIndex __CFHashRoundUpCapacity(CFIndex capacity) {
-    return 3 * ((CFIndex)1 << (flsl((capacity - 1) / 3)));
-}
-
-// Returns next power of two higher than the capacity
-// threshold for the given input capacity.
-CF_INLINE CFIndex __CFHashNumBucketsForCapacity(CFIndex capacity) {
-    return 4 * ((CFIndex)1 << (flsl((capacity - 1) / 3)));
-}
-
-enum {                /* Bits 1-0 */
-    __kCFHashImmutable = 0,        /* unchangable and fixed capacity */
-    __kCFHashMutable = 1,                /* changeable and variable capacity */
-};
-
-enum {                /* Bits 5-4 (value), 3-2 (key) */
-    __kCFHashHasNullCallBacks = 0,
-    __kCFHashHasCFTypeCallBacks = 1,
-    __kCFHashHasCustomCallBacks = 3        /* callbacks are at end of header */
-};
-
-// Under GC, we fudge the key/value memory in two ways
-// First, if we had null callbacks or null for both retain/release, we use unscanned memory and get
-// standard 'dangling' references.
-// This means that if people were doing addValue:[xxx new] and never removing, well, that doesn't work
-//
-// Second, if we notice standard retain/release implementations we use scanned memory, and fudge the
-// standard callbacks to generally do nothing if the collection was allocated in GC memory. On special
-// CF objects, however, like those used for precious resources like video-card buffers, we do indeed
-// do CFRetain on input and CFRelease on output.  The tricky case is GC finalization; we need to remember
-// that we did the CFReleases so that subsequent collection operations, like removal, don't double CFRelease.
-// (In fact we don't really use CFRetain/CFRelease but go directly to the collector)
-//
-
-enum {
-    __kCFHashFinalized =         (1 << 7),
-    __kCFHashWeakKeys =          (1 << 8),
-    __kCFHashWeakValues =        (1 << 9)
-};
 
 typedef uintptr_t any_t;
 typedef const void * const_any_pointer_t;
 typedef void * any_pointer_t;
 
-struct __CFBag {
-    CFRuntimeBase _base;
-    CFIndex _count;             /* number of values */
-    CFIndex _bucketsNum;        /* number of buckets */
-    CFIndex _bucketsUsed;       /* number of used buckets */
-    CFIndex _bucketsCap;        /* maximum number of used buckets */
-    CFIndex _mutations;
-    CFIndex _deletes;
-    any_pointer_t _context;     /* private */
-    CFOptionFlags _xflags;
-    any_t _marker;
-    any_t *_keys;     /* can be NULL if not allocated yet */
-    any_t *_values;   /* can be NULL if not allocated yet */
-};
-
-/* Bits 1-0 of the _xflags are used for mutability variety */
-/* Bits 3-2 of the _xflags are used for key callback indicator bits */
-/* Bits 5-4 of the _xflags are used for value callback indicator bits */
-/* Bit 6 of the _xflags is special KVO actions bit */
-/* Bits 7,8,9 are GC use */
-
-CF_INLINE bool hasBeenFinalized(CFTypeRef collection) {
-    return __CFBitfieldGetValue(((const struct __CFBag *)collection)->_xflags, 7, 7) != 0;
-}
-
-CF_INLINE void markFinalized(CFTypeRef collection) {
-    __CFBitfieldSetValue(((struct __CFBag *)collection)->_xflags, 7, 7, 1);
-}
-
-
-CF_INLINE CFIndex __CFHashGetType(CFHashRef hc) {
-    return __CFBitfieldGetValue(hc->_xflags, 1, 0);
-}
-
-CF_INLINE CFIndex __CFBagGetSizeOfType(CFIndex t) {
-    CFIndex size = sizeof(struct __CFBag);
-    if (__CFBitfieldGetValue(t, 3, 2) == __kCFHashHasCustomCallBacks) {
-        size += sizeof(CFBagKeyCallBacks);
-    }
-    if (__CFBitfieldGetValue(t, 5, 4) == __kCFHashHasCustomCallBacks) {
-        size += sizeof(CFBagValueCallBacks);
-    }
-    return size;
-}
-
-CF_INLINE const CFBagKeyCallBacks *__CFBagGetKeyCallBacks(CFHashRef hc) {
-    CFBagKeyCallBacks *result = NULL;
-    switch (__CFBitfieldGetValue(hc->_xflags, 3, 2)) {
-    case __kCFHashHasNullCallBacks:
-        return &__kCFNullBagKeyCallBacks;
-    case __kCFHashHasCFTypeCallBacks:
-        return &kCFTypeBagKeyCallBacks;
-    case __kCFHashHasCustomCallBacks:
-        break;
-    }
-    result = (CFBagKeyCallBacks *)((uint8_t *)hc + sizeof(struct __CFBag));
-    return result;
-}
-
-CF_INLINE Boolean __CFBagKeyCallBacksMatchNull(const CFBagKeyCallBacks *c) {
-    return (NULL == c ||
-        (c->retain == __kCFNullBagKeyCallBacks.retain &&
-         c->release == __kCFNullBagKeyCallBacks.release &&
-         c->copyDescription == __kCFNullBagKeyCallBacks.copyDescription &&
-         c->equal == __kCFNullBagKeyCallBacks.equal &&
-         c->hash == __kCFNullBagKeyCallBacks.hash));
-}
-
-CF_INLINE Boolean __CFBagKeyCallBacksMatchCFType(const CFBagKeyCallBacks *c) {
-    return (&kCFTypeBagKeyCallBacks == c ||
-        (c->retain == kCFTypeBagKeyCallBacks.retain &&
-         c->release == kCFTypeBagKeyCallBacks.release &&
-         c->copyDescription == kCFTypeBagKeyCallBacks.copyDescription &&
-         c->equal == kCFTypeBagKeyCallBacks.equal &&
-         c->hash == kCFTypeBagKeyCallBacks.hash));
-}
-
-CF_INLINE const CFBagValueCallBacks *__CFBagGetValueCallBacks(CFHashRef hc) {
-    CFBagValueCallBacks *result = NULL;
-    switch (__CFBitfieldGetValue(hc->_xflags, 5, 4)) {
-    case __kCFHashHasNullCallBacks:
-        return &__kCFNullBagValueCallBacks;
-    case __kCFHashHasCFTypeCallBacks:
-        return &kCFTypeBagValueCallBacks;
-    case __kCFHashHasCustomCallBacks:
-        break;
-    }
-    if (__CFBitfieldGetValue(hc->_xflags, 3, 2) == __kCFHashHasCustomCallBacks) {
-        result = (CFBagValueCallBacks *)((uint8_t *)hc + sizeof(struct __CFBag) + sizeof(CFBagKeyCallBacks));
-    } else {
-        result = (CFBagValueCallBacks *)((uint8_t *)hc + sizeof(struct __CFBag));
-    }
-    return result;
-}
-
-CF_INLINE Boolean __CFBagValueCallBacksMatchNull(const CFBagValueCallBacks *c) {
-    return (NULL == c ||
-        (c->retain == __kCFNullBagValueCallBacks.retain &&
-         c->release == __kCFNullBagValueCallBacks.release &&
-         c->copyDescription == __kCFNullBagValueCallBacks.copyDescription &&
-         c->equal == __kCFNullBagValueCallBacks.equal));
-}
-
-CF_INLINE Boolean __CFBagValueCallBacksMatchCFType(const CFBagValueCallBacks *c) {
-    return (&kCFTypeBagValueCallBacks == c ||
-        (c->retain == kCFTypeBagValueCallBacks.retain &&
-         c->release == kCFTypeBagValueCallBacks.release &&
-         c->copyDescription == kCFTypeBagValueCallBacks.copyDescription &&
-         c->equal == kCFTypeBagValueCallBacks.equal));
-}
-
-CFIndex _CFBagGetKVOBit(CFHashRef hc) {
-    return __CFBitfieldGetValue(hc->_xflags, 6, 6);
-}
-
-void _CFBagSetKVOBit(CFHashRef hc, CFIndex bit) {
-    __CFBitfieldSetValue(((CFMutableHashRef)hc)->_xflags, 6, 6, ((uintptr_t)bit & 0x1));
-}
-
-CF_INLINE Boolean __CFBagShouldShrink(CFHashRef hc) {
-    return (__kCFHashMutable == __CFHashGetType(hc)) &&
-                !(CF_USING_COLLECTABLE_MEMORY && auto_zone_is_finalized(__CFCollectableZone, hc)) && /* GC:  don't shrink finalizing hcs! */
-                (hc->_bucketsNum < 4 * hc->_deletes || (256 <= hc->_bucketsCap && hc-> _bucketsUsed < 3 * hc->_bucketsCap / 16));
-}
-
-CF_INLINE CFIndex __CFHashGetOccurrenceCount(CFHashRef hc, CFIndex idx) {
-#if CFBag
-    return hc->_values[idx];
-#endif
-    return 1;
-}
-
-CF_INLINE Boolean __CFHashKeyIsValue(CFHashRef hc, any_t key) {
-    return (hc->_marker != key && ~hc->_marker != key) ? true : false;
-}
-
-CF_INLINE Boolean __CFHashKeyIsMagic(CFHashRef hc, any_t key) {
-    return (hc->_marker == key || ~hc->_marker == key) ? true : false;
-}
-
-
-#if !defined(CF_OBJC_KVO_WILLCHANGE)
-#define CF_OBJC_KVO_WILLCHANGE(obj, key)
-#define CF_OBJC_KVO_DIDCHANGE(obj, key)
-#endif
-
-CF_INLINE uintptr_t __CFBagScrambleHash(uintptr_t k) {
-#if 0
-    return k;
-#else
-#if __LP64__
-    uintptr_t a = 0x4368726973746F70ULL;
-    uintptr_t b = 0x686572204B616E65ULL;
-#else
-    uintptr_t a = 0x4B616E65UL;
-    uintptr_t b = 0x4B616E65UL;
-#endif
-    uintptr_t c = 1;
-    a += k;
-#if __LP64__
-    a -= b; a -= c; a ^= (c >> 43);
-    b -= c; b -= a; b ^= (a << 9);
-    c -= a; c -= b; c ^= (b >> 8);
-    a -= b; a -= c; a ^= (c >> 38);
-    b -= c; b -= a; b ^= (a << 23);
-    c -= a; c -= b; c ^= (b >> 5);
-    a -= b; a -= c; a ^= (c >> 35);
-    b -= c; b -= a; b ^= (a << 49);
-    c -= a; c -= b; c ^= (b >> 11);
-    a -= b; a -= c; a ^= (c >> 12);
-    b -= c; b -= a; b ^= (a << 18);
-    c -= a; c -= b; c ^= (b >> 22);
-#else
-    a -= b; a -= c; a ^= (c >> 13);
-    b -= c; b -= a; b ^= (a << 8);
-    c -= a; c -= b; c ^= (b >> 13);
-    a -= b; a -= c; a ^= (c >> 12);
-    b -= c; b -= a; b ^= (a << 16);
-    c -= a; c -= b; c ^= (b >> 5);
-    a -= b; a -= c; a ^= (c >> 3);
-    b -= c; b -= a; b ^= (a << 10);
-    c -= a; c -= b; c ^= (b >> 15);
-#endif
-    return c;
-#endif
-}
-
-static CFIndex __CFBagFindBuckets1a(CFHashRef hc, any_t key) {
-    CFHashCode keyHash = (CFHashCode)key;
-    keyHash = __CFBagScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            return kCFNotFound;
-        } else if (~marker == currKey) {        /* deleted */
-            /* do nothing */
-        } else if (currKey == key) {
-            return probe;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return kCFNotFound;
-        }
-    }
-}
-
-static CFIndex __CFBagFindBuckets1b(CFHashRef hc, any_t key) {
-    const CFBagKeyCallBacks *cb = __CFBagGetKeyCallBacks(hc);
-    CFHashCode keyHash = cb->hash ? (CFHashCode)INVOKE_CALLBACK2(((CFHashCode (*)(any_t, any_pointer_t))cb->hash), key, hc->_context) : (CFHashCode)key;
-    keyHash = __CFBagScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            return kCFNotFound;
-        } else if (~marker == currKey) {        /* deleted */
-            /* do nothing */
-        } else if (currKey == key || (cb->equal && INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))cb->equal, currKey, key, hc->_context))) {
-            return probe;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return kCFNotFound;
-        }
-    }
-}
-
-CF_INLINE CFIndex __CFBagFindBuckets1(CFHashRef hc, any_t key) {
-    if (__kCFHashHasNullCallBacks == __CFBitfieldGetValue(hc->_xflags, 3, 2)) {
-        return __CFBagFindBuckets1a(hc, key);
-    }
-    return __CFBagFindBuckets1b(hc, key);
-}
-
-static void __CFBagFindBuckets2(CFHashRef hc, any_t key, CFIndex *match, CFIndex *nomatch) {
-    const CFBagKeyCallBacks *cb = __CFBagGetKeyCallBacks(hc);
-    CFHashCode keyHash = cb->hash ? (CFHashCode)INVOKE_CALLBACK2(((CFHashCode (*)(any_t, any_pointer_t))cb->hash), key, hc->_context) : (CFHashCode)key;
-    keyHash = __CFBagScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    *match = kCFNotFound;
-    *nomatch = kCFNotFound;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            if (nomatch) *nomatch = probe;
-            return;
-        } else if (~marker == currKey) {        /* deleted */
-            if (nomatch) {
-                *nomatch = probe;
-                nomatch = NULL;
-            }
-        } else if (currKey == key || (cb->equal && INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))cb->equal, currKey, key, hc->_context))) {
-            *match = probe;
-            return;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return;
-        }
-    }
-}
-
-static void __CFBagFindNewMarker(CFHashRef hc) {
-    any_t *keys = hc->_keys;
-    any_t newMarker;
-    CFIndex idx, nbuckets;
-    Boolean hit;
-
-    nbuckets = hc->_bucketsNum;
-    newMarker = hc->_marker;
-    do {
-        newMarker--;
-        hit = false;
-        for (idx = 0; idx < nbuckets; idx++) {
-            if (newMarker == keys[idx] || ~newMarker == keys[idx]) {
-                hit = true;
-                break;
-            }
-        }
-    } while (hit);
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (hc->_marker == keys[idx]) {
-            keys[idx] = newMarker;
-        } else if (~hc->_marker == keys[idx]) {
-            keys[idx] = ~newMarker;
-        }
-    }
-    ((struct __CFBag *)hc)->_marker = newMarker;
-}
-
 static Boolean __CFBagEqual(CFTypeRef cf1, CFTypeRef cf2) {
-    CFHashRef hc1 = (CFHashRef)cf1;
-    CFHashRef hc2 = (CFHashRef)cf2;
-    const CFBagKeyCallBacks *cb1, *cb2;
-    const CFBagValueCallBacks *vcb1, *vcb2;
-    any_t *keys;
-    CFIndex idx, nbuckets;
-    if (hc1 == hc2) return true;
-    if (hc1->_count != hc2->_count) return false;
-    cb1 = __CFBagGetKeyCallBacks(hc1);
-    cb2 = __CFBagGetKeyCallBacks(hc2);
-    if (cb1->equal != cb2->equal) return false;
-    vcb1 = __CFBagGetValueCallBacks(hc1);
-    vcb2 = __CFBagGetValueCallBacks(hc2);
-    if (vcb1->equal != vcb2->equal) return false;
-    if (0 == hc1->_bucketsUsed) return true; /* after function comparison! */
-    keys = hc1->_keys;
-    nbuckets = hc1->_bucketsNum;
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (hc1->_marker != keys[idx] && ~hc1->_marker != keys[idx]) {
-#if CFDictionary
-            const_any_pointer_t value;
-            if (!CFBagGetValueIfPresent(hc2, (any_pointer_t)keys[idx], &value)) return false;
-           if (hc1->_values[idx] != (any_t)value) {
-               if (NULL == vcb1->equal) return false;
-               if (!INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))vcb1->equal, hc1->_values[idx], (any_t)value, hc1->_context)) return false;
-            }
-#endif
-#if  CFSet
-            const_any_pointer_t value;
-            if (!CFBagGetValueIfPresent(hc2, (any_pointer_t)keys[idx], &value)) return false;
-#endif
-#if CFBag
-            if (hc1->_values[idx] != CFBagGetCountOfValue(hc2, (any_pointer_t)keys[idx])) return false;
-#endif
-        }
-    }
-    return true;
+    return __CFBasicHashEqual((CFBasicHashRef)cf1, (CFBasicHashRef)cf2);
 }
 
 static CFHashCode __CFBagHash(CFTypeRef cf) {
-    CFHashRef hc = (CFHashRef)cf;
-    return hc->_count;
+    return __CFBasicHashHash((CFBasicHashRef)cf);
 }
 
 static CFStringRef __CFBagCopyDescription(CFTypeRef cf) {
-    CFHashRef hc = (CFHashRef)cf;
-    CFAllocatorRef allocator;
-    const CFBagKeyCallBacks *cb;
-    const CFBagValueCallBacks *vcb;
-    any_t *keys;
-    CFIndex idx, nbuckets;
-    CFMutableStringRef result;
-    cb = __CFBagGetKeyCallBacks(hc);
-    vcb = __CFBagGetValueCallBacks(hc);
-    keys = hc->_keys;
-    nbuckets = hc->_bucketsNum;
-    allocator = CFGetAllocator(hc);
-    result = CFStringCreateMutable(allocator, 0);
-    const char *type = "?";
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashImmutable: type = "immutable"; break;
-    case __kCFHashMutable: type = "mutable"; break;
-    }
-    CFStringAppendFormat(result, NULL, CFSTR("<CFBag %p [%p]>{type = %s, count = %u, capacity = %u, pairs = (\n"), cf, allocator, type, hc->_count, hc->_bucketsCap);
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            CFStringRef kDesc = NULL, vDesc = NULL;
-            if (NULL != cb->copyDescription) {
-                kDesc = (CFStringRef)INVOKE_CALLBACK2(((CFStringRef (*)(any_t, any_pointer_t))cb->copyDescription), keys[idx], hc->_context);
-            }
-            if (NULL != vcb->copyDescription) {
-                vDesc = (CFStringRef)INVOKE_CALLBACK2(((CFStringRef (*)(any_t, any_pointer_t))vcb->copyDescription), hc->_values[idx], hc->_context);
-            }
-#if CFDictionary
-            if (NULL != kDesc && NULL != vDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ = %@\n"), idx, kDesc, vDesc);
-                CFRelease(kDesc);
-                CFRelease(vDesc);
-            } else if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ = <%p>\n"), idx, kDesc, hc->_values[idx]);
-                CFRelease(kDesc);
-            } else if (NULL != vDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> = %@\n"), idx, keys[idx], vDesc);
-                CFRelease(vDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> = <%p>\n"), idx, keys[idx], hc->_values[idx]);
-            }
-#endif
-#if CFSet
-            if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@\n"), idx, kDesc);
-                CFRelease(kDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, keys[idx]);
-            }
-#endif
-#if CFBag
-            if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ (%ld)\n"), idx, kDesc, hc->_values[idx]);
-                CFRelease(kDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> (%ld)\n"), idx, keys[idx], hc->_values[idx]);
-            }
-#endif
-        }
-    }
-    CFStringAppend(result, CFSTR(")}"));
-    return result;
+    return __CFBasicHashCopyDescription((CFBasicHashRef)cf);
 }
 
 static void __CFBagDeallocate(CFTypeRef cf) {
-    CFMutableHashRef hc = (CFMutableHashRef)cf;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    const CFBagKeyCallBacks *cb = __CFBagGetKeyCallBacks(hc);
-    const CFBagValueCallBacks *vcb = __CFBagGetValueCallBacks(hc);
-
-    // mark now in case any callout somehow tries to add an entry back in
-    markFinalized(cf);
-    if (vcb->release || cb->release) {
-        any_t *keys = hc->_keys;
-        CFIndex idx, nbuckets = hc->_bucketsNum;
-        for (idx = 0; idx < nbuckets; idx++) {
-            any_t oldkey = keys[idx];
-            if (hc->_marker != oldkey && ~hc->_marker != oldkey) {
-                if (vcb->release) {
-                    INVOKE_CALLBACK3(((void (*)(CFAllocatorRef, any_t, any_pointer_t))vcb->release), allocator, hc->_values[idx], hc->_context);
-                }
-                if (cb->release) {
-                    INVOKE_CALLBACK3(((void (*)(CFAllocatorRef, any_t, any_pointer_t))cb->release), allocator, oldkey, hc->_context);
-                }
-            }
-        }
-    }
-
-    if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-        // return early so that contents are preserved after finalization
-        return;
-    }
-    
-    _CFAllocatorDeallocateGC(allocator, hc->_keys);
-#if CFDictionary || CFBag
-    _CFAllocatorDeallocateGC(allocator, hc->_values);
-#endif
-    hc->_keys = NULL;
-    hc->_values = NULL;
-    hc->_count = 0;  // GC: also zero count, so the hc will appear empty.
-    hc->_bucketsUsed = 0;
-    hc->_bucketsNum = 0;
+    __CFBasicHashDeallocate((CFBasicHashRef)cf);
 }
 
 static CFTypeID __kCFBagTypeID = _kCFRuntimeNotATypeID;
@@ -658,123 +125,183 @@ static const CFRuntimeClass __CFBagClass = {
     __CFBagCopyDescription
 };
 
-__private_extern__ void __CFBagInitialize(void) {
-    __kCFHashTypeID = _CFRuntimeRegisterClass(&__CFBagClass);
-}
-
 CFTypeID CFBagGetTypeID(void) {
-    return __kCFHashTypeID;
+    if (_kCFRuntimeNotATypeID == __kCFBagTypeID) __kCFBagTypeID = _CFRuntimeRegisterClass(&__CFBagClass);
+    return __kCFBagTypeID;
 }
 
-static CFMutableHashRef __CFBagInit(CFAllocatorRef allocator, CFOptionFlags flags, CFIndex capacity, const CFBagKeyCallBacks *keyCallBacks
-#if CFDictionary
-, const CFBagValueCallBacks *valueCallBacks
-#endif
-) {
-    struct __CFBag *hc;
-    CFIndex size;
-    __CFBitfieldSetValue(flags, 31, 2, 0);
-    CFOptionFlags xflags = 0;
+static uintptr_t __CFBagCallback(CFBasicHashRef ht, uint8_t op, uintptr_t a1, uintptr_t a2, CFBasicHashCallbacks *cb) {
+    switch (op) {
+    case kCFBasicHashCallbackOpCopyCallbacks: {
+        CFBasicHashCallbacks *newcb = NULL;
+        if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
+            newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
+        } else {
+            newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate((CFAllocatorRef)a1, 10 * sizeof(void *), 0);
+        }
+        if (!newcb) HALT;
+        memmove(newcb, (void *)cb, 10 * sizeof(void *));
+        return (uintptr_t)newcb;
+    }
+    case kCFBasicHashCallbackOpFreeCallbacks: {
+        if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
+           auto_zone_release(auto_zone(), cb);
+       } else {
+            CFAllocatorDeallocate((CFAllocatorRef)a1, cb);
+        }
+        return 0;
+    }
+    case kCFBasicHashCallbackOpRetainValue: {
+        const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0];
+        if (NULL == value_retain) return a1;
+        return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpRetainKey: {
+        const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1];
+        if (NULL == key_retain) return a1;
+        return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpReleaseValue: {
+        void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2];
+        if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
+        return 0;
+    }
+    case kCFBasicHashCallbackOpReleaseKey: {
+        void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3];
+        if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
+        return 0;
+    }
+    case kCFBasicHashCallbackOpValueEqual: {
+        Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4];
+        if (NULL == value_equal) return (a1 == a2);
+        return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
+    }
+    case kCFBasicHashCallbackOpKeyEqual: {
+        Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5];
+        if (NULL == key_equal) return (a1 == a2);
+        return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
+    }
+    case kCFBasicHashCallbackOpHashKey: {
+        CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6];
+        if (NULL == hash) return a1;
+        return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpDescribeValue: {
+        CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[7];
+        if (NULL == value_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
+        return (uintptr_t)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpDescribeKey: {
+        CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8];
+        if (NULL == key_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
+        return (uintptr_t)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t)a1);
+    }
+    }
+    return 0;
+}
+
+static CFBasicHashRef __CFBagCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
+
+    CFBasicHashCallbacks *cb = NULL;
+    CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
+    flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
+
+    const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    Boolean std_cb = false;
+    if ((NULL == keyCallBacks || (keyCallBacks && 0 == memcmp(&__kCFNullBagKeyCallBacks, keyCallBacks, sizeof(__kCFNullBagKeyCallBacks))))
+                && (!useValueCB || (NULL == valueCallBacks || (valueCallBacks && 0 == memcmp(&__kCFNullBagValueCallBacks, valueCallBacks, sizeof(__kCFNullBagValueCallBacks)))))) {
+        cb = (CFBasicHashCallbacks *)& CFBasicHashNullCallbacks;
+    } else if ((&kCFTypeBagKeyCallBacks == keyCallBacks || (keyCallBacks && 0 == memcmp(&kCFTypeBagKeyCallBacks, keyCallBacks, sizeof(kCFTypeBagKeyCallBacks))))
+                && (!useValueCB || (&kCFTypeBagValueCallBacks == valueCallBacks || (valueCallBacks && 0 == memcmp(&kCFTypeBagValueCallBacks, valueCallBacks, sizeof(kCFTypeBagValueCallBacks)))))) {
+        std_cb = true;
+        cb = (CFBasicHashCallbacks *)& CFBasicHashStandardCallbacks;
+    } else {
+        Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
+        Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
+        CFStringRef (*key_describe)(const_any_pointer_t) = NULL;
+        CFStringRef (*value_describe)(const_any_pointer_t) = NULL;
+        CFHashCode (*hash_key)(const_any_pointer_t) = NULL;
+        key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
+        key_release = keyCallBacks ? keyCallBacks->release : NULL;
+        key_equal = keyCallBacks ? keyCallBacks->equal : NULL;
+        key_describe = keyCallBacks ? keyCallBacks->copyDescription : NULL;
+        if (useValueCB) {
+            value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
+            value_release = valueCallBacks ? valueCallBacks->release : NULL;
+            value_equal = valueCallBacks ? valueCallBacks->equal : NULL;
+            value_describe = valueCallBacks ? valueCallBacks->copyDescription : NULL;
+        } else {
+            value_retain = key_retain;
+            value_release = key_release;
+            value_equal = key_equal;
+            value_describe = key_describe;
+        }
+        hash_key = keyCallBacks ? keyCallBacks->hash : NULL;
+        FAULT_CALLBACK((void **)&key_retain);
+        FAULT_CALLBACK((void **)&key_release);
+        FAULT_CALLBACK((void **)&value_retain);
+        FAULT_CALLBACK((void **)&value_release);
+        FAULT_CALLBACK((void **)&key_equal);
+        FAULT_CALLBACK((void **)&value_equal);
+        FAULT_CALLBACK((void **)&key_describe);
+        FAULT_CALLBACK((void **)&value_describe);
+        FAULT_CALLBACK((void **)&hash_key);
+
+        CFBasicHashCallbacks *newcb = NULL;
+        if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+            newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
+        } else {
+            newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, 10 * sizeof(void *), 0);
+        }
+        if (!newcb) HALT;
+        newcb->func = (CFBasicHashCallbackType)__CFBagCallback;
+        newcb->context[0] = (uintptr_t)value_retain;
+        newcb->context[1] = (uintptr_t)key_retain;
+        newcb->context[2] = (uintptr_t)value_release;
+        newcb->context[3] = (uintptr_t)key_release;
+        newcb->context[4] = (uintptr_t)value_equal;
+        newcb->context[5] = (uintptr_t)key_equal;
+        newcb->context[6] = (uintptr_t)hash_key;
+        newcb->context[7] = (uintptr_t)value_describe;
+        newcb->context[8] = (uintptr_t)key_describe;
+        cb = newcb;
+    }
+
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-        // preserve NULL for key or value CB, otherwise fix up.
-        if (!keyCallBacks || (keyCallBacks->retain == NULL && keyCallBacks->release == NULL)) {
-            xflags = __kCFHashWeakKeys;
+        if (std_cb || value_retain != NULL || value_release != NULL) {
+            flags |= kCFBasicHashStrongValues;
         }
-#if CFDictionary
-        if (!valueCallBacks || (valueCallBacks->retain == NULL && valueCallBacks->release == NULL)) {
-            xflags |= __kCFHashWeakValues;
+        if (std_cb || key_retain != NULL || key_release != NULL) {
+            flags |= kCFBasicHashStrongKeys;
         }
-#endif
-#if CFBag
-        xflags |= __kCFHashWeakValues;
-#endif
-    }
-    if (__CFBagKeyCallBacksMatchNull(keyCallBacks)) {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasNullCallBacks);
-    } else if (__CFBagKeyCallBacksMatchCFType(keyCallBacks)) {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasCFTypeCallBacks);
-    } else {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasCustomCallBacks);
-    }
-#if CFDictionary
-    if (__CFBagValueCallBacksMatchNull(valueCallBacks)) {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasNullCallBacks);
-    } else if (__CFBagValueCallBacksMatchCFType(valueCallBacks)) {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasCFTypeCallBacks);
-    } else {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasCustomCallBacks);
-    }
-#endif
-    size = __CFBagGetSizeOfType(flags) - sizeof(CFRuntimeBase);
-    hc = (struct __CFBag *)_CFRuntimeCreateInstance(allocator, __kCFHashTypeID, size, NULL);
-    if (NULL == hc) {
-        return NULL;
     }
-    hc->_count = 0;
-    hc->_bucketsUsed = 0;
-    hc->_marker = (any_t)0xa1b1c1d3;
-    hc->_context = NULL;
-    hc->_deletes = 0;
-    hc->_mutations = 1;
-    hc->_xflags = xflags | flags;
-    switch (__CFBitfieldGetValue(flags, 1, 0)) {
-    case __kCFHashImmutable:
-        if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFBag (immutable)");
-        break;
-    case __kCFHashMutable:
-        if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFBag (mutable-variable)");
-        break;
-    }
-    hc->_bucketsCap = __CFHashRoundUpCapacity(1);
-    hc->_bucketsNum = 0;
-    hc->_keys = NULL;
-    hc->_values = NULL;
-    if (__kCFHashHasCustomCallBacks == __CFBitfieldGetValue(flags, 3, 2)) {
-        CFBagKeyCallBacks *cb = (CFBagKeyCallBacks *)__CFBagGetKeyCallBacks((CFHashRef)hc);
-        *cb = *keyCallBacks;
-        FAULT_CALLBACK((void **)&(cb->retain));
-        FAULT_CALLBACK((void **)&(cb->release));
-        FAULT_CALLBACK((void **)&(cb->copyDescription));
-        FAULT_CALLBACK((void **)&(cb->equal));
-        FAULT_CALLBACK((void **)&(cb->hash));
-    }
-#if CFDictionary
-    if (__kCFHashHasCustomCallBacks == __CFBitfieldGetValue(flags, 5, 4)) {
-        CFBagValueCallBacks *vcb = (CFBagValueCallBacks *)__CFBagGetValueCallBacks((CFHashRef)hc);
-        *vcb = *valueCallBacks;
-        FAULT_CALLBACK((void **)&(vcb->retain));
-        FAULT_CALLBACK((void **)&(vcb->release));
-        FAULT_CALLBACK((void **)&(vcb->copyDescription));
-        FAULT_CALLBACK((void **)&(vcb->equal));
-    }
-#endif
-    return hc;
+
+    return CFBasicHashCreate(allocator, flags, cb);
 }
 
 #if CFDictionary
-CFHashRef CFBagCreate(CFAllocatorRef allocator, const_any_pointer_t *keys, const_any_pointer_t *values, CFIndex numValues, const CFBagKeyCallBacks *keyCallBacks, const CFBagValueCallBacks *valueCallBacks) {
+CFHashRef CFBagCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFBagKeyCallBacks *keyCallBacks, const CFBagValueCallBacks *valueCallBacks) {
 #endif
 #if CFSet || CFBag
-CFHashRef CFBagCreate(CFAllocatorRef allocator, const_any_pointer_t *keys, CFIndex numValues, const CFBagKeyCallBacks *keyCallBacks) {
+CFHashRef CFBagCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFBagKeyCallBacks *keyCallBacks) {
+    const_any_pointer_t *vlist = klist;
+    const CFBagValueCallBacks *valueCallBacks = 0;
 #endif
+    CFTypeID typeID = CFBagGetTypeID();
     CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
-#if CFDictionary
-    CFMutableHashRef hc = __CFBagInit(allocator, __kCFHashImmutable, numValues, keyCallBacks, valueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFBagInit(allocator, __kCFHashImmutable, numValues, keyCallBacks);
-#endif
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashMutable);
+    CFBasicHashRef ht = __CFBagCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+    if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
     for (CFIndex idx = 0; idx < numValues; idx++) {
-#if CFDictionary
-        CFBagAddValue(hc, keys[idx], values[idx]);
-#endif
-#if CFSet || CFBag
-        CFBagAddValue(hc, keys[idx]);
-#endif
+        CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
     }
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    return (CFHashRef)hc;
+    CFBasicHashMakeImmutable(ht);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)");
+    return (CFHashRef)ht;
 }
 
 #if CFDictionary
@@ -782,158 +309,90 @@ CFMutableHashRef CFBagCreateMutable(CFAllocatorRef allocator, CFIndex capacity,
 #endif
 #if CFSet || CFBag
 CFMutableHashRef CFBagCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFBagKeyCallBacks *keyCallBacks) {
+    const CFBagValueCallBacks *valueCallBacks = 0;
 #endif
+    CFTypeID typeID = CFBagGetTypeID();
     CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
-#if CFDictionary
-    CFMutableHashRef hc = __CFBagInit(allocator, __kCFHashMutable, capacity, keyCallBacks, valueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFBagInit(allocator, __kCFHashMutable, capacity, keyCallBacks);
-#endif
-    return hc;
+    CFBasicHashRef ht = __CFBagCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (mutable)");
+    return (CFMutableHashRef)ht;
 }
 
-#if CFDictionary || CFSet
-// does not have Add semantics for Bag; it has Set semantics ... is that best?
-static void __CFBagGrow(CFMutableHashRef hc, CFIndex numNewValues);
-
-// This creates a hc which is for CFTypes or NSObjects, with a CFRetain style ownership transfer;
-// the hc does not take a retain (since it claims 1), and the caller does not need to release the inserted objects (since we do it).
-// The incoming objects must also be collectable if allocated out of a collectable allocator - and are neither released nor retained.
-#if CFDictionary
-CFHashRef _CFBagCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const_any_pointer_t *keys, const_any_pointer_t *values, CFIndex numValues) {
-#endif
-#if CFSet || CFBag
-CFHashRef _CFBagCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const_any_pointer_t *keys, CFIndex numValues) {
-#endif
-    CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
-#if CFDictionary
-    CFMutableHashRef hc = __CFBagInit(allocator, __kCFHashMutable, numValues, &kCFTypeBagKeyCallBacks, &kCFTypeBagValueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFBagInit(allocator, __kCFHashMutable, numValues, &kCFTypeBagKeyCallBacks);
-#endif
-    __CFBagGrow(hc, numValues);
-    for (CFIndex idx = 0; idx < numValues; idx++) {
-        CFIndex match, nomatch;
-        __CFBagFindBuckets2(hc, (any_t)keys[idx], &match, &nomatch);
-        if (kCFNotFound == match) {
-            CFAllocatorRef allocator = __CFGetAllocator(hc);
-            any_t newKey = (any_t)keys[idx];
-            if (__CFHashKeyIsMagic(hc, newKey)) {
-                __CFBagFindNewMarker(hc);
-            }
-            if (hc->_keys[nomatch] == ~hc->_marker) {
-                hc->_deletes--;
-            }
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-            any_t newValue = (any_t)values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-            hc->_values[nomatch] = 1;
-#endif
-            hc->_bucketsUsed++;
-            hc->_count++;
-        } else {
-            CFAllocatorRef allocator = __CFGetAllocator(hc);
+CFHashRef CFBagCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
+    CFTypeID typeID = CFBagGetTypeID();
+    CFAssert1(other, __kCFLogAssertion, "%s(): other CFBag cannot be NULL", __PRETTY_FUNCTION__);
+    __CFGenericValidateType(other, typeID);
+    CFBasicHashRef ht = NULL;
+    if (CF_IS_OBJC(typeID, other)) {
+        CFIndex numValues = CFBagGetCount(other);
+        const_any_pointer_t vbuffer[256], kbuffer[256];
+        const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
 #if CFSet || CFBag
-            any_t oldKey = hc->_keys[match];
-            any_t newKey = (any_t)keys[idx];
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-            if (__CFHashKeyIsMagic(hc, newKey)) {
-                __CFBagFindNewMarker(hc);
-            }
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-            RELEASEKEY(oldKey);
+        const_any_pointer_t *klist = vlist;
+        CFBagGetValues(other, vlist);
 #endif
 #if CFDictionary
-            any_t oldValue = hc->_values[match];
-            any_t newValue = (any_t)values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-            RELEASEVALUE(oldValue);
+        const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
+        CFDictionaryGetKeysAndValues(other, klist, vlist);
 #endif
+        ht = __CFBagCreateGeneric(allocator, & kCFTypeBagKeyCallBacks, CFDictionary ? & kCFTypeBagValueCallBacks : NULL, CFDictionary);
+        if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+        for (CFIndex idx = 0; idx < numValues; idx++) {
+            CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
         }
+        if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
+        if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
+    } else {
+        ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
     }
-    if (!isMutable) __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    return (CFHashRef)hc;
-}
-#endif
-
-CFHashRef CFBagCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
-    CFMutableHashRef hc = CFBagCreateMutableCopy(allocator, CFBagGetCount(other), other);
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFBag (immutable)");
-    return hc;
+    CFBasicHashMakeImmutable(ht);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)");
+    return (CFHashRef)ht;
 }
 
 CFMutableHashRef CFBagCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) {
-    CFIndex numValues = CFBagGetCount(other);
-    const_any_pointer_t *list, buffer[256];
-    list = (numValues <= 256) ? buffer : (const_any_pointer_t *)CFAllocatorAllocate(allocator, numValues * sizeof(const_any_pointer_t), 0);
-    if (list != buffer && __CFOASafe) __CFSetLastAllocationEventName(list, "CFBag (temp)");
-#if CFDictionary
-    const_any_pointer_t *vlist, vbuffer[256];
-    vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(allocator, numValues * sizeof(const_any_pointer_t), 0);
-    if (vlist != vbuffer && __CFOASafe) __CFSetLastAllocationEventName(vlist, "CFBag (temp)");
-#endif
+    CFTypeID typeID = CFBagGetTypeID();
+    CFAssert1(other, __kCFLogAssertion, "%s(): other CFBag cannot be NULL", __PRETTY_FUNCTION__);
+    __CFGenericValidateType(other, typeID);
+    CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
+    CFBasicHashRef ht = NULL;
+    if (CF_IS_OBJC(typeID, other)) {
+        CFIndex numValues = CFBagGetCount(other);
+        const_any_pointer_t vbuffer[256], kbuffer[256];
+        const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
 #if CFSet || CFBag
-    CFBagGetValues(other, list);
+        const_any_pointer_t *klist = vlist;
+        CFBagGetValues(other, vlist);
 #endif
 #if CFDictionary
-    CFBagGetKeysAndValues(other, list, vlist);
+        const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
+        CFDictionaryGetKeysAndValues(other, klist, vlist);
 #endif
-    const CFBagKeyCallBacks *kcb;
-    const CFBagValueCallBacks *vcb;
-    if (CF_IS_OBJC(__kCFHashTypeID, other)) {
-        kcb = &kCFTypeBagKeyCallBacks;
-        vcb = &kCFTypeBagValueCallBacks;
+        ht = __CFBagCreateGeneric(allocator, & kCFTypeBagKeyCallBacks, CFDictionary ? & kCFTypeBagValueCallBacks : NULL, CFDictionary);
+        if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+        for (CFIndex idx = 0; idx < numValues; idx++) {
+            CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
+        }
+        if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
+        if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
     } else {
-        kcb = __CFBagGetKeyCallBacks(other);
-        vcb = __CFBagGetValueCallBacks(other);
-    }
-#if CFDictionary
-    CFMutableHashRef hc = __CFBagInit(allocator, __kCFHashMutable, capacity, kcb, vcb);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFBagInit(allocator, __kCFHashMutable, capacity, kcb);
-#endif
-    if (0 == capacity) _CFBagSetCapacity(hc, numValues);
-    for (CFIndex idx = 0; idx < numValues; idx++) {
-#if CFDictionary
-        CFBagAddValue(hc, list[idx], vlist[idx]);
-#endif
-#if CFSet || CFBag
-        CFBagAddValue(hc, list[idx]);
-#endif
+        ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
     }
-    if (list != buffer) CFAllocatorDeallocate(allocator, list);
-#if CFDictionary
-    if (vlist != vbuffer) CFAllocatorDeallocate(allocator, vlist);
-#endif
-    return hc;
-}
-
-// Used by NSHashTables/NSMapTables and KVO
-void _CFBagSetContext(CFHashRef hc, any_pointer_t context) {
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    CF_WRITE_BARRIER_BASE_ASSIGN(__CFGetAllocator(hc), hc, hc->_context, context);
-}
-
-any_pointer_t _CFBagGetContext(CFHashRef hc) {
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    return hc->_context;
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (mutable)");
+    return (CFMutableHashRef)ht;
 }
 
 CFIndex CFBagGetCount(CFHashRef hc) {
-    if (CFDictionary || CFSet) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, CFIndex, hc, "count");
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    return hc->_count;
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFBagTypeID, CFIndex, hc, "count");
+    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFBagTypeID, CFIndex, hc, "count");
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    return CFBasicHashGetCount((CFBasicHashRef)hc);
 }
 
 #if CFDictionary
@@ -942,12 +401,10 @@ CFIndex CFBagGetCountOfKey(CFHashRef hc, const_any_pointer_t key) {
 #if CFSet || CFBag
 CFIndex CFBagGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    CFIndex match = __CFBagFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? __CFHashGetOccurrenceCount(hc, match) : 0);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, CFIndex, hc, "countForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, CFIndex, hc, "countForObject:", key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
 }
 
 #if CFDictionary
@@ -956,74 +413,66 @@ Boolean CFBagContainsKey(CFHashRef hc, const_any_pointer_t key) {
 #if CFSet || CFBag
 Boolean CFBagContainsValue(CFHashRef hc, const_any_pointer_t key) {
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFBagFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? true : false);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, char, hc, "containsKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, char, hc, "containsObject:", key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
 }
 
-#if CFDictionary
-CFIndex CFBagGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
-    CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForObject:", value);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    any_t *keys = hc->_keys;
-    Boolean (*equal)(any_t, any_t, any_pointer_t) = (Boolean (*)(any_t, any_t, any_pointer_t))__CFBagGetValueCallBacks(hc)->equal;
-    CFIndex cnt = 0;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            if ((hc->_values[idx] == (any_t)value) || (equal && INVOKE_CALLBACK3(equal, hc->_values[idx], (any_t)value, hc->_context))) {
-                cnt++;
-            }
-        }
-    }
-    return cnt;
+const_any_pointer_t CFBagGetValue(CFHashRef hc, const_any_pointer_t key) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, const_any_pointer_t, hc, "objectForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, const_any_pointer_t, hc, "member:", key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
 }
 
-Boolean CFBagContainsValue(CFHashRef hc, const_any_pointer_t value) {
-    CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsObject:", value);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    any_t *keys = hc->_keys;
-    Boolean (*equal)(any_t, any_t, any_pointer_t) = (Boolean (*)(any_t, any_t, any_pointer_t))__CFBagGetValueCallBacks(hc)->equal;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            if ((hc->_values[idx] == (any_t)value) || (equal && INVOKE_CALLBACK3(equal, hc->_values[idx], (any_t)value, hc->_context))) {
-                return true;
+Boolean CFBagGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, Boolean, hc, "_getValue:forKey:", (any_t *)value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, Boolean, hc, "_getValue:forObj:", (any_t *)value, key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    if (0 < bkt.count) {
+        if (value) {
+            if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongValues)) {
+                __CFAssignWithWriteBarrier((void **)value, (void *)bkt.weak_value);
+            } else {
+                *value = (const_any_pointer_t)bkt.weak_value;
             }
         }
+        return true;
     }
     return false;
 }
-#endif
 
-const_any_pointer_t CFBagGetValue(CFHashRef hc, const_any_pointer_t key) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, const_any_pointer_t, hc, "objectForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, const_any_pointer_t, hc, "member:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    CFIndex match = __CFBagFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? (const_any_pointer_t)(CFDictionary ? hc->_values[match] : hc->_keys[match]) : 0);
+#if CFDictionary
+CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
+    CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, CFIndex, hc, "countForObject:", value);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
 }
 
-Boolean CFBagGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "_getValue:forKey:", (any_t *)value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "_getValue:forObj:", (any_t *)value, key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFBagFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? ((value ? __CFObjCStrongAssign((const_any_pointer_t)(CFDictionary ? hc->_values[match] : hc->_keys[match]), value) : 0), true) : false);
+Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
+    CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, char, hc, "containsObject:", value);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
 }
 
-#if CFDictionary
-Boolean CFBagGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
-    CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFBagFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? ((actualkey ? __CFObjCStrongAssign((const_any_pointer_t)hc->_keys[match], actualkey) : NULL), true) : false);
+CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
+    CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    if (0 < bkt.count) {
+        if (actualkey) {
+            if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongKeys)) {
+                __CFAssignWithWriteBarrier((void **)actualkey, (void *)bkt.weak_key);
+            } else {
+                *actualkey = (const_any_pointer_t)bkt.weak_key;
+            }
+        }
+        return true;
+    }
+    return false;
 }
 #endif
 
@@ -1034,183 +483,113 @@ void CFBagGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_
 void CFBagGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
     const_any_pointer_t *valuebuf = 0;
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "getObjects:", (any_t *)keybuf);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (CF_USING_COLLECTABLE_MEMORY) {
-        // GC: speculatively issue a write-barrier on the copied to buffers
-        __CFObjCWriteBarrierRange(keybuf, hc->_count * sizeof(any_t));
-        __CFObjCWriteBarrierRange(valuebuf, hc->_count * sizeof(any_t));
-    }
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            for (CFIndex cnt = __CFHashGetOccurrenceCount(hc, idx); cnt--;) {
-                if (keybuf) *keybuf++ = (const_any_pointer_t)keys[idx];
-                if (valuebuf) *valuebuf++ = (const_any_pointer_t)hc->_values[idx];
-            }
-        }
-    }
-}
-
-#if CFDictionary || CFSet
-unsigned long _CFBagFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
-    /* copy as many as count items over */
-    if (0 == state->state) {        /* first time */
-        state->mutationsPtr = (unsigned long *)&hc->_mutations;
-    }
-    state->itemsPtr = (unsigned long *)stackbuffer;
-    CFIndex cnt = 0;
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = (CFIndex)state->state, nbuckets = hc->_bucketsNum; idx < nbuckets && cnt < (CFIndex)count; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            state->itemsPtr[cnt++] = (unsigned long)keys[idx];
-        }
-        state->state++;
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "getObjects:", (any_t *)keybuf);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    if (kCFUseCollectableAllocator) {
+        CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
+        __block const_any_pointer_t *keys = keybuf, *values = valuebuf;
+        CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
+                for (CFIndex cnt = bkt.count; cnt--;) {
+                    if (keybuf && (flags & kCFBasicHashStrongKeys)) { __CFAssignWithWriteBarrier((void **)keys, (void *)bkt.weak_key); keys++; }
+                    if (keybuf && !(flags & kCFBasicHashStrongKeys)) { *keys++ = (const_any_pointer_t)bkt.weak_key; }
+                    if (valuebuf && (flags & kCFBasicHashStrongValues)) { __CFAssignWithWriteBarrier((void **)values, (void *)bkt.weak_value); values++; }
+                    if (valuebuf && !(flags & kCFBasicHashStrongValues)) { *values++ = (const_any_pointer_t)bkt.weak_value; }
+                }
+                return (Boolean)true;
+            });
+    } else {
+        CFBasicHashGetElements((CFBasicHashRef)hc, CFBagGetCount(hc), (uintptr_t *)valuebuf, NULL, (uintptr_t *)keybuf, NULL);
     }
-    return cnt;
 }
-#endif
 
 void CFBagApplyFunction(CFHashRef hc, CFBagApplierFunction applier, any_pointer_t context) {
     FAULT_CALLBACK((void **)&(applier));
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_apply:context:", applier, context);
-    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_applyValues:context:", applier, context);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            for (CFIndex cnt = __CFHashGetOccurrenceCount(hc, idx); cnt--;) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "_apply:context:", applier, context);
+    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "_applyValues:context:", applier, context);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
 #if CFDictionary
-                INVOKE_CALLBACK3(applier, (const_any_pointer_t)keys[idx], (const_any_pointer_t)hc->_values[idx], context);
+            INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context);
 #endif
-#if CFSet || CFBag
-                INVOKE_CALLBACK2(applier, (const_any_pointer_t)keys[idx], context);
+#if CFSet
+            INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
 #endif
+#if CFBag
+            for (CFIndex cnt = bkt.count; cnt--;) {
+                INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
             }
-        }
-    }
+#endif
+            return (Boolean)true;
+        });
 }
 
-static void __CFBagGrow(CFMutableHashRef hc, CFIndex numNewValues) {
-    any_t *oldkeys = hc->_keys;
-    any_t *oldvalues = hc->_values;
-    CFIndex nbuckets = hc->_bucketsNum;
-    hc->_bucketsCap = __CFHashRoundUpCapacity(hc->_bucketsUsed + numNewValues);
-    hc->_bucketsNum = __CFHashNumBucketsForCapacity(hc->_bucketsCap);
-    hc->_deletes = 0;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    CFOptionFlags weakOrStrong = (hc->_xflags & __kCFHashWeakKeys) ? 0 : __kCFAllocatorGCScannedMemory;
-    any_t *mem = (any_t *)_CFAllocatorAllocateGC(allocator, hc->_bucketsNum * sizeof(any_t), weakOrStrong);
-    if (NULL == mem) __CFBagHandleOutOfMemory(hc, hc->_bucketsNum * sizeof(any_t));
-    if (__CFOASafe) __CFSetLastAllocationEventName(mem, "CFBag (key-store)");
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, hc, hc->_keys, mem);
-    CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;  // GC: avoids write-barrier in weak case.
-    any_t *keysBase = mem;
-#if CFDictionary || CFBag
-    weakOrStrong = (hc->_xflags & __kCFHashWeakValues) ? 0 : __kCFAllocatorGCScannedMemory;
-    mem = (any_t *)_CFAllocatorAllocateGC(allocator, hc->_bucketsNum * sizeof(any_t), weakOrStrong);
-    if (NULL == mem) __CFBagHandleOutOfMemory(hc, hc->_bucketsNum * sizeof(any_t));
-    if (__CFOASafe) __CFSetLastAllocationEventName(mem, "CFBag (value-store)");
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, hc, hc->_values, mem);
-#endif
-#if CFDictionary
-    CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator; // GC: avoids write-barrier in weak case.
-    any_t *valuesBase = mem;
-#endif
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        hc->_keys[idx] = hc->_marker;
-#if CFDictionary || CFBag
-        hc->_values[idx] = 0;
-#endif
-    }
-    if (NULL == oldkeys) return;
-    for (CFIndex idx = 0; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, oldkeys[idx])) {
-            CFIndex match, nomatch;
-            __CFBagFindBuckets2(hc, oldkeys[idx], &match, &nomatch);
-            CFAssert3(kCFNotFound == match, __kCFLogAssertion, "%s(): two values (%p, %p) now hash to the same slot; mutable value changed while in table or hash value is not immutable", __PRETTY_FUNCTION__, oldkeys[idx], hc->_keys[match]);
-            if (kCFNotFound != nomatch) {
-                CF_WRITE_BARRIER_BASE_ASSIGN(keysAllocator, keysBase, hc->_keys[nomatch], oldkeys[idx]);
-#if CFDictionary
-                CF_WRITE_BARRIER_BASE_ASSIGN(valuesAllocator, valuesBase, hc->_values[nomatch], oldvalues[idx]);
-#endif
-#if CFBag
-                hc->_values[nomatch] = oldvalues[idx];
-#endif
-            }
-        }
-    }
-    _CFAllocatorDeallocateGC(allocator, oldkeys);
-    _CFAllocatorDeallocateGC(allocator, oldvalues);
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT unsigned long _CFBagFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
+    if (CF_IS_OBJC(__kCFBagTypeID, hc)) return 0;
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count);
 }
 
 // This function is for Foundation's benefit; no one else should use it.
-void _CFBagSetCapacity(CFMutableHashRef hc, CFIndex cap) {
-    if (CF_IS_OBJC(__kCFHashTypeID, hc)) return;
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    CFAssert1(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): collection is immutable", __PRETTY_FUNCTION__);
-    CFAssert3(hc->_bucketsUsed <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than bucket count (%ld)", __PRETTY_FUNCTION__, cap, hc->_bucketsUsed);
-    __CFBagGrow(hc, cap - hc->_bucketsUsed);
+CF_EXPORT Boolean _CFBagIsMutable(CFHashRef hc) {
+    if (CF_IS_OBJC(__kCFBagTypeID, hc)) return false;
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    return CFBasicHashIsMutable((CFBasicHashRef)hc);
 }
 
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT void _CFBagSetCapacity(CFMutableHashRef hc, CFIndex cap) {
+    if (CF_IS_OBJC(__kCFBagTypeID, hc)) return;
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    CFAssert3(CFBagGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFBagGetCount(hc));
+    CFBasicHashSetCapacity((CFBasicHashRef)hc, cap);
+}
+
+CF_INLINE CFIndex __CFBagGetKVOBit(CFHashRef hc) {
+    return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0);
+}
+
+CF_INLINE void __CFBagSetKVOBit(CFHashRef hc, CFIndex bit) {
+    __CFBitfieldSetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0, ((uintptr_t)bit & 0x1));
+}
+
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT CFIndex _CFBagGetKVOBit(CFHashRef hc) {
+    return __CFBagGetKVOBit(hc);
+}
+
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT void _CFBagSetKVOBit(CFHashRef hc, CFIndex bit) {
+    __CFBagSetKVOBit(hc, bit);
+}
+
+
+#if !defined(CF_OBJC_KVO_WILLCHANGE)
+#define CF_OBJC_KVO_WILLCHANGE(obj, key)
+#define CF_OBJC_KVO_DIDCHANGE(obj, key)
+#define CF_OBJC_KVO_WILLCHANGEALL(obj)
+#define CF_OBJC_KVO_DIDCHANGEALL(obj)
+#endif
 
 #if CFDictionary
 void CFBagAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
 #endif
 #if CFSet || CFBag
 void CFBagAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
-#endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_addObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "addObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        if (hc->_bucketsUsed == hc->_bucketsCap || NULL == hc->_keys) {
-            __CFBagGrow(hc, 1);
-        }
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    CFIndex match, nomatch;
-    __CFBagFindBuckets2(hc, (any_t)key, &match, &nomatch);
-    if (kCFNotFound != match) {
-#if CFBag
-        CF_OBJC_KVO_WILLCHANGE(hc, hc->_keys[match]);
-        hc->_values[match]++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, hc->_keys[match]);
-#endif
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        GETNEWKEY(newKey, key);
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFBagFindNewMarker(hc);
-        }
-        if (hc->_keys[nomatch] == ~hc->_marker) {
-            hc->_deletes--;
-        }
-        CF_OBJC_KVO_WILLCHANGE(hc, key);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-        hc->_values[nomatch] = 1;
+    const_any_pointer_t value = key;
 #endif
-        hc->_bucketsUsed++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, key);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "addObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "addObject:", key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 #if CFDictionary
@@ -1218,51 +597,18 @@ void CFBagReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_p
 #endif
 #if CFSet || CFBag
 void CFBagReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
-#endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_replaceObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "_replaceObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFIndex match = __CFBagFindBuckets1(hc, (any_t)key);
-    if (kCFNotFound == match) return;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-#if CFSet || CFBag
-    GETNEWKEY(newKey, key);
-#endif
-#if CFDictionary
-    GETNEWVALUE(newValue);
+    const_any_pointer_t value = key;
 #endif
-    any_t oldKey = hc->_keys[match];
-    CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFSet || CFBag
-    CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-    CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-    if (__CFHashKeyIsMagic(hc, newKey)) {
-        __CFBagFindNewMarker(hc);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "replaceObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "replaceObject:", key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
-    CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-#endif
-#if CFDictionary
-    any_t oldValue = hc->_values[match];
-    CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-    CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-#endif
-    CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-#if CFSet || CFBag
-    RELEASEKEY(oldKey);
-#endif
-#if CFDictionary
-    RELEASEVALUE(oldValue);
-#endif
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 #if CFDictionary
@@ -1270,198 +616,49 @@ void CFBagSetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_point
 #endif
 #if CFSet || CFBag
 void CFBagSetValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
-#endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "setObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "_setObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        if (hc->_bucketsUsed == hc->_bucketsCap || NULL == hc->_keys) {
-            __CFBagGrow(hc, 1);
-        }
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    CFIndex match, nomatch;
-    __CFBagFindBuckets2(hc, (any_t)key, &match, &nomatch);
-    if (kCFNotFound == match) {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        GETNEWKEY(newKey, key);
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFBagFindNewMarker(hc);
-        }
-        if (hc->_keys[nomatch] == ~hc->_marker) {
-            hc->_deletes--;
-        }
-        CF_OBJC_KVO_WILLCHANGE(hc, key);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-        hc->_values[nomatch] = 1;
-#endif
-        hc->_bucketsUsed++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, key);
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-#if CFSet || CFBag
-        GETNEWKEY(newKey, key);
-#endif
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        any_t oldKey = hc->_keys[match];
-        CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFSet || CFBag
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFBagFindNewMarker(hc);
-        }
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-#endif
-#if CFDictionary
-        any_t oldValue = hc->_values[match];
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-#endif
-        CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-#if CFSet || CFBag
-        RELEASEKEY(oldKey);
-#endif
-#if CFDictionary
-        RELEASEVALUE(oldValue);
+    const_any_pointer_t value = key;
 #endif
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "setObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "_setObject:", key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+//#warning this for a dictionary used to not replace the key
+    CFBasicHashSetValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 void CFBagRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "removeObjectForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "removeObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFIndex match = __CFBagFindBuckets1(hc, (any_t)key);
-    if (kCFNotFound == match) return;
-    if (1 < __CFHashGetOccurrenceCount(hc, match)) {
-#if CFBag
-        CF_OBJC_KVO_WILLCHANGE(hc, hc->_keys[match]);
-        hc->_values[match]--;
-        hc->_count--;
-        CF_OBJC_KVO_DIDCHANGE(hc, hc->_keys[match]);
-#endif
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        any_t oldKey = hc->_keys[match];
-        CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-#if CFDictionary
-        any_t oldValue = hc->_values[match];
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], 0);
-#endif
-#if CFBag
-        hc->_values[match] = 0;
-#endif
-        hc->_count--;
-        hc->_bucketsUsed--;
-        hc->_deletes++;
-        CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-        RELEASEKEY(oldKey);
-#if CFDictionary
-        RELEASEVALUE(oldValue);
-#endif
-        if (__CFBagShouldShrink(hc)) {
-            __CFBagGrow(hc, 0);
-        } else {
-            // When the probeskip == 1 always and only, a DELETED slot followed by an EMPTY slot
-            // can be converted to an EMPTY slot.  By extension, a chain of DELETED slots followed
-            // by an EMPTY slot can be converted to EMPTY slots, which is what we do here.
-            if (match < hc->_bucketsNum - 1 && hc->_keys[match + 1] == hc->_marker) {
-                while (0 <= match && hc->_keys[match] == ~hc->_marker) {
-                    hc->_keys[match] = hc->_marker;
-                    hc->_deletes--;
-                    match--;
-                }
-            }
-        }
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "removeObjectForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "removeObject:", key);
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 void CFBagRemoveAllValues(CFMutableHashRef hc) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, void, hc, "removeAllObjects");
-    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, void, hc, "removeAllObjects");
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            any_t oldKey = keys[idx];
-            CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFDictionary || CFSet
-            hc->_count--;
-#endif
-#if CFBag
-            hc->_count -= hc->_values[idx];
-#endif
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[idx], ~hc->_marker);
-#if CFDictionary
-            any_t oldValue = hc->_values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[idx], 0);
-#endif
-#if CFBag
-            hc->_values[idx] = 0;
-#endif
-            hc->_bucketsUsed--;
-            hc->_deletes++;
-            CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-            RELEASEKEY(oldKey);
-#if CFDictionary
-            RELEASEVALUE(oldValue);
-#endif
-        }
-    }
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        keys[idx] = hc->_marker;
-    }
-    hc->_deletes = 0;
-    hc->_bucketsUsed = 0;
-    hc->_count = 0;
-    if (__CFBagShouldShrink(hc) && (256 <= hc->_bucketsCap)) {
-        __CFBagGrow(hc, 128);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFBagTypeID, void, hc, "removeAllObjects");
+    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFBagTypeID, void, hc, "removeAllObjects");
+    __CFGenericValidateType(hc, __kCFBagTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGEALL(hc);
+    CFBasicHashRemoveAllValues((CFBasicHashRef)hc);
+    CF_OBJC_KVO_DIDCHANGEALL(hc);
 }
 
 #undef CF_OBJC_KVO_WILLCHANGE
 #undef CF_OBJC_KVO_DIDCHANGE
+#undef CF_OBJC_KVO_WILLCHANGEALL
+#undef CF_OBJC_KVO_DIDCHANGEALL
 
diff --git a/CFBag.h b/CFBag.h
index ae5c276333feda1abe384d4d8171be8efe8364dd..54cfeb18135efe4a8ab0f6333a1b49bac7414aaf 100644 (file)
--- a/CFBag.h
+++ b/CFBag.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBag.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFBAG__)
index df5f2aff487543711ec5afb59232454047ec3c6e..068826a739552de07570753a1bfa9d4e0c7fdb37 100644 (file)
--- a/CFBase.c
+++ b/CFBase.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBase.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #include <CoreFoundation/CFBase.h>
 #include "CFInternal.h"
-#include <pthread.h>
-#include <malloc/malloc.h>
-extern size_t malloc_good_size(size_t size);
-#include <mach/mach.h>
-#include <dlfcn.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+    #include <pthread.h>
+#endif
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    #include <malloc/malloc.h>
+    extern size_t malloc_good_size(size_t size);
+    #include <mach/mach.h>
+    #include <dlfcn.h>
+#endif
 #include <stdlib.h>
 #include <string.h>
 
-#if defined(__CYGWIN32__) || defined (D__CYGWIN_)
-#error CoreFoundation is currently built with the Microsoft C Runtime, which is incompatible with the Cygwin DLL.  You must either use the -mno-cygwin flag, or complete a port of CF to the Cygwin environment.
-#endif
-
 // -------- -------- -------- -------- -------- -------- -------- --------
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 // CFAllocator structure must match struct _malloc_zone_t!
 // The first two reserved fields in struct _malloc_zone_t are for us with CFRuntimeBase
+#endif
+
+
 struct __CFAllocator {
+
+
     CFRuntimeBase _base;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     size_t (*size)(struct _malloc_zone_t *zone, const void *ptr); /* returns the size of a block or 0 if not in this zone; must be fast, especially for negative answers */
     void *(*malloc)(struct _malloc_zone_t *zone, size_t size);
     void *(*calloc)(struct _malloc_zone_t *zone, size_t num_items, size_t size); /* same as malloc, but block returned is set to zero */
@@ -57,6 +64,7 @@ struct __CFAllocator {
     void (*batch_free)(struct _malloc_zone_t *zone, void **to_be_freed, unsigned num_to_be_freed); /* frees all the pointers in to_be_freed; note that to_be_freed may be overwritten during the process */
     struct malloc_introspection_t      *introspect;
     void       *reserved5;
+#endif
     CFAllocatorRef _allocator;
     CFAllocatorContext _context;
 };
@@ -103,7 +111,7 @@ CF_INLINE CFAllocatorPreferredSizeCallBack __CFAllocatorGetPreferredSizeFunction
     return retval;
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 
 __private_extern__ void __CFAllocatorDeallocate(CFTypeRef cf);
 
@@ -241,7 +249,7 @@ static void __CFAllocatorSystemDeallocate(void *ptr, void *info) {
 
 #endif
 
-#if defined(__WIN32__) || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 static void *__CFAllocatorSystemAllocate(CFIndex size, CFOptionFlags hint, void *info) {
     return malloc(size);
 }
@@ -281,7 +289,7 @@ static void __CFAllocatorCPPFree(void *ptr, void *info)
 
 static struct __CFAllocator __kCFAllocatorMalloc = {
     INIT_CFRUNTIME_BASE(),
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     __CFAllocatorCustomSize,
     __CFAllocatorCustomMalloc,
     __CFAllocatorCustomCalloc,
@@ -308,7 +316,7 @@ static struct __CFAllocator __kCFAllocatorMalloc = {
 
 static struct __CFAllocator __kCFAllocatorMallocZone = {
     INIT_CFRUNTIME_BASE(),
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     __CFAllocatorCustomSize,
     __CFAllocatorCustomMalloc,
     __CFAllocatorCustomCalloc,
@@ -328,7 +336,7 @@ static struct __CFAllocator __kCFAllocatorMallocZone = {
 
 static struct __CFAllocator __kCFAllocatorSystemDefault = {
     INIT_CFRUNTIME_BASE(),
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     __CFAllocatorCustomSize,
     __CFAllocatorCustomMalloc,
     __CFAllocatorCustomCalloc,
@@ -348,7 +356,7 @@ static struct __CFAllocator __kCFAllocatorSystemDefault = {
 
 static struct __CFAllocator __kCFAllocatorNull = {
     INIT_CFRUNTIME_BASE(),
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     __CFAllocatorNullSize,
     __CFAllocatorNullMalloc,
     __CFAllocatorNullCalloc,
@@ -428,8 +436,8 @@ __private_extern__ void __CFAllocatorInitialize(void) {
 
     _CFRuntimeSetInstanceTypeID(&__kCFAllocatorSystemDefault, __kCFAllocatorTypeID);
     __kCFAllocatorSystemDefault._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
-#if DEPLOYMENT_TARGET_MACOSX
-    __kCFAllocatorSystemDefault._context.info = (CF_USING_COLLECTABLE_MEMORY ? __CFCollectableZone : malloc_default_zone());
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    __kCFAllocatorSystemDefault._context.info = (kCFUseCollectableAllocator ? auto_zone() : malloc_default_zone());
     memset(malloc_default_zone(), 0, 2 * sizeof(void *));
 #endif
     __kCFAllocatorSystemDefault._allocator = kCFAllocatorSystemDefault;
@@ -438,12 +446,12 @@ __private_extern__ void __CFAllocatorInitialize(void) {
     __kCFAllocatorMalloc._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
     __kCFAllocatorMalloc._allocator = kCFAllocatorSystemDefault;
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMallocZone, __kCFAllocatorTypeID);
     __kCFAllocatorMallocZone._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
     __kCFAllocatorMallocZone._allocator = kCFAllocatorSystemDefault;
     __kCFAllocatorMallocZone._context.info = malloc_default_zone();
-#endif //__MACH__
+#endif
 
     _CFRuntimeSetInstanceTypeID(&__kCFAllocatorNull, __kCFAllocatorTypeID);
     __kCFAllocatorNull._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
@@ -456,21 +464,17 @@ CFTypeID CFAllocatorGetTypeID(void) {
 }
 
 CFAllocatorRef CFAllocatorGetDefault(void) {
-    CFAllocatorRef allocator = (CFAllocatorRef)__CFGetThreadSpecificData_inline()->_allocator;
-    if (NULL == allocator) {
-       allocator = kCFAllocatorSystemDefault;
-    }
-    return allocator;
+    return __CFGetDefaultAllocator();
 }
 
 void CFAllocatorSetDefault(CFAllocatorRef allocator) {
-    CFAllocatorRef current = (CFAllocatorRef)__CFGetThreadSpecificData_inline()->_allocator;
+    CFAllocatorRef current = __CFGetDefaultAllocator();
 #if defined(DEBUG) 
     if (NULL != allocator) {
        __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
     }
 #endif
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {      // malloc_zone_t *
        return;         // require allocator to this function to be an allocator
     }
@@ -478,10 +482,15 @@ void CFAllocatorSetDefault(CFAllocatorRef allocator) {
     if (NULL != allocator && allocator != current) {
        if (current) CFRelease(current);
        CFRetain(allocator);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+       // extra retain not needed here, since we never attempt cleanup of this key
+        pthread_setspecific(__CFTSDKeyAllocator, allocator);
+#else
        // We retain an extra time so that anything set as the default
        // allocator never goes away.
        CFRetain(allocator);
        __CFGetThreadSpecificData_inline()->_allocator = (void *)allocator;
+#endif
     }
 }
 
@@ -490,7 +499,7 @@ static CFAllocatorRef __CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorC
     CFAllocatorRetainCallBack retainFunc;
     CFAllocatorAllocateCallBack allocateFunc;
     void *retainedInfo;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (allocator && kCFAllocatorUseContext != allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {       // malloc_zone_t *
        return NULL;    // require allocator to this function to be an allocator
     }
@@ -530,7 +539,7 @@ static CFAllocatorRef __CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorC
     memory->_base._cfinfo[CF_INFO_BITS] = 0;
     _CFRuntimeSetInstanceTypeID(memory, __kCFAllocatorTypeID);
     memory->_base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     memory->size = __CFAllocatorCustomSize;
     memory->malloc = __CFAllocatorCustomMalloc;
     memory->calloc = __CFAllocatorCustomCalloc;
@@ -564,15 +573,6 @@ static CFAllocatorRef __CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorC
 }
 
 CFAllocatorRef CFAllocatorCreate(CFAllocatorRef allocator, CFAllocatorContext *context) {
-    CFAssert1(!CF_USING_COLLECTABLE_MEMORY, __kCFLogAssertion, "%s(): Shouldn't be called when GC is enabled!", __PRETTY_FUNCTION__);
-#if defined(DEBUG)
-    if (CF_USING_COLLECTABLE_MEMORY)
-        HALT;
-#endif
-    return __CFAllocatorCreate(allocator, context);
-}
-
-CFAllocatorRef _CFAllocatorCreateGC(CFAllocatorRef allocator, CFAllocatorContext *context) {
     return __CFAllocatorCreate(allocator, context);
 }
 
@@ -580,7 +580,7 @@ void *CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags
     CFAllocatorAllocateCallBack allocateFunc;
     void *newptr = NULL;
     allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator;
-#if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
     if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
        __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
     }
@@ -588,7 +588,7 @@ void *CFAllocatorAllocate(CFAllocatorRef allocator, CFIndex size, CFOptionFlags
     __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
 #endif
     if (0 == size) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {   // malloc_zone_t *
        return malloc_zone_malloc((malloc_zone_t *)allocator, size);
     }
@@ -611,7 +611,7 @@ void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize
     CFAllocatorDeallocateCallBack deallocateFunc;
     void *newptr;
     allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator;
-#if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
     if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
        __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
     }
@@ -619,7 +619,7 @@ void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize
     __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
 #endif
     if (NULL == ptr && 0 < newsize) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {        // malloc_zone_t *
            return malloc_zone_malloc((malloc_zone_t *)allocator, newsize);
        }
@@ -632,7 +632,7 @@ void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize
        return newptr;
     }
     if (NULL != ptr && 0 == newsize) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {        // malloc_zone_t *
 #if defined(DEBUG)
            size_t size = malloc_size(ptr);
@@ -649,7 +649,7 @@ void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize
        return NULL;
     }
     if (NULL == ptr && 0 == newsize) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {   // malloc_zone_t *
        return malloc_zone_realloc((malloc_zone_t *)allocator, ptr, newsize);
     }
@@ -663,14 +663,14 @@ void *CFAllocatorReallocate(CFAllocatorRef allocator, void *ptr, CFIndex newsize
 void CFAllocatorDeallocate(CFAllocatorRef allocator, void *ptr) {
     CFAllocatorDeallocateCallBack deallocateFunc;
     allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator;
-#if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
     if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
        __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
     }
 #else
     __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
 #endif
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {   // malloc_zone_t *
 #if defined(DEBUG)
        size_t size = malloc_size(ptr);
@@ -689,14 +689,14 @@ CFIndex CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex siz
     CFAllocatorPreferredSizeCallBack prefFunc;
     CFIndex newsize = 0;
     allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator;
-#if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
     if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
        __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
     }
 #else
     __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
 #endif
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {   // malloc_zone_t *
        return malloc_good_size(size);
     }
@@ -711,7 +711,7 @@ CFIndex CFAllocatorGetPreferredSizeForSize(CFAllocatorRef allocator, CFIndex siz
 
 void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context) {
     allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator;
-#if (DEPLOYMENT_TARGET_MACOSX) && defined(DEBUG)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
     if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
        __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
     }
@@ -719,7 +719,7 @@ void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context
     __CFGenericValidateType(allocator, __kCFAllocatorTypeID);
 #endif
     CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) {   // malloc_zone_t *
        return;
     }
@@ -733,7 +733,7 @@ void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context
     context->reallocate = __CFAllocatorGetReallocateFunction(&allocator->_context);
     context->deallocate = __CFAllocatorGetDeallocateFunction(&allocator->_context);
     context->preferredSize = __CFAllocatorGetPreferredSizeFunction(&allocator->_context);
-#if (DEPLOYMENT_TARGET_MACOSX) && defined(__ppc__)
+#if DEPLOYMENT_TARGET_MACOSX && defined(__ppc__)
     context->retain = (void *)((uintptr_t)context->retain & ~0x3);
     context->release = (void *)((uintptr_t)context->release & ~0x3);
     context->copyDescription = (void *)((uintptr_t)context->copyDescription & ~0x3);
@@ -744,7 +744,7 @@ void CFAllocatorGetContext(CFAllocatorRef allocator, CFAllocatorContext *context
 #endif
 }
 
-void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint)
+__private_extern__ void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint)
 {
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator))
         return auto_zone_allocate_object((auto_zone_t*)kCFAllocatorSystemDefault->_context.info, size, CF_GET_GC_MEMORY_TYPE(hint), false, false);
@@ -752,7 +752,7 @@ void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFla
         return CFAllocatorAllocate(allocator, size, hint);
 }
 
-void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint)
+__private_extern__ void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint)
 {
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
        if (ptr && (newsize == 0)) {
@@ -766,7 +766,7 @@ void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex news
     return CFAllocatorReallocate(allocator, ptr, newsize, hint);
 }
 
-void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr)
+__private_extern__ void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr)
 {
     // when running GC, don't deallocate.
     if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, ptr);
@@ -774,50 +774,25 @@ void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr)
 
 // -------- -------- -------- -------- -------- -------- -------- --------
 
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-__private_extern__ pthread_key_t __CFTSDKey = (pthread_key_t)NULL;
-#endif
-#if 0
+#if DEPLOYMENT_TARGET_WINDOWS
 __private_extern__ DWORD __CFTSDKey = 0xFFFFFFFF;
 #endif
 
-extern void _CFRunLoop1(void);
+#if DEPLOYMENT_TARGET_WINDOWS
+extern void __CFStringEncodingICUThreadDataCleaner(void *);
 
 // Called for each thread as it exits
 __private_extern__ void __CFFinalizeThreadData(void *arg) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-    __CFThreadSpecificData *tsd = (__CFThreadSpecificData *)arg;
-#elif defined(__WIN32__)
     __CFThreadSpecificData *tsd = (__CFThreadSpecificData*)TlsGetValue(__CFTSDKey);
     TlsSetValue(__CFTSDKey, NULL);
-#endif
     if (NULL == tsd) return; 
     if (tsd->_allocator) CFRelease(tsd->_allocator);
-#if DEPLOYMENT_TARGET_MACOSX
-    _CFRunLoop1();
-#endif
-#if 0 || 0
-
     if (tsd->_messageHook) UnhookWindowsHookEx(tsd->_messageHook);
-
-#endif
-
+    if (tsd->_icuThreadData) __CFStringEncodingICUThreadDataCleaner(tsd->_icuThreadData);
     CFAllocatorDeallocate(kCFAllocatorSystemDefault, tsd);
 }
 
 __private_extern__ __CFThreadSpecificData *__CFGetThreadSpecificData(void) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-    __CFThreadSpecificData *data;
-    data = pthread_getspecific(__CFTSDKey);
-    if (data) {
-       return data;
-    }
-    data = CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__CFThreadSpecificData), 0);
-    if (__CFOASafe) __CFSetLastAllocationEventName(data, "CFUtilities (thread-data)");
-    memset(data, 0, sizeof(__CFThreadSpecificData));
-    pthread_setspecific(__CFTSDKey, data);
-    return data;
-#elif defined(__WIN32__)
     __CFThreadSpecificData *data;
     data = (__CFThreadSpecificData *)TlsGetValue(__CFTSDKey);
     if (data) {
@@ -828,36 +803,22 @@ __private_extern__ __CFThreadSpecificData *__CFGetThreadSpecificData(void) {
     memset(data, 0, sizeof(__CFThreadSpecificData));
     TlsSetValue(__CFTSDKey, data);
     return data;
-#endif
 }
+#endif
 
 __private_extern__ void __CFBaseInitialize(void) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-    pthread_key_create(&__CFTSDKey, __CFFinalizeThreadData);
-#endif
-#if 0 || 0
+#if DEPLOYMENT_TARGET_WINDOWS
     __CFTSDKey = TlsAlloc();
 #endif
 }
 
-#if 0 || 0
+#if DEPLOYMENT_TARGET_WINDOWS
 __private_extern__ void __CFBaseCleanup(void) {
     TlsFree(__CFTSDKey);
 }
 #endif
 
 
-static CFBadErrorCallBack __CFOutOfMemoryCallBack = NULL;
-
-CFBadErrorCallBack _CFGetOutOfMemoryErrorCallBack(void) {
-    return __CFOutOfMemoryCallBack;
-}
-
-void _CFSetOutOfMemoryErrorCallBack(CFBadErrorCallBack callBack) {
-    __CFOutOfMemoryCallBack = callBack;
-}
-
-
 CFRange __CFRangeMake(CFIndex loc, CFIndex len) {
     CFRange range;
     range.location = loc;
@@ -920,7 +881,7 @@ void _CFRuntimeSetCFMPresent(void *addr) {
     hasCFM = 1;
 }
 
-#if (DEPLOYMENT_TARGET_MACOSX) && defined(__ppc__)
+#if DEPLOYMENT_TARGET_MACOSX && defined(__ppc__)
 
 /* See comments below */
 __private_extern__ void __CF_FAULT_CALLBACK(void **ptr) {
@@ -987,11 +948,11 @@ __asm__ (
 
 // void __HALT(void);
 
-#if defined(__ppc__) || defined(__ppc64__)
+#if defined(__ppc__)
 __asm__ (
 ".text\n"
 "      .align 2\n"
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 ".private_extern ___HALT\n"
 #else
 ".globl ___HALT\n"
@@ -1010,7 +971,7 @@ void __HALT() {
 __asm__ (
 ".text\n"
 "      .align 2, 0x90\n"
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 ".private_extern ___HALT\n"
 #else
 ".globl ___HALT\n"
index 7ff29ee6b2cbecf9f29cf8fade62aa8180e74918..c21f1e7f86ba8ae6b136e0ea5ae88c03b4db11e8 100644 (file)
--- a/CFBase.h
+++ b/CFBase.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBase.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFBASE__)
 #define __COREFOUNDATION_CFBASE__ 1
 
-#if (defined(__CYGWIN32__) || defined(_WIN32)) && !defined (__WIN32__)
+#include <TargetConditionals.h>
+
+#if (defined(__CYGWIN32__) || defined(_WIN32)) && !defined(__WIN32__)
 #define __WIN32__ 1
 #endif
 
@@ -36,7 +38,7 @@
 #endif
 
 #if (defined(__i386__) || defined(__x86_64__)) && !defined(__LITTLE_ENDIAN__)
-    #define __LITTLE_ENDIAN__ 1
+#define __LITTLE_ENDIAN__ 1
 #endif
 
 #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
@@ -51,9 +53,7 @@
 #error Both __BIG_ENDIAN__ and __LITTLE_ENDIAN__ cannot be true
 #endif
 
-#if defined(__WIN32__)
-#include <windows.h>
-#include <winsock2.h>
+#if TARGET_OS_WIN32
 #include <stdint.h>
 #include <stdbool.h>
 #elif defined(__GNUC__)
@@ -62,9 +62,9 @@
 #endif
 #include <AvailabilityMacros.h>
 
-    #if defined(__MACH__)
-        #include <libkern/OSTypes.h>
-    #endif
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+#include <libkern/OSTypes.h>
+#endif
 
 #if !defined(__MACTYPES__)
 #if !defined(_OS_OSTYPES_H)
@@ -82,6 +82,7 @@
     typedef float                   Float32;
     typedef double                  Float64;
     typedef unsigned short          UniChar;
+    typedef unsigned long           UniCharCount;
     typedef unsigned char *         StringPtr;
     typedef const unsigned char *   ConstStringPtr;
     typedef unsigned char           Str255[256];
     typedef SInt16                  OSErr;
     typedef SInt16                  RegionCode;
     typedef SInt16                  LangCode;
+    typedef SInt16                  ScriptCode;
+    typedef UInt32                  FourCharCode;
+    typedef FourCharCode            OSType;
+    typedef UInt8                   Byte;
+    typedef SInt8                   SignedByte;
 #endif
 #if !defined(__MACTYPES__) || (defined(UNIVERSAL_INTERFACES_VERSION) && UNIVERSAL_INTERFACES_VERSION < 0x0340)
     typedef UInt32                  UTF32Char;
 #endif
 #endif
 
+#if TARGET_OS_WIN32 && defined(CF_BUILDING_CF) && defined(__cplusplus)
+#define CF_EXPORT extern "C" __declspec(dllexport) 
+#elif TARGET_OS_WIN32 && defined(CF_BUILDING_CF) && !defined(__cplusplus)
+#define CF_EXPORT extern __declspec(dllexport) 
+#elif TARGET_OS_WIN32 && defined(__cplusplus)
+#define CF_EXPORT extern "C" __declspec(dllimport) 
+#elif TARGET_OS_WIN32
+#define CF_EXPORT extern __declspec(dllimport) 
+#else
+#define CF_EXPORT extern
+#endif
+
 CF_EXTERN_C_BEGIN
 
 #if !defined(NULL)
@@ -126,23 +144,6 @@ CF_EXTERN_C_BEGIN
     #define FALSE      0
 #endif
 
-#if defined(__WIN32__)
-    #undef CF_EXPORT
-    #if defined(CF_BUILDING_CF)
-       #define CF_EXPORT __declspec(dllexport) extern
-    #else
-       #define CF_EXPORT __declspec(dllimport) extern
-    #endif
-#elif defined(macintosh)
-    #if defined(__MWERKS__)
-        #define CF_EXPORT __declspec(export) extern
-    #endif
-#endif
-
-#if !defined(CF_EXPORT)
-    #define CF_EXPORT extern
-#endif
-
 #if !defined(CF_INLINE)
     #if defined(__GNUC__) && (__GNUC__ == 4) && !defined(DEBUG)
         #define CF_INLINE static __inline__ __attribute__((always_inline))
@@ -152,14 +153,22 @@ CF_EXTERN_C_BEGIN
        #define CF_INLINE static inline
     #elif defined(_MSC_VER)
         #define CF_INLINE static __inline
-    #elif defined(__WIN32__)
+    #elif TARGET_OS_WIN32
        #define CF_INLINE static __inline__
     #endif
 #endif
 
+// Marks functions which return a CF type that needs to be released by the caller but whose names are not consistent with CoreFoundation naming rules. The recommended fix to this is the rename the functions, but this macro can be used to let the clang static analyzer know of any exceptions that cannot be fixed.
+#if defined(__clang__)
+#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
+#else
+#define CF_RETURNS_RETAINED
+#endif
+
 
 CF_EXPORT double kCFCoreFoundationVersionNumber;
 
+#if TARGET_OS_MAC
 #define kCFCoreFoundationVersionNumber10_0     196.40
 #define kCFCoreFoundationVersionNumber10_0_3   196.50
 #define kCFCoreFoundationVersionNumber10_1     226.00
@@ -202,6 +211,20 @@ CF_EXPORT double kCFCoreFoundationVersionNumber;
 #define kCFCoreFoundationVersionNumber10_4_9   368.28
 #define kCFCoreFoundationVersionNumber10_4_10  368.28
 #define kCFCoreFoundationVersionNumber10_4_11  368.31
+#define kCFCoreFoundationVersionNumber10_5     476.00
+#define kCFCoreFoundationVersionNumber10_5_1   476.00
+#define kCFCoreFoundationVersionNumber10_5_2   476.10
+#define kCFCoreFoundationVersionNumber10_5_3   476.13
+#define kCFCoreFoundationVersionNumber10_5_4   476.14
+#define kCFCoreFoundationVersionNumber10_5_5   476.15
+#define kCFCoreFoundationVersionNumber10_5_6   476.17
+#endif
+
+#if TARGET_OS_IPHONE
+#define kCFCoreFoundationVersionNumber_iPhoneOS_2_0    478.23
+#define kCFCoreFoundationVersionNumber_iPhoneOS_2_1 478.26
+#define kCFCoreFoundationVersionNumber_iPhoneOS_2_2 478.29
+#endif
 
 typedef unsigned long CFTypeID;
 typedef unsigned long CFOptionFlags;
diff --git a/CFBasicHash.h b/CFBasicHash.h
new file mode 100644 (file)
index 0000000..e592b69
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*     CFBasicHash.h
+       Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+*/
+
+#include <CoreFoundation/CFBase.h>
+#include <CoreFoundation/CFString.h>
+#include "CFInternal.h"
+
+CF_EXTERN_C_BEGIN
+
+struct __objcFastEnumerationStateEquivalent2 {
+    unsigned long state;
+    unsigned long *itemsPtr;
+    unsigned long *mutationsPtr;
+    unsigned long extra[5];
+};
+
+enum {
+    __kCFBasicHashLinearHashingValue = 1,
+    __kCFBasicHashDoubleHashingValue = 2,
+    __kCFBasicHashExponentialHashingValue = 3,
+};
+
+enum {
+    kCFBasicHashHasValues2 = (1UL << 2),
+    kCFBasicHashHasKeys = (1UL << 3),
+    kCFBasicHashHasKeys2 = (1UL << 4),
+    kCFBasicHashHasCounts = (1UL << 5),
+    kCFBasicHashHasOrder = (1UL << 6),
+    kCFBasicHashHasHashCache = (1UL << 7),
+
+    kCFBasicHashStrongValues = (1UL << 9),
+    kCFBasicHashStrongValues2 = (1UL << 10),
+    kCFBasicHashStrongKeys = (1UL << 11),
+    kCFBasicHashStrongKeys2 = (1UL << 12),
+
+    kCFBasicHashLinearHashing = (__kCFBasicHashLinearHashingValue << 13), // bits 13-14
+    kCFBasicHashDoubleHashing = (__kCFBasicHashDoubleHashingValue << 13),
+    kCFBasicHashExponentialHashing = (__kCFBasicHashExponentialHashingValue << 13),
+
+    kCFBasicHashAggressiveGrowth = (1UL << 15),
+};
+
+// Note that for a hash table without keys, the value is treated as the key,
+// and the value should be passed in as the key for operations which take a key.
+
+typedef struct {
+    CFIndex idx;
+    uintptr_t weak_key;
+    uintptr_t weak_key2;
+    uintptr_t weak_value;
+    uintptr_t weak_value2;
+    uintptr_t count;
+    uintptr_t order;
+} CFBasicHashBucket;
+
+typedef struct __CFBasicHash *CFBasicHashRef;
+
+// Bit 6 in the CF_INFO_BITS of the CFRuntimeBase inside the CFBasicHashRef is the "is immutable" bit
+CF_INLINE Boolean CFBasicHashIsMutable(CFBasicHashRef ht) {
+    return __CFBitfieldGetValue(((CFRuntimeBase *)ht)->_cfinfo[CF_INFO_BITS], 6, 6) ? false : true;
+}
+CF_INLINE void CFBasicHashMakeImmutable(CFBasicHashRef ht) {
+    __CFBitfieldSetValue(((CFRuntimeBase *)ht)->_cfinfo[CF_INFO_BITS], 6, 6, 1);
+}
+
+
+typedef struct __CFBasicHashCallbacks CFBasicHashCallbacks;
+
+typedef uintptr_t (*CFBasicHashCallbackType)(CFBasicHashRef ht, uint8_t op, uintptr_t a1, uintptr_t a2, const CFBasicHashCallbacks *cb);
+
+enum {
+    kCFBasicHashCallbackOpCopyCallbacks = 8,   // Return new value; REQUIRED
+    kCFBasicHashCallbackOpFreeCallbacks = 9,   // Return 0; REQUIRED
+
+    kCFBasicHashCallbackOpRetainValue = 10,    // Return first arg or new value; REQUIRED
+    kCFBasicHashCallbackOpRetainValue2 = 11,   // Return first arg or new value
+    kCFBasicHashCallbackOpRetainKey = 12,      // Return first arg or new key; REQUIRED
+    kCFBasicHashCallbackOpRetainKey2 = 13,     // Return first arg or new key
+    kCFBasicHashCallbackOpReleaseValue = 14,   // Return 0; REQUIRED
+    kCFBasicHashCallbackOpReleaseValue2 = 15,  // Return 0
+    kCFBasicHashCallbackOpReleaseKey = 16,     // Return 0; REQUIRED
+    kCFBasicHashCallbackOpReleaseKey2 = 17,    // Return 0
+    kCFBasicHashCallbackOpValueEqual = 18,     // Return 0 or 1; REQUIRED
+    kCFBasicHashCallbackOpValue2Equal = 19,    // Return 0 or 1
+    kCFBasicHashCallbackOpKeyEqual = 20,       // Return 0 or 1; REQUIRED
+    kCFBasicHashCallbackOpKey2Equal = 21,      // Return 0 or 1
+    kCFBasicHashCallbackOpHashKey = 22,                // Return hash code; REQUIRED
+    kCFBasicHashCallbackOpHashKey2 = 23,       // Return hash code
+    kCFBasicHashCallbackOpDescribeValue = 24,  // Return retained CFStringRef; REQUIRED
+    kCFBasicHashCallbackOpDescribeValue2 = 25, // Return retained CFStringRef
+    kCFBasicHashCallbackOpDescribeKey = 26,    // Return retained CFStringRef; REQUIRED
+    kCFBasicHashCallbackOpDescribeKey2 = 27,   // Return retained CFStringRef
+};
+
+struct __CFBasicHashCallbacks {
+    CFBasicHashCallbackType func; // must not be NULL
+    uintptr_t context[0]; // variable size; any pointers in here must remain valid as long as the CFBasicHash
+};
+
+extern const CFBasicHashCallbacks CFBasicHashNullCallbacks;
+extern const CFBasicHashCallbacks CFBasicHashStandardCallbacks;
+
+
+CFOptionFlags CFBasicHashGetFlags(CFBasicHashRef ht);
+CFIndex CFBasicHashGetNumBuckets(CFBasicHashRef ht);
+CFIndex CFBasicHashGetCapacity(CFBasicHashRef ht);
+void CFBasicHashSetCapacity(CFBasicHashRef ht, CFIndex capacity);
+
+CFIndex CFBasicHashGetCount(CFBasicHashRef ht);
+CFBasicHashBucket CFBasicHashGetBucket(CFBasicHashRef ht, CFIndex idx);
+CFBasicHashBucket CFBasicHashFindBucket(CFBasicHashRef ht, uintptr_t stack_key);
+CFIndex CFBasicHashGetCountOfKey(CFBasicHashRef ht, uintptr_t stack_key);
+CFIndex CFBasicHashGetCountOfValue(CFBasicHashRef ht, uintptr_t stack_value);
+Boolean CFBasicHashesAreEqual(CFBasicHashRef ht1, CFBasicHashRef ht2);
+void CFBasicHashApply(CFBasicHashRef ht, Boolean (^block)(CFBasicHashBucket));
+void CFBasicHashGetElements(CFBasicHashRef ht, CFIndex bufferslen, uintptr_t *weak_values, uintptr_t *weak_values2, uintptr_t *weak_keys, uintptr_t *weak_keys2);
+
+void CFBasicHashAddValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value);
+void CFBasicHashReplaceValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value);
+void CFBasicHashSetValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value);
+CFIndex CFBasicHashRemoveValue(CFBasicHashRef ht, uintptr_t stack_key);
+void CFBasicHashRemoveAllValues(CFBasicHashRef ht);
+
+size_t CFBasicHashGetSize(CFBasicHashRef ht, Boolean total);
+
+CFStringRef CFBasicHashCopyDescription(CFBasicHashRef ht, Boolean detailed, CFStringRef linePrefix, CFStringRef entryLinePrefix, Boolean describeElements);
+
+CFTypeID CFBasicHashGetTypeID(void);
+
+extern Boolean __CFBasicHashEqual(CFTypeRef cf1, CFTypeRef cf2);
+extern CFHashCode __CFBasicHashHash(CFTypeRef cf);
+extern CFStringRef __CFBasicHashCopyDescription(CFTypeRef cf);
+extern void __CFBasicHashDeallocate(CFTypeRef cf);
+extern unsigned long __CFBasicHashFastEnumeration(CFBasicHashRef ht, struct __objcFastEnumerationStateEquivalent2 *state, void *stackbuffer, unsigned long count);
+
+// creation functions create mutable CFBasicHashRefs
+CFBasicHashRef CFBasicHashCreate(CFAllocatorRef allocator, CFOptionFlags flags, const CFBasicHashCallbacks *cb);
+CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFBasicHashRef ht);
+
+
+CF_EXTERN_C_END
+
diff --git a/CFBasicHash.m b/CFBasicHash.m
new file mode 100644 (file)
index 0000000..929d8bf
--- /dev/null
@@ -0,0 +1,1763 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*     CFBasicHash.m
+       Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+       Responsibility: Christopher Kane
+*/
+
+#import "CFBasicHash.h"
+#import <CoreFoundation/CFRuntime.h>
+#import <CoreFoundation/CFSet.h>
+#import <Block.h>
+#import <objc/objc.h>
+#import <math.h>
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#define __SetLastAllocationEventName(A, B) do { } while (0)
+#else
+#define __SetLastAllocationEventName(A, B) do { if (__CFOASafe && (A)) __CFSetLastAllocationEventName(A, B); } while (0)
+#endif
+
+#define GCRETAIN(A, B) kCFTypeSetCallBacks.retain(A, B)
+#define GCRELEASE(A, B) kCFTypeSetCallBacks.release(A, B)
+
+#define __AssignWithWriteBarrier(location, value) objc_assign_strongCast((id)value, (id *)location)
+
+#define ENABLE_DTRACE_PROBES 0
+#define ENABLE_MEMORY_COUNTERS 0
+
+
+/*
+// dtrace -h -s foo.d
+// Note: output then changed by putting do/while around macro bodies and adding a cast of the arguments
+
+provider Cocoa_HashTable {
+        probe hash_key(unsigned long table, unsigned long key, unsigned long hash);
+        probe test_equal(unsigned long table, unsigned long key1, unsigned long key2);
+        probe probing_start(unsigned long table, unsigned long num_buckets);
+        probe probe_empty(unsigned long table, unsigned long idx);
+        probe probe_deleted(unsigned long table, unsigned long idx);
+        probe probe_valid(unsigned long table, unsigned long idx);
+        probe probing_end(unsigned long table, unsigned long num_probes);
+        probe rehash_start(unsigned long table, unsigned long num_buckets, unsigned long total_size);
+        probe rehash_end(unsigned long table, unsigned long num_buckets, unsigned long total_size);
+};
+
+#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable provider
+#pragma D attributes Private/Private/Unknown provider Cocoa_HashTable module
+#pragma D attributes Private/Private/Unknown provider Cocoa_HashTable function
+#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable name
+#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable args
+*/
+
+#if ENABLE_DTRACE_PROBES
+
+#define COCOA_HASHTABLE_STABILITY "___dtrace_stability$Cocoa_HashTable$v1$4_4_5_1_1_0_1_1_0_4_4_5_4_4_5"
+
+#define COCOA_HASHTABLE_TYPEDEFS "___dtrace_typedefs$Cocoa_HashTable$v2"
+
+#define COCOA_HASHTABLE_REHASH_END(arg0, arg1, arg2) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$rehash_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_REHASH_END_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$rehash_end$v1()
+#define COCOA_HASHTABLE_REHASH_START(arg0, arg1, arg2) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$rehash_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_REHASH_START_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$rehash_start$v1()
+#define COCOA_HASHTABLE_HASH_KEY(arg0, arg1, arg2) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$hash_key$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_HASH_KEY_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$hash_key$v1()
+#define COCOA_HASHTABLE_PROBE_DELETED(arg0, arg1) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$probe_deleted$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBE_DELETED_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$probe_deleted$v1()
+#define COCOA_HASHTABLE_PROBE_EMPTY(arg0, arg1) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$probe_empty$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBE_EMPTY_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$probe_empty$v1()
+#define COCOA_HASHTABLE_PROBE_VALID(arg0, arg1) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$probe_valid$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBE_VALID_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$probe_valid$v1()
+#define COCOA_HASHTABLE_PROBING_END(arg0, arg1) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$probing_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBING_END_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$probing_end$v1()
+#define COCOA_HASHTABLE_PROBING_START(arg0, arg1) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$probing_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBING_START_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$probing_start$v1()
+#define COCOA_HASHTABLE_TEST_EQUAL(arg0, arg1, arg2) \
+do { \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+        __dtrace_probe$Cocoa_HashTable$test_equal$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
+        __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_TEST_EQUAL_ENABLED() \
+        __dtrace_isenabled$Cocoa_HashTable$test_equal$v1()
+
+extern void __dtrace_probe$Cocoa_HashTable$rehash_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$rehash_end$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$rehash_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$rehash_start$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$hash_key$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$hash_key$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probe_deleted$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probe_deleted$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probe_empty$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probe_empty$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probe_valid$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probe_valid$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probing_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probing_end$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probing_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probing_start$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$test_equal$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$test_equal$v1(void);
+
+#else
+
+#define COCOA_HASHTABLE_REHASH_END(arg0, arg1, arg2) do {} while (0)
+#define COCOA_HASHTABLE_REHASH_END_ENABLED() 0
+#define COCOA_HASHTABLE_REHASH_START(arg0, arg1, arg2) do {} while (0)
+#define COCOA_HASHTABLE_REHASH_START_ENABLED() 0
+#define COCOA_HASHTABLE_HASH_KEY(arg0, arg1, arg2) do {} while (0)
+#define COCOA_HASHTABLE_HASH_KEY_ENABLED() 0
+#define COCOA_HASHTABLE_PROBE_DELETED(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBE_DELETED_ENABLED() 0
+#define COCOA_HASHTABLE_PROBE_EMPTY(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBE_EMPTY_ENABLED() 0
+#define COCOA_HASHTABLE_PROBE_VALID(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBE_VALID_ENABLED() 0
+#define COCOA_HASHTABLE_PROBING_END(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBING_END_ENABLED() 0
+#define COCOA_HASHTABLE_PROBING_START(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBING_START_ENABLED() 0
+#define COCOA_HASHTABLE_TEST_EQUAL(arg0, arg1, arg2) do {} while (0)
+#define COCOA_HASHTABLE_TEST_EQUAL_ENABLED() 0
+
+#endif
+
+
+#if !defined(__LP64__)
+#define __LP64__ 0
+#endif
+
+enum {
+#if __LP64__
+    __CFBasicHashMarkerShift = 40 // 64 - 24
+#else
+    __CFBasicHashMarkerShift = 8  // 32 - 24
+#endif
+};
+
+typedef union {
+    uintptr_t weak;
+    id strong;
+} CFBasicHashValue;
+
+struct __CFBasicHash {
+    CFRuntimeBase base;
+    struct { // 128 bits
+        uint64_t hash_style:2;
+        uint64_t values2_offset:1;
+        uint64_t keys_offset:2;
+        uint64_t keys2_offset:2;
+        uint64_t counts_offset:3;
+        uint64_t orders_offset:3;
+        uint64_t hashes_offset:3;
+        uint64_t num_buckets_idx:6; /* index to number of buckets */
+        uint64_t used_buckets:42;   /* number of used buckets */
+        uint64_t __0:2;
+        uint64_t finalized:1;
+        uint64_t fast_grow:1;
+        uint64_t strong_values:1;
+        uint64_t strong_values2:1;
+        uint64_t strong_keys:1;
+        uint64_t strong_keys2:1;
+        uint64_t marker:24;
+        uint64_t deleted:16;
+        uint64_t mutations:16;
+    } bits;
+    __strong const CFBasicHashCallbacks *callbacks;
+    void *pointers[1];
+};
+
+CF_INLINE CFBasicHashValue *__CFBasicHashGetValues(CFBasicHashRef ht) {
+    return (CFBasicHashValue *)ht->pointers[0];
+}
+
+CF_INLINE void __CFBasicHashSetValues(CFBasicHashRef ht, CFBasicHashValue *ptr) {
+    __AssignWithWriteBarrier(&ht->pointers[0], ptr);
+}
+
+CF_INLINE CFBasicHashValue *__CFBasicHashGetValues2(CFBasicHashRef ht) {
+    if (0 == ht->bits.values2_offset) HALT;
+    return (CFBasicHashValue *)ht->pointers[ht->bits.values2_offset];
+}
+
+CF_INLINE void __CFBasicHashSetValues2(CFBasicHashRef ht, CFBasicHashValue *ptr) {
+    if (0 == ht->bits.values2_offset) HALT;
+    __AssignWithWriteBarrier(&ht->pointers[ht->bits.values2_offset], ptr);
+}
+
+CF_INLINE CFBasicHashValue *__CFBasicHashGetKeys(CFBasicHashRef ht) {
+    if (0 == ht->bits.keys_offset) HALT;
+    return (CFBasicHashValue *)ht->pointers[ht->bits.keys_offset];
+}
+
+CF_INLINE void __CFBasicHashSetKeys(CFBasicHashRef ht, CFBasicHashValue *ptr) {
+    if (0 == ht->bits.keys_offset) HALT;
+    __AssignWithWriteBarrier(&ht->pointers[ht->bits.keys_offset], ptr);
+}
+
+CF_INLINE CFBasicHashValue *__CFBasicHashGetKeys2(CFBasicHashRef ht) {
+    if (0 == ht->bits.keys2_offset) HALT;
+    return (CFBasicHashValue *)ht->pointers[ht->bits.keys2_offset];
+}
+
+CF_INLINE void __CFBasicHashSetKeys2(CFBasicHashRef ht, CFBasicHashValue *ptr) {
+    if (0 == ht->bits.keys2_offset) HALT;
+    __AssignWithWriteBarrier(&ht->pointers[ht->bits.keys2_offset], ptr);
+}
+
+CF_INLINE uintptr_t *__CFBasicHashGetCounts(CFBasicHashRef ht) {
+    if (0 == ht->bits.counts_offset) HALT;
+    return (uintptr_t *)ht->pointers[ht->bits.counts_offset];
+}
+
+CF_INLINE void __CFBasicHashSetCounts(CFBasicHashRef ht, uintptr_t *ptr) {
+    if (0 == ht->bits.counts_offset) HALT;
+    __AssignWithWriteBarrier(&ht->pointers[ht->bits.counts_offset], ptr);
+}
+
+CF_INLINE uintptr_t *__CFBasicHashGetOrders(CFBasicHashRef ht) {
+    if (0 == ht->bits.orders_offset) HALT;
+    return (uintptr_t *)ht->pointers[ht->bits.orders_offset];
+}
+
+CF_INLINE void __CFBasicHashSetOrders(CFBasicHashRef ht, uintptr_t *ptr) {
+    if (0 == ht->bits.orders_offset) HALT;
+    __AssignWithWriteBarrier(&ht->pointers[ht->bits.orders_offset], ptr);
+}
+
+CF_INLINE uintptr_t *__CFBasicHashGetHashes(CFBasicHashRef ht) {
+    if (0 == ht->bits.hashes_offset) HALT;
+    return (uintptr_t *)ht->pointers[ht->bits.hashes_offset];
+}
+
+CF_INLINE void __CFBasicHashSetHashes(CFBasicHashRef ht, uintptr_t *ptr) {
+    if (0 == ht->bits.hashes_offset) HALT;
+    __AssignWithWriteBarrier(&ht->pointers[ht->bits.hashes_offset], ptr);
+}
+
+static uintptr_t __CFBasicHashNullCallback(CFBasicHashRef ht, uint8_t op, uintptr_t a1, uintptr_t a2, const CFBasicHashCallbacks *cb) {
+    switch (op) {
+    case kCFBasicHashCallbackOpCopyCallbacks: return (uintptr_t)&CFBasicHashNullCallbacks;
+    case kCFBasicHashCallbackOpFreeCallbacks: return 0;
+    case kCFBasicHashCallbackOpRetainValue:
+    case kCFBasicHashCallbackOpRetainValue2:
+    case kCFBasicHashCallbackOpRetainKey:
+    case kCFBasicHashCallbackOpRetainKey2:   return a1;
+    case kCFBasicHashCallbackOpReleaseValue:
+    case kCFBasicHashCallbackOpReleaseValue2:
+    case kCFBasicHashCallbackOpReleaseKey:
+    case kCFBasicHashCallbackOpReleaseKey2:  return 0;
+    case kCFBasicHashCallbackOpValueEqual:
+    case kCFBasicHashCallbackOpValue2Equal:
+    case kCFBasicHashCallbackOpKeyEqual:
+    case kCFBasicHashCallbackOpKey2Equal:    return a1 == a2;
+    case kCFBasicHashCallbackOpHashKey:
+    case kCFBasicHashCallbackOpHashKey2:     return a1;
+    case kCFBasicHashCallbackOpDescribeValue:
+    case kCFBasicHashCallbackOpDescribeValue2:
+    case kCFBasicHashCallbackOpDescribeKey:
+    case kCFBasicHashCallbackOpDescribeKey2: return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)a1);
+    }
+    return 0;
+}
+
+static uintptr_t __CFBasicHashStandardCallback(CFBasicHashRef ht, uint8_t op, uintptr_t a1, uintptr_t a2, const CFBasicHashCallbacks *cb) {
+    switch (op) {
+    case kCFBasicHashCallbackOpCopyCallbacks: return (uintptr_t)&CFBasicHashStandardCallbacks;
+    case kCFBasicHashCallbackOpFreeCallbacks: return 0;
+    case kCFBasicHashCallbackOpRetainValue:   return (ht->bits.strong_values) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)a1) : (uintptr_t)CFRetain((CFTypeRef)a1);
+    case kCFBasicHashCallbackOpRetainValue2:  return (ht->bits.strong_values2) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)a1) : (uintptr_t)CFRetain((CFTypeRef)a1);
+    case kCFBasicHashCallbackOpRetainKey:     return (ht->bits.strong_keys) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)a1) : (uintptr_t)CFRetain((CFTypeRef)a1);
+    case kCFBasicHashCallbackOpRetainKey2:    return (ht->bits.strong_keys2) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)a1) : (uintptr_t)CFRetain((CFTypeRef)a1);
+    case kCFBasicHashCallbackOpReleaseValue:  if (ht->bits.strong_values) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)a1); else CFRelease((CFTypeRef)a1); return 0;
+    case kCFBasicHashCallbackOpReleaseValue2: if (ht->bits.strong_values2) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)a1); else CFRelease((CFTypeRef)a1); return 0;
+    case kCFBasicHashCallbackOpReleaseKey:    if (ht->bits.strong_keys) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)a1); else CFRelease((CFTypeRef)a1); return 0;
+    case kCFBasicHashCallbackOpReleaseKey2:   if (ht->bits.strong_keys2) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)a1); else CFRelease((CFTypeRef)a1); return 0;
+    case kCFBasicHashCallbackOpValueEqual:
+    case kCFBasicHashCallbackOpValue2Equal:
+    case kCFBasicHashCallbackOpKeyEqual:
+    case kCFBasicHashCallbackOpKey2Equal:     return CFEqual((CFTypeRef)a1, (CFTypeRef)a2);
+    case kCFBasicHashCallbackOpHashKey:
+    case kCFBasicHashCallbackOpHashKey2:      return (uintptr_t)CFHash((CFTypeRef)a1);
+    case kCFBasicHashCallbackOpDescribeValue:
+    case kCFBasicHashCallbackOpDescribeValue2:
+    case kCFBasicHashCallbackOpDescribeKey:
+    case kCFBasicHashCallbackOpDescribeKey2:  return (uintptr_t)CFCopyDescription((CFTypeRef)a1);
+    }
+    return 0;
+}
+
+__private_extern__ const CFBasicHashCallbacks CFBasicHashNullCallbacks = {__CFBasicHashNullCallback};
+__private_extern__ const CFBasicHashCallbacks CFBasicHashStandardCallbacks = {__CFBasicHashStandardCallback};
+
+CF_INLINE uintptr_t __CFBasicHashImportValue(CFBasicHashRef ht, uintptr_t stack_value) {
+    return ht->callbacks->func(ht, kCFBasicHashCallbackOpRetainValue, stack_value, 0, ht->callbacks);
+}
+
+CF_INLINE uintptr_t __CFBasicHashImportValue2(CFBasicHashRef ht, uintptr_t stack_value) {
+    return ht->callbacks->func(ht, kCFBasicHashCallbackOpRetainValue2, stack_value, 0, ht->callbacks);
+}
+
+CF_INLINE uintptr_t __CFBasicHashImportKey(CFBasicHashRef ht, uintptr_t stack_key) {
+    return ht->callbacks->func(ht, kCFBasicHashCallbackOpRetainKey, stack_key, 0, ht->callbacks);
+}
+
+CF_INLINE uintptr_t __CFBasicHashImportKey2(CFBasicHashRef ht, uintptr_t stack_key) {
+    return ht->callbacks->func(ht, kCFBasicHashCallbackOpRetainKey2, stack_key, 0, ht->callbacks);
+}
+
+CF_INLINE void __CFBasicHashEjectValue(CFBasicHashRef ht, uintptr_t stack_value) {
+    ht->callbacks->func(ht, kCFBasicHashCallbackOpReleaseValue, stack_value, 0, ht->callbacks);
+}
+
+CF_INLINE void __CFBasicHashEjectValue2(CFBasicHashRef ht, uintptr_t stack_value) {
+    ht->callbacks->func(ht, kCFBasicHashCallbackOpReleaseValue2, stack_value, 0, ht->callbacks);
+}
+
+CF_INLINE void __CFBasicHashEjectKey(CFBasicHashRef ht, uintptr_t stack_key) {
+    ht->callbacks->func(ht, kCFBasicHashCallbackOpReleaseKey, stack_key, 0, ht->callbacks);
+}
+
+CF_INLINE void __CFBasicHashEjectKey2(CFBasicHashRef ht, uintptr_t stack_key) {
+    ht->callbacks->func(ht, kCFBasicHashCallbackOpReleaseKey2, stack_key, 0, ht->callbacks);
+}
+
+CF_INLINE Boolean __CFBasicHashTestEqualValue(CFBasicHashRef ht, uintptr_t stack_value_a, uintptr_t stack_value_b) {
+    return (Boolean)ht->callbacks->func(ht, kCFBasicHashCallbackOpValueEqual, stack_value_a, stack_value_b, ht->callbacks);
+}
+
+CF_INLINE Boolean __CFBasicHashTestEqualValue2(CFBasicHashRef ht, uintptr_t stack_value_a, uintptr_t stack_value_b) {
+    return (Boolean)ht->callbacks->func(ht, kCFBasicHashCallbackOpValue2Equal, stack_value_a, stack_value_b, ht->callbacks);
+}
+
+CF_INLINE Boolean __CFBasicHashTestEqualKey(CFBasicHashRef ht, uintptr_t stack_key_a, uintptr_t stack_key_b) {
+    COCOA_HASHTABLE_TEST_EQUAL(ht, stack_key_a, stack_key_b);
+    return (Boolean)ht->callbacks->func(ht, kCFBasicHashCallbackOpKeyEqual, stack_key_a, stack_key_b, ht->callbacks);
+}
+
+CF_INLINE Boolean __CFBasicHashTestEqualKey2(CFBasicHashRef ht, uintptr_t stack_key_a, uintptr_t stack_key_b) {
+    COCOA_HASHTABLE_TEST_EQUAL(ht, stack_key_a, stack_key_b);
+    return (Boolean)ht->callbacks->func(ht, kCFBasicHashCallbackOpKey2Equal, stack_key_a, stack_key_b, ht->callbacks);
+}
+
+CF_INLINE CFHashCode __CFBasicHashHashKey(CFBasicHashRef ht, uintptr_t stack_key) {
+    CFHashCode hash_code = (CFHashCode)ht->callbacks->func(ht, kCFBasicHashCallbackOpHashKey, stack_key, 0, ht->callbacks);
+    COCOA_HASHTABLE_HASH_KEY(ht, stack_key, hash_code);
+    return hash_code;
+}
+
+CF_INLINE CFHashCode __CFBasicHashHashKey2(CFBasicHashRef ht, uintptr_t stack_key) {
+    CFHashCode hash_code = (CFHashCode)ht->callbacks->func(ht, kCFBasicHashCallbackOpHashKey2, stack_key, 0, ht->callbacks);
+    COCOA_HASHTABLE_HASH_KEY(ht, stack_key, hash_code);
+    return hash_code;
+}
+
+CF_INLINE void *__CFBasicHashAllocateMemory(CFBasicHashRef ht, CFIndex count, CFIndex elem_size, Boolean strong) {
+    CFAllocatorRef allocator = CFGetAllocator(ht);
+    void *new_mem = NULL;
+    if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+        new_mem = auto_zone_allocate_object(auto_zone(), count * elem_size, strong ? AUTO_MEMORY_SCANNED : AUTO_UNSCANNED, false, false);
+    } else {
+        new_mem = CFAllocatorAllocate(allocator, count * elem_size, 0);
+    }
+    if (!new_mem) HALT;
+    return new_mem;
+}
+
+
+// Prime numbers. Values above 100 have been adjusted up so that the
+// malloced block size will be just below a multiple of 512; values
+// above 1200 have been adjusted up to just below a multiple of 4096.
+static const uintptr_t __CFBasicHashTableSizes[64] = {
+    0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
+    2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
+    214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
+    6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
+    111638519, 180634607, 292272623, 472907251,
+#if __LP64__
+    765180413UL, 1238087663UL, 2003267557UL, 3241355263UL, 5244622819UL,
+    8485977589UL, 13730600407UL, 22216578047UL, 35947178479UL,
+    58163756537UL, 94110934997UL, 152274691561UL, 246385626107UL,
+    398660317687UL, 645045943807UL, 1043706260983UL, 1688752204787UL,
+    2732458465769UL, 4421210670577UL, 7153669136377UL,
+    11574879807461UL, 18728548943849UL, 30303428750843UL
+#endif
+};
+
+// Primitive roots for the primes above
+static const uintptr_t __CFBasicHashPrimitiveRoots[64] = {
+    0, 2, 3, 2, 5, 6, 7, 3, 19, 6, 5, 3, 3, 3,
+    2, 5, 6, 3, 3, 6, 2, 3, 3,
+    3, 5, 10, 3, 3, 22, 3,
+    3, 3, 5, 2, 22, 2,
+    11, 5, 5, 2,
+#if __LP64__
+    3, 10, 2, 3, 10,
+    2, 3, 5, 3,
+    3, 2, 7, 2,
+    3, 3, 3, 2,
+    3, 5, 5,
+    2, 3, 2
+#endif
+};
+
+/* Primitive roots under 100 for the primes above
+3: 2
+7: 3 5
+13: 2 6 7 11
+23: 5 7 10 11 14 15 17 19 20 21
+41: 6 7 11 12 13 15 17 19 22 24 26 28 29 30 34 35
+71: 7 11 13 21 22 28 31 33 35 42 44 47 52 53 55 56 59 61 62 63 65 67 68 69
+127: 3 6 7 12 14 23 29 39 43 45 46 48 53 55 56 57 58 65 67 78 83 85 86 91 92 93 96 97
+191: 19 21 22 28 29 33 35 42 44 47 53 56 57 58 61 62 63 71 73 74 76 83 87 88 89 91 93 94 95 99
+251: 6 11 14 18 19 24 26 29 30 33 34 37 42 43 44 46 53 54 55 56 57 59 61 62 70 71 72 76 77 78 82 87 90 95 96 97 98 99
+383: 5 10 11 13 15 20 22 26 30 33 35 37 39 40 41 44 45 47 52 53 59 60 61 66 70 74 77 78 79 80 82 83 85 88 89 90 91 94 95 97 99
+631: 3 7 12 13 14 15 19 26 51 53 54 56 59 60 61 63 65 70 75 76 87 93 95 96 99
+1087: 3 10 12 13 14 20 22 24 28 29 31 38 44 45 46 51 52 53 54 58 59 61 62 63 67 74 75 76 80 89 90 92 94 96 97 99
+1723: 3 12 17 18 29 30 38 45 46 48 55 63 74 75 77 78 82 83 86 88 94 95
+2803: 2 11 12 18 20 21 29 30 32 34 35 38 41 46 48 50 52 56 66 67 74 78 79 80 83 84 86 91 93 94 98 99
+4523: 5 6 7 15 18 20 22 24 26 31 34 41 45 54 55 57 60 65 66 70 72 74 76 77 83 85 88 93 94 96 98
+7351: 6 7 12 15 17 22 28 31 35 38 44 52 54 55 56 60 65 69 71 75 96
+11959: 3 6 12 24 29 33 37 39 41 47 48 51 53 57 58 59 66 67 69 73 74 75 78 82 94 96
+19447: 3 5 6 7 10 12 14 20 23 24 28 29 37 39 45 46 47 51 55 56 58 65 71 73 74 75 78 79 80 82 83 90 91 92 94 96
+31231: 6 7 24 29 30 33 41 43 48 52 53 54 56 57 59 60 62 65 69 70 73 75 77 83 86
+50683: 2 3 12 14 17 18 20 32 33 35 39 41 45 50 55 56 57 58 61 62 65 68 69 71 72 74 75 80 84 86 88 93 95
+81919: 3 12 23 24 26 30 33 43 52 53 54 57 59 60 65 66 75 84 86 87 91 92 93 96 97
+132607: 3 5 6 17 19 20 21 23 24 26 29 33 34 35 38 40 42 45 48 52 54 61 62 67 71 73 75 79 82 86 89 90 92
+214519: 3 7 12 15 19 24 26 28 30 33 35 38 41 52 54 56 61 65 69 70 73 77 86 87 89 93 96 97
+346607: 5 10 14 15 17 19 20 21 28 30 34 38 40 41 42 45 51 55 56 57 59 60 63 65 67 68 76 77 80 82 84 89 90 91 97
+561109: 10 11 18 21 26 30 33 35 38 40 41 43 46 47 50 51 53 61 62 72 73 74 84 85 91 96
+907759: 3 6 12 13 17 24 26 33 34 41 47 48 52 57 61 66 68 71 75 79 82 87 89 93 94
+1468927: 3 5 6 11 20 21 22 23 24 26 35 40 42 45 48 51 52 54 58 71 73 75 77 79 86 88 90 92 93 94 95
+2376191: 22 29 31 33 37 43 44 47 55 58 59 62 66 77 86 87 88 93 99
+3845119: 3 11 12 13 15 23 24 30 37 42 43 44 51 52 53 54 55 57 65 73 84 86 87 88 89 92 94 96 97
+6221311: 3 12 13 15 21 24 30 31 33 46 54 57 61 66 67 74 82 84 87 89 91 92 96
+10066421: 3 10 11 12 17 18 19 21 23 27 39 40 41 48 50 56 58 60 61 66 68 71 72 73 74 75 76 77 83 85 86 87 92 94 95 97
+16287743: 5 10 15 20 30 31 35 40 43 45 47 53 55 59 60 61 62 65 70 73 79 80 85 86 89 90 93 94 95
+26354171: 2 6 7 8 10 17 18 21 22 23 24 26 30 35 38 40 50 51 53 59 62 63 66 67 68 69 71 72 74 77 78 83 84 85 87 88 90 91 96 98
+42641881: 22 31 38 44 46 57 59 62 67 69 73 76 77 83 92 99
+68996069: 2 3 8 10 11 12 14 15 17 18 21 26 27 32 37 38 40 43 44 46 47 48 50 53 55 56 58 60 61 62 66 67 68 69 70 72 75 77 82 84 85 87 89 90 93 98 99
+111638519: 11 13 17 22 26 29 33 34 39 41 44 51 52 53 55 58 59 61 65 66 67 68 71 77 78 79 82 83 85 87 88 91 97 99
+180634607: 5 10 15 19 20 23 30 31 35 37 38 40 43 45 46 47 55 57 60 62 65 69 70 74 76 79 80 85 86 89 90 92 93 94
+292272623: 5 10 11 13 15 20 22 23 26 30 31 33 35 39 40 44 45 46 47 52 59 60 61 62 66 67 69 70 71 77 78 79 80 83 85 88 90 91 92 93 94 95 97 99
+472907251: 2 10 12 14 17 18 29 31 37 46 50 60 61 65 68 70 78 82 84 85 90 91 94 98
+765180413: 3 5 11 12 14 18 20 21 23 26 27 29 30 34 35 38 39 44 45 47 48 50 51 56 57 59 62 66 67 71 72 73 74 75 77 80 82 84 85 86 89 92 93 95 97 98 99
+1238087663: 10 13 14 15 20 21 23 28 38 40 41 42 43 45 46 52 55 56 57 60 63 67 69 71 76 78 80 82 84 85 86 89 90 92
+2003267557: 2 13 14 18 20 22 23 24 31 32 34 37 38 41 43 47 50 54 59 60 67 69 79 80 85 87 91 93 96
+3241355263: 3 6 10 11 20 21 22 24 34 42 43 45 46 48 54 57 61 65 68 70 71 75 77 78 80 83 86 87 88 92 93 94
+5244622819: 10 15 17 23 29 31 35 38 40 50 57 60 65 67 68 71 73 74 75 79 90 92 94
+8485977589: 2 6 10 17 18 19 22 28 30 31 32 35 37 40 47 51 52 54 57 58 59 61 65 66 76 77 79 84 85 86 88 90 93 96 98
+13730600407: 3 5 10 12 19 24 33 35 40 42 43 45 46 51 54 55 65 73 75 76 78 80 82 84 87 89 92 93 94 96
+22216578047: 5 10 11 15 17 20 22 30 33 34 35 40 44 45 51 59 60 61 65 66 68 70 73 77 79 80 88 90 95 99
+35947178479: 3 12 14 15 22 24 29 30 38 41 44 51 54 55 56 58 63 69 70 73 76 78 89 91 95 96 97 99
+58163756537: 3 5 6 7 10 11 12 14 17 20 22 23 24 27 28 31 39 40 43 44 45 46 47 48 53 54 56 57 59 61 62 63 65 68 71 73 75 78 79 80 86 87 88 89 90 91 92 94 95 96 97 99
+94110934997: 2 3 5 8 11 12 14 18 19 20 21 23 26 27 29 30 32 34 35 39 41 43 44 48 51 56 59 62 66 67 71 72 74 75 76 77 79 80 84 85 92 93 94 98 99
+152274691561: 7 17 26 35 37 39 41 42 43 53 56 62 63 65 67 74 82 84 85 89 93 94
+246385626107UL: 2 5 6 8 11 14 15 18 20 23 24 26 29 31 32 33 34 35 37 38 42 43 44 45 50 54 56 60 61 65 67 69 71 72 77 78 80 82 83 85 87 89 92 93 94 95 96 98 99
+398660317687UL: 3 5 6 7 11 13 20 24 26 28 40 44 45 48 54 56 59 63 69 75 79 85 88 89 90 93 95 99
+645045943807UL: 3 5 10 12 21 22 23 24 26 35 37 40 41 44 45 47 51 52 53 59 70 75 79 85 87 92 93 95 96 97 99
+1043706260983UL: 3 7 11 24 28 29 (<= 32)
+1688752204787UL: 2 5 6 7 8 13 18 20 21 22 23 24 28 32 (<= 32)
+2732458465769UL: 3 6 11 12 13 15 17 19 21 22 23 24 26 27 30 31 (<= 32)
+4421210670577UL: 5 (<= 9)
+
+*/
+
+static const uintptr_t __CFBasicHashTableCapacities[64] = {
+    0, 3, 6, 11, 19, 32, 52, 85, 118, 155, 237, 390, 672, 1065,
+    1732, 2795, 4543, 7391, 12019, 19302, 31324, 50629, 81956,
+    132580, 214215, 346784, 561026, 907847, 1468567, 2376414,
+    3844982, 6221390, 10066379, 16287773, 26354132, 42641916,
+    68996399, 111638327, 180634415, 292272755,
+#if __LP64__
+    472907503UL, 765180257UL, 1238087439UL, 2003267722UL, 3241355160UL,
+    5244622578UL, 8485977737UL, 13730600347UL, 22216578100UL,
+    35947178453UL, 58163756541UL, 94110935011UL, 152274691274UL,
+    246385626296UL, 398660317578UL, 645045943559UL, 1043706261135UL,
+    1688752204693UL, 2732458465840UL, 4421210670552UL,
+    7153669136706UL, 11574879807265UL, 18728548943682UL
+#endif
+};
+
+// to expose the load factor, expose this function to customization
+CF_INLINE CFIndex __CFBasicHashGetCapacityForNumBuckets(CFBasicHashRef ht, CFIndex num_buckets_idx) {
+    return __CFBasicHashTableCapacities[num_buckets_idx];
+#if 0
+    CFIndex num_buckets = __CFBasicHashTableSizes[num_buckets_idx];
+    if (num_buckets_idx < 8) {
+        double dep = 0.0545665730357293074; // (1 - (sqrt(5) - 1) / 2) / 7
+        double factor = 1.0 - (num_buckets_idx - 1) * dep;
+        return (CFIndex)floor(num_buckets * factor + 0.375); // 0.375 is intentional
+    }
+    double factor = 0.6180339887498948482; // (sqrt(5) - 1) / 2
+    return (CFIndex)floor(num_buckets * factor + 0.5);
+#endif
+}
+
+CF_INLINE CFIndex __CFBasicHashGetNumBucketsIndexForCapacity(CFBasicHashRef ht, CFIndex capacity) {
+    for (CFIndex idx = 0; idx < 64; idx++) {
+        if (capacity <= __CFBasicHashGetCapacityForNumBuckets(ht, idx)) return idx;
+    }
+    HALT;
+    return 0;
+}
+
+__private_extern__ CFIndex CFBasicHashGetNumBuckets(CFBasicHashRef ht) {
+    return __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+}
+
+__private_extern__ CFIndex CFBasicHashGetCapacity(CFBasicHashRef ht) {
+    return __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx);
+}
+
+// In returned struct, .count is zero if the bucket is empty or deleted,
+// and the .weak_key field indicates which. .idx is either the index of
+// the found bucket or the index of the bucket which should be filled by
+// an add operation. For a set or multiset, the .weak_key and .weak_value
+// are the same.
+__private_extern__ CFBasicHashBucket CFBasicHashGetBucket(CFBasicHashRef ht, CFIndex idx) {
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFBasicHashBucket result;
+    result.idx = idx;
+    result.weak_value = __CFBasicHashGetValues(ht)[idx].weak;
+    result.weak_value2 = (0 != ht->bits.values2_offset) ? __CFBasicHashGetValues2(ht)[idx].weak : 0;
+    result.weak_key = (0 != ht->bits.keys_offset) ? __CFBasicHashGetKeys(ht)[idx].weak : result.weak_value;
+    result.weak_key2 = (0 != ht->bits.keys2_offset) ? __CFBasicHashGetKeys2(ht)[idx].weak : 0;
+    result.count = (0 != ht->bits.counts_offset) ? __CFBasicHashGetCounts(ht)[idx] : ((result.weak_key == empty || result.weak_key == deleted) ? 0 : 1);
+    result.order = (0 != ht->bits.orders_offset) ? __CFBasicHashGetOrders(ht)[idx] : 0;
+    return result;
+}
+
+// During rehashing of a mutable CFBasicHash, we know that there are no
+// deleted slots and the keys have already been uniqued. When rehashing,
+// if key_hash is non-0, we use it as the hash code.
+static CFBasicHashBucket ___CFBasicHashFindBucket1(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t key_hash, Boolean rehashing) {
+    CFHashCode hash_code = key_hash ? key_hash : __CFBasicHashHashKey(ht, stack_key);
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFBasicHashValue *keys = (0 != ht->bits.keys_offset) ? __CFBasicHashGetKeys(ht) : __CFBasicHashGetValues(ht);
+    uintptr_t *hashes = (0 != ht->bits.hashes_offset) ? __CFBasicHashGetHashes(ht) : NULL;
+    uintptr_t num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    CFBasicHashBucket result = {kCFNotFound, deleted, 0, deleted, 0, 0, 0};
+
+    uintptr_t h1 = 0;
+        // Linear probing, with c = 1
+        // probe[0] = h1(k)
+        // probe[i] = (h1(k) + i * c) mod num_buckets, i = 1 .. num_buckets - 1
+        // h1(k) = k mod num_buckets
+        h1 = hash_code % num_buckets;
+
+    COCOA_HASHTABLE_PROBING_START(ht, num_buckets);
+    uintptr_t probe = h1;
+    for (CFIndex idx = 0; idx < num_buckets; idx++) {
+        uintptr_t stack_curr = keys[probe].weak;
+        if (stack_curr == empty) {
+            COCOA_HASHTABLE_PROBE_EMPTY(ht, probe);
+            if (kCFNotFound == result.idx) {
+                result.idx = probe;
+                result.weak_value = empty;
+                result.weak_key = empty;
+            }
+            COCOA_HASHTABLE_PROBING_END(ht, idx + 1);
+            return result;
+        } else if (__builtin_expect(!rehashing, 0)) {
+            if (stack_curr == deleted) {
+                COCOA_HASHTABLE_PROBE_DELETED(ht, probe);
+                if (kCFNotFound == result.idx) {
+                    result.idx = probe;
+                }
+            } else {
+                COCOA_HASHTABLE_PROBE_VALID(ht, probe);
+                if (stack_curr == stack_key || ((!hashes || hashes[probe] == hash_code) && __CFBasicHashTestEqualKey(ht, stack_curr, stack_key))) {
+                    COCOA_HASHTABLE_PROBING_END(ht, idx + 1);
+                    result.idx = probe;
+                    result.weak_value = (0 != ht->bits.keys_offset) ? __CFBasicHashGetValues(ht)[probe].weak : stack_curr;
+                    result.weak_value2 = (0 != ht->bits.values2_offset) ? __CFBasicHashGetValues2(ht)[probe].weak : 0;
+                    result.weak_key = stack_curr;
+                    result.weak_key2 = (0 != ht->bits.keys2_offset) ? __CFBasicHashGetKeys2(ht)[probe].weak : 0;
+                    result.count = (0 != ht->bits.counts_offset) ? __CFBasicHashGetCounts(ht)[probe] : 1;
+                    result.order = (0 != ht->bits.orders_offset) ? __CFBasicHashGetOrders(ht)[probe] : 1;
+                    return result;
+                }
+            }
+        }
+        // Linear probing, with c = 1
+            probe += 1;
+            if (__builtin_expect(num_buckets <= probe, 0)) {
+                probe -= num_buckets;
+            }
+    }
+    COCOA_HASHTABLE_PROBING_END(ht, num_buckets);
+    return result; // all buckets full or deleted, return first deleted element which was found
+}
+
+static CFBasicHashBucket ___CFBasicHashFindBucket2(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t key_hash, Boolean rehashing) {
+    CFHashCode hash_code = key_hash ? key_hash : __CFBasicHashHashKey(ht, stack_key);
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFBasicHashValue *keys = (0 != ht->bits.keys_offset) ? __CFBasicHashGetKeys(ht) : __CFBasicHashGetValues(ht);
+    uintptr_t *hashes = (0 != ht->bits.hashes_offset) ? __CFBasicHashGetHashes(ht) : NULL;
+    uintptr_t num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    CFBasicHashBucket result = {kCFNotFound, deleted, 0, deleted, 0, 0, 0};
+
+    uintptr_t h1 = 0, h2 = 0;
+        // Double hashing
+        // probe[0] = h1(k)
+        // probe[i] = (h1(k) + i * h2(k)) mod num_buckets, i = 1 .. num_buckets - 1
+        // h1(k) = k mod num_buckets
+        // h2(k) = floor(k / num_buckets) mod num_buckets
+        h1 = hash_code % num_buckets;
+        h2 = (hash_code / num_buckets) % num_buckets;
+        if (0 == h2) h2 = num_buckets - 1;
+
+    COCOA_HASHTABLE_PROBING_START(ht, num_buckets);
+    uintptr_t probe = h1;
+    for (CFIndex idx = 0; idx < num_buckets; idx++) {
+        uintptr_t stack_curr = keys[probe].weak;
+        if (stack_curr == empty) {
+            COCOA_HASHTABLE_PROBE_EMPTY(ht, probe);
+            if (kCFNotFound == result.idx) {
+                result.idx = probe;
+                result.weak_value = empty;
+                result.weak_key = empty;
+            }
+            COCOA_HASHTABLE_PROBING_END(ht, idx + 1);
+            return result;
+        } else if (__builtin_expect(!rehashing, 0)) {
+            if (stack_curr == deleted) {
+                COCOA_HASHTABLE_PROBE_DELETED(ht, probe);
+                if (kCFNotFound == result.idx) {
+                    result.idx = probe;
+                }
+            } else {
+                COCOA_HASHTABLE_PROBE_VALID(ht, probe);
+                if (stack_curr == stack_key || ((!hashes || hashes[probe] == hash_code) && __CFBasicHashTestEqualKey(ht, stack_curr, stack_key))) {
+                    COCOA_HASHTABLE_PROBING_END(ht, idx + 1);
+                    result.idx = probe;
+                    result.weak_value = (0 != ht->bits.keys_offset) ? __CFBasicHashGetValues(ht)[probe].weak : stack_curr;
+                    result.weak_value2 = (0 != ht->bits.values2_offset) ? __CFBasicHashGetValues2(ht)[probe].weak : 0;
+                    result.weak_key = stack_curr;
+                    result.weak_key2 = (0 != ht->bits.keys2_offset) ? __CFBasicHashGetKeys2(ht)[probe].weak : 0;
+                    result.count = (0 != ht->bits.counts_offset) ? __CFBasicHashGetCounts(ht)[probe] : 1;
+                    result.order = (0 != ht->bits.orders_offset) ? __CFBasicHashGetOrders(ht)[probe] : 1;
+                    return result;
+                }
+            }
+        }
+        // Double hashing
+            probe += h2;
+            if (__builtin_expect(num_buckets <= probe, 1)) {
+                probe -= num_buckets;
+            }
+    }
+    COCOA_HASHTABLE_PROBING_END(ht, num_buckets);
+    return result; // all buckets full or deleted, return first deleted element which was found
+}
+
+static CFBasicHashBucket ___CFBasicHashFindBucket3(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t key_hash, Boolean rehashing) {
+    CFHashCode hash_code = key_hash ? key_hash : __CFBasicHashHashKey(ht, stack_key);
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFBasicHashValue *keys = (0 != ht->bits.keys_offset) ? __CFBasicHashGetKeys(ht) : __CFBasicHashGetValues(ht);
+    uintptr_t *hashes = (0 != ht->bits.hashes_offset) ? __CFBasicHashGetHashes(ht) : NULL;
+    uintptr_t num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    CFBasicHashBucket result = {kCFNotFound, deleted, 0, deleted, 0, 0, 0};
+
+    uintptr_t h1 = 0, h2 = 0, pr = 0;
+        // Improved exponential hashing
+        // probe[0] = h1(k)
+        // probe[i] = (h1(k) + pr(k)^i * h2(k)) mod num_buckets, i = 1 .. num_buckets - 1
+        // h1(k) = k mod num_buckets
+        // h2(k) = floor(k / num_buckets) mod num_buckets
+        // note: h2(k) has the effect of rotating the sequence if it is constant
+        // note: pr(k) is any primitive root of num_buckets, varying this gives different sequences
+        h1 = hash_code % num_buckets;
+        h2 = (hash_code / num_buckets) % num_buckets;
+        if (0 == h2) h2 = num_buckets - 1;
+        pr = __CFBasicHashPrimitiveRoots[ht->bits.num_buckets_idx];
+
+    COCOA_HASHTABLE_PROBING_START(ht, num_buckets);
+    uintptr_t probe = h1, acc = pr;
+    for (CFIndex idx = 0; idx < num_buckets; idx++) {
+        uintptr_t stack_curr = keys[probe].weak;
+        if (stack_curr == empty) {
+            COCOA_HASHTABLE_PROBE_EMPTY(ht, probe);
+            if (kCFNotFound == result.idx) {
+                result.idx = probe;
+                result.weak_value = empty;
+                result.weak_key = empty;
+            }
+            COCOA_HASHTABLE_PROBING_END(ht, idx + 1);
+            return result;
+        } else if (__builtin_expect(!rehashing, 0)) {
+            if (stack_curr == deleted) {
+                COCOA_HASHTABLE_PROBE_DELETED(ht, probe);
+                if (kCFNotFound == result.idx) {
+                    result.idx = probe;
+                }
+            } else {
+                COCOA_HASHTABLE_PROBE_VALID(ht, probe);
+                if (stack_curr == stack_key || ((!hashes || hashes[probe] == hash_code) && __CFBasicHashTestEqualKey(ht, stack_curr, stack_key))) {
+                    COCOA_HASHTABLE_PROBING_END(ht, idx + 1);
+                    result.idx = probe;
+                    result.weak_value = (0 != ht->bits.keys_offset) ? __CFBasicHashGetValues(ht)[probe].weak : stack_curr;
+                    result.weak_value2 = (0 != ht->bits.values2_offset) ? __CFBasicHashGetValues2(ht)[probe].weak : 0;
+                    result.weak_key = stack_curr;
+                    result.weak_key2 = (0 != ht->bits.keys2_offset) ? __CFBasicHashGetKeys2(ht)[probe].weak : 0;
+                    result.count = (0 != ht->bits.counts_offset) ? __CFBasicHashGetCounts(ht)[probe] : 1;
+                    result.order = (0 != ht->bits.orders_offset) ? __CFBasicHashGetOrders(ht)[probe] : 1;
+                    return result;
+                }
+            }
+        }
+        // Improved exponential hashing
+            probe = h1 + h2 * acc;
+            if (__builtin_expect(num_buckets <= probe, 1)) {
+                probe = probe % num_buckets;
+            }
+            acc = acc * pr;
+            if (__builtin_expect(num_buckets <= acc, 1)) {
+                acc = acc % num_buckets;
+            }
+    }
+    COCOA_HASHTABLE_PROBING_END(ht, num_buckets);
+    return result; // all buckets full or deleted, return first deleted element which was found
+}
+
+CF_INLINE CFBasicHashBucket ___CFBasicHashFindBucket(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t key_hash, Boolean rehashing) {
+    switch (ht->bits.hash_style) {
+    case __kCFBasicHashLinearHashingValue:
+        return ___CFBasicHashFindBucket1(ht, stack_key, 0, rehashing);
+    case __kCFBasicHashDoubleHashingValue:
+        return ___CFBasicHashFindBucket2(ht, stack_key, 0, rehashing);
+    case __kCFBasicHashExponentialHashingValue:
+        return ___CFBasicHashFindBucket3(ht, stack_key, 0, rehashing);
+    }
+    HALT;
+    CFBasicHashBucket result = {kCFNotFound, 0, 0, 0};
+    return result;
+}
+
+CF_INLINE CFBasicHashBucket __CFBasicHashFindBucket(CFBasicHashRef ht, uintptr_t stack_key) {
+    if (0 == ht->bits.num_buckets_idx) {
+        uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift);
+        CFBasicHashBucket result = {kCFNotFound, empty, empty, 0};
+        return result;
+    }
+    return ___CFBasicHashFindBucket(ht, stack_key, 0, false);
+}
+
+__private_extern__ CFBasicHashBucket CFBasicHashFindBucket(CFBasicHashRef ht, uintptr_t stack_key) {
+    return __CFBasicHashFindBucket(ht, stack_key);
+}
+
+__private_extern__ CFOptionFlags CFBasicHashGetFlags(CFBasicHashRef ht) {
+    CFOptionFlags flags = (ht->bits.hash_style << 13);
+    if (ht->bits.strong_values) flags |= kCFBasicHashStrongValues;
+    if (ht->bits.strong_values2) flags |= kCFBasicHashStrongValues2;
+    if (ht->bits.strong_keys) flags |= kCFBasicHashStrongKeys;
+    if (ht->bits.strong_keys2) flags |= kCFBasicHashStrongKeys2;
+    if (ht->bits.fast_grow) flags |= kCFBasicHashAggressiveGrowth;
+    if (ht->bits.values2_offset) flags |= kCFBasicHashHasValues2;
+    if (ht->bits.keys_offset) flags |= kCFBasicHashHasKeys;
+    if (ht->bits.keys2_offset) flags |= kCFBasicHashHasKeys2;
+    if (ht->bits.counts_offset) flags |= kCFBasicHashHasCounts;
+    if (ht->bits.orders_offset) flags |= kCFBasicHashHasOrder;
+    if (ht->bits.hashes_offset) flags |= kCFBasicHashHasHashCache;
+    return flags;
+}
+
+__private_extern__ CFIndex CFBasicHashGetCount(CFBasicHashRef ht) {
+    if (0 != ht->bits.counts_offset) {
+        CFIndex total = 0L;
+        CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+        uintptr_t *counts = __CFBasicHashGetCounts(ht);
+        for (CFIndex idx = 0; idx < cnt; idx++) {
+            total += counts[idx];
+        }
+        return total;
+    }
+    return (CFIndex)ht->bits.used_buckets;
+}
+
+__private_extern__ CFIndex CFBasicHashGetCountOfKey(CFBasicHashRef ht, uintptr_t stack_key) {
+    if (0L == ht->bits.used_buckets) {
+        return 0L;
+    }
+    return __CFBasicHashFindBucket(ht, stack_key).count;
+}
+
+__private_extern__ CFIndex CFBasicHashGetCountOfValue(CFBasicHashRef ht, uintptr_t stack_value) {
+    if (0L == ht->bits.used_buckets) {
+        return 0L;
+    }
+    if (!(0 != ht->bits.keys_offset)) {
+        return __CFBasicHashFindBucket(ht, stack_value).count;
+    }
+    __block CFIndex total = 0L;
+    CFBasicHashApply(ht, ^(CFBasicHashBucket bkt) {
+            if ((stack_value == bkt.weak_value) || __CFBasicHashTestEqualValue(ht, bkt.weak_value, stack_value)) total += bkt.count;
+            return (Boolean)true;
+        });
+    return total;
+}
+
+__private_extern__ Boolean CFBasicHashesAreEqual(CFBasicHashRef ht1, CFBasicHashRef ht2) {
+    CFIndex cnt1 = CFBasicHashGetCount(ht1);
+    if (cnt1 != CFBasicHashGetCount(ht2)) return false;
+    if (0 == cnt1) return true;
+    __block Boolean equal = true;
+    CFBasicHashApply(ht1, ^(CFBasicHashBucket bkt1) {
+            CFBasicHashBucket bkt2 = __CFBasicHashFindBucket(ht2, bkt1.weak_key);
+            if (bkt1.count != bkt2.count) {
+                equal = false;
+                return (Boolean)false;
+            }
+            if ((0 != ht1->bits.keys_offset) && (bkt1.weak_value != bkt2.weak_value) && !__CFBasicHashTestEqualValue(ht1, bkt1.weak_value, bkt2.weak_value)) {
+                equal = false;
+                return (Boolean)false;
+            }
+            return (Boolean)true;
+        });
+    return equal;
+}
+
+__private_extern__ void CFBasicHashApply(CFBasicHashRef ht, Boolean (^block)(CFBasicHashBucket)) {
+    CFIndex used = (CFIndex)ht->bits.used_buckets, cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    for (CFIndex idx = 0; 0 < used && idx < cnt; idx++) {
+        CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx);
+        if (0 < bkt.count) {
+            if (!block(bkt)) {
+                return;
+            }
+            used--;
+        }
+    }
+}
+
+__private_extern__ void CFBasicHashGetElements(CFBasicHashRef ht, CFIndex bufferslen, uintptr_t *weak_values, uintptr_t *weak_values2, uintptr_t *weak_keys, uintptr_t *weak_keys2) {
+    CFIndex used = (CFIndex)ht->bits.used_buckets, cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFBasicHashValue *values = __CFBasicHashGetValues(ht);
+    CFBasicHashValue *values2 = (0 != ht->bits.values2_offset) ? __CFBasicHashGetValues2(ht) : NULL;
+    CFBasicHashValue *keys = (0 != ht->bits.keys_offset) ? __CFBasicHashGetKeys(ht) : NULL;
+    CFBasicHashValue *keys2 = (0 != ht->bits.keys2_offset) ? __CFBasicHashGetKeys2(ht) : NULL;
+    uintptr_t *counts = (0 != ht->bits.counts_offset) ? __CFBasicHashGetCounts(ht) : NULL;
+    CFIndex offset = 0;
+    for (CFIndex idx = 0; 0 < used && idx < cnt && offset < bufferslen; idx++) {
+        uintptr_t weak_key = keys ? keys[idx].weak : values[idx].weak;
+        uintptr_t count = counts ? counts[idx] : ((weak_key == empty || weak_key == deleted) ? 0 : 1);
+        if (0 < count) {
+            used--;
+            for (CFIndex cnt = count; cnt-- && offset < bufferslen;) {
+                if (weak_values) { weak_values[offset] = values[idx].weak; }
+                if (weak_values2) { weak_values2[offset] = values2 ? values2[idx].weak : 0; }
+                if (weak_keys) { weak_keys[offset] = weak_key; }
+                if (weak_keys2) { weak_keys2[offset] = keys2 ? keys2[idx].weak : 0; }
+                offset++;
+            }
+        }
+    }
+}
+
+__private_extern__ unsigned long __CFBasicHashFastEnumeration(CFBasicHashRef ht, struct __objcFastEnumerationStateEquivalent2 *state, void *stackbuffer, unsigned long count) {
+    /* copy as many as count items over */
+    if (0 == state->state) {        /* first time */
+        state->mutationsPtr = (unsigned long *)&ht->bits + (__LP64__ ? 1 : 3);
+    }
+    state->itemsPtr = (unsigned long *)stackbuffer;
+    CFIndex cntx = 0;
+    CFIndex used = (CFIndex)ht->bits.used_buckets, cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    for (CFIndex idx = (CFIndex)state->state; 0 < used && idx < cnt && cntx < (CFIndex)count; idx++) {
+        CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx);
+        if (0 < bkt.count) {
+            state->itemsPtr[cntx++] = (unsigned long)bkt.weak_key;
+            used--;
+        }
+        state->state++;
+    }
+    return cntx;
+}
+
+#if ENABLE_MEMORY_COUNTERS
+static volatile int64_t __CFBasicHashTotalCount = 0ULL;
+static volatile int64_t __CFBasicHashTotalSize = 0ULL;
+static volatile int64_t __CFBasicHashPeakCount = 0ULL;
+static volatile int64_t __CFBasicHashPeakSize = 0ULL;
+static volatile int32_t __CFBasicHashSizes[64] = {0};
+#endif
+
+static void __CFBasicHashDrain(CFBasicHashRef ht, Boolean forFinalization) {
+#if ENABLE_MEMORY_COUNTERS
+    OSAtomicAdd64Barrier(-1 * (int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+#endif
+
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFIndex old_num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+
+    CFAllocatorRef allocator = CFGetAllocator(ht);
+    Boolean nullify = (!forFinalization || !CF_IS_COLLECTABLE_ALLOCATOR(allocator));
+
+    CFBasicHashValue *old_values = NULL, *old_values2 = NULL, *old_keys = NULL, *old_keys2 = NULL;
+    uintptr_t *old_counts = NULL, *old_orders = NULL, *old_hashes = NULL;
+
+    old_values = __CFBasicHashGetValues(ht);
+    if (nullify) __CFBasicHashSetValues(ht, NULL);
+    if (0 != ht->bits.values2_offset) {
+        old_values2 = __CFBasicHashGetValues2(ht);
+        if (nullify) __CFBasicHashSetValues2(ht, NULL);
+    }
+    if (0 != ht->bits.keys_offset) {
+        old_keys = __CFBasicHashGetKeys(ht);
+        if (nullify) __CFBasicHashSetKeys(ht, NULL);
+    }
+    if (0 != ht->bits.keys2_offset) {
+        old_keys2 = __CFBasicHashGetKeys2(ht);
+        if (nullify) __CFBasicHashSetKeys2(ht, NULL);
+    }
+    if (0 != ht->bits.counts_offset) {
+        old_counts = __CFBasicHashGetCounts(ht);
+        if (nullify) __CFBasicHashSetCounts(ht, NULL);
+    }
+    if (0 != ht->bits.orders_offset) {
+        old_orders = __CFBasicHashGetOrders(ht);
+        if (nullify) __CFBasicHashSetOrders(ht, NULL);
+    }
+    if (0 != ht->bits.hashes_offset) {
+        old_hashes = __CFBasicHashGetHashes(ht);
+        if (nullify) __CFBasicHashSetHashes(ht, NULL);
+    }
+
+    if (nullify) {
+        ht->bits.mutations++;
+        ht->bits.num_buckets_idx = 0;
+        ht->bits.used_buckets = 0;
+        ht->bits.marker = 0;
+        ht->bits.deleted = 0;
+    }
+    
+    if (ht->callbacks != &CFBasicHashNullCallbacks) {
+        CFBasicHashValue *keys = old_keys ? old_keys : old_values;
+        for (CFIndex idx = 0; idx < old_num_buckets; idx++) {
+            uintptr_t stack_key = keys[idx].weak;
+            if (stack_key != empty && stack_key != deleted) {
+                __CFBasicHashEjectValue(ht, old_values[idx].weak);
+                if (old_values2) {
+                    __CFBasicHashEjectValue2(ht, old_values2[idx].weak);
+                }
+                if (old_keys) {
+                    __CFBasicHashEjectKey(ht, old_keys[idx].weak);
+                }
+                if (old_keys2) {
+                    __CFBasicHashEjectKey2(ht, old_keys2[idx].weak);
+                }
+            }
+        }
+    }
+
+    if (forFinalization) {
+        ht->callbacks->func(ht, kCFBasicHashCallbackOpFreeCallbacks, (uintptr_t)allocator, 0, ht->callbacks);
+    }
+
+    if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+        CFAllocatorDeallocate(allocator, old_values);
+        CFAllocatorDeallocate(allocator, old_values2);
+        CFAllocatorDeallocate(allocator, old_keys);
+        CFAllocatorDeallocate(allocator, old_keys2);
+        CFAllocatorDeallocate(allocator, old_counts);
+        CFAllocatorDeallocate(allocator, old_orders);
+        CFAllocatorDeallocate(allocator, old_hashes);
+    }
+
+#if ENABLE_MEMORY_COUNTERS
+    int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+    while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+#endif
+}
+
+static void __CFBasicHashRehash(CFBasicHashRef ht, CFIndex newItemCount) {
+#if ENABLE_MEMORY_COUNTERS
+    OSAtomicAdd64Barrier(-1 * (int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+    OSAtomicAdd32Barrier(-1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+
+    if (COCOA_HASHTABLE_REHASH_START_ENABLED()) COCOA_HASHTABLE_REHASH_START(ht, CFBasicHashGetNumBuckets(ht), CFBasicHashGetSize(ht, true));
+
+    CFIndex new_num_buckets_idx = ht->bits.num_buckets_idx;
+    if (0 != newItemCount) {
+        if (newItemCount < 0) newItemCount = 0;
+        CFIndex new_capacity_req = ht->bits.used_buckets + newItemCount;
+        new_num_buckets_idx = __CFBasicHashGetNumBucketsIndexForCapacity(ht, new_capacity_req);
+        if (1 == newItemCount && ht->bits.fast_grow) {
+            new_num_buckets_idx++;
+        }
+    }
+
+    CFIndex new_num_buckets = __CFBasicHashTableSizes[new_num_buckets_idx];
+    CFIndex old_num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+
+    CFBasicHashValue *new_values = NULL, *new_values2 = NULL, *new_keys = NULL, *new_keys2 = NULL;
+    uintptr_t *new_counts = NULL, *new_orders = NULL, *new_hashes = NULL;
+
+    if (0 < new_num_buckets) {
+        new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), ht->bits.strong_values);
+        __SetLastAllocationEventName(new_values, "CFBasicHash (value-store)");
+        if (0 != ht->bits.values2_offset) {
+            new_values2 = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), ht->bits.strong_values2);
+            __SetLastAllocationEventName(new_values2, "CFBasicHash (value2-store)");
+        }
+        if (0 != ht->bits.keys_offset) {
+            new_keys = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), ht->bits.strong_keys);
+            __SetLastAllocationEventName(new_keys, "CFBasicHash (key-store)");
+        }
+        if (0 != ht->bits.keys2_offset) {
+            new_keys2 = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), ht->bits.strong_keys2);
+            __SetLastAllocationEventName(new_keys2, "CFBasicHash (key2-store)");
+        }
+        if (0 != ht->bits.counts_offset) {
+            new_counts = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false);
+            __SetLastAllocationEventName(new_counts, "CFBasicHash (count-store)");
+            memset(new_counts, 0, new_num_buckets * sizeof(uintptr_t));
+        }
+        if (0 != ht->bits.orders_offset) {
+            new_orders = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false);
+            __SetLastAllocationEventName(new_orders, "CFBasicHash (order-store)");
+            memset(new_orders, 0, new_num_buckets * sizeof(uintptr_t));
+        }
+        if (0 != ht->bits.hashes_offset) {
+            new_hashes = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false);
+            __SetLastAllocationEventName(new_hashes, "CFBasicHash (hash-store)");
+            memset(new_hashes, 0, new_num_buckets * sizeof(uintptr_t));
+        }
+    }
+
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    // if we knew the allocations were coming from already-cleared memory, and the marker was still 0, we could skip all this next stuff
+    for (CFIndex idx = 0; idx < new_num_buckets; idx++) {
+        if (ht->bits.strong_values) new_values[idx].strong = (id)empty; else new_values[idx].weak = empty;
+        if (new_values2) {
+            if (ht->bits.strong_values2) new_values2[idx].strong = (id)empty; else new_values2[idx].weak = empty;
+        }
+        if (new_keys) {
+            if (ht->bits.strong_keys) new_keys[idx].strong = (id)empty; else new_keys[idx].weak = empty;
+        }
+        if (new_keys2) {
+            if (ht->bits.strong_keys2) new_keys2[idx].strong = (id)empty; else new_keys2[idx].weak = empty;
+        }
+    }
+
+    ht->bits.num_buckets_idx = new_num_buckets_idx;
+    ht->bits.deleted = 0;
+
+    CFBasicHashValue *old_values = NULL, *old_values2 = NULL, *old_keys = NULL, *old_keys2 = NULL;
+    uintptr_t *old_counts = NULL, *old_orders = NULL, *old_hashes = NULL;
+
+    old_values = __CFBasicHashGetValues(ht);
+    __CFBasicHashSetValues(ht, new_values);
+    if (0 != ht->bits.values2_offset) {
+        old_values2 = __CFBasicHashGetValues2(ht);
+        __CFBasicHashSetValues2(ht, new_values2);
+    }
+    if (0 != ht->bits.keys_offset) {
+        old_keys = __CFBasicHashGetKeys(ht);
+        __CFBasicHashSetKeys(ht, new_keys);
+    }
+    if (0 != ht->bits.keys2_offset) {
+        old_keys2 = __CFBasicHashGetKeys2(ht);
+        __CFBasicHashSetKeys2(ht, new_keys2);
+    }
+    if (0 != ht->bits.counts_offset) {
+        old_counts = __CFBasicHashGetCounts(ht);
+        __CFBasicHashSetCounts(ht, new_counts);
+    }
+    if (0 != ht->bits.orders_offset) {
+        old_orders = __CFBasicHashGetOrders(ht);
+        __CFBasicHashSetOrders(ht, new_orders);
+    }
+    if (0 != ht->bits.hashes_offset) {
+        old_hashes = __CFBasicHashGetHashes(ht);
+        __CFBasicHashSetHashes(ht, new_hashes);
+    }
+
+    if (0 < old_num_buckets) {
+        CFBasicHashValue *keys = old_keys ? old_keys : old_values;
+        for (CFIndex idx = 0; idx < old_num_buckets; idx++) {
+            uintptr_t stack_key = keys[idx].weak;
+            if (stack_key != empty && stack_key != deleted) {
+                CFBasicHashBucket bkt = ___CFBasicHashFindBucket(ht, stack_key, old_hashes ? old_hashes[idx] : 0, true);
+                uintptr_t stack_value = old_values[idx].weak;
+                if (ht->bits.strong_values) new_values[bkt.idx].strong = (id)stack_value; else new_values[bkt.idx].weak = stack_value;
+                if (old_values2) {
+                    if (ht->bits.strong_values2) new_values2[bkt.idx].strong = (id)old_values2[idx].weak; else new_values2[bkt.idx].weak = old_values2[idx].weak;
+                }
+                if (old_keys) {
+                    if (ht->bits.strong_keys) new_keys[bkt.idx].strong = (id)stack_key; else new_keys[bkt.idx].weak = stack_key;
+                }
+                if (old_keys2) {
+                    if (ht->bits.strong_keys2) new_keys2[bkt.idx].strong = (id)old_keys2[idx].weak; else new_keys2[bkt.idx].weak = old_keys2[idx].weak;
+                }
+                if (old_counts) {
+                    new_counts[bkt.idx] = old_counts[idx];
+                }
+                if (old_orders) {
+                    new_orders[bkt.idx] = old_orders[idx];
+                }
+                if (old_hashes) {
+                    new_hashes[bkt.idx] = old_hashes[idx];
+                }
+            }
+        }
+    }
+
+    CFAllocatorRef allocator = CFGetAllocator(ht);
+    if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+        CFAllocatorDeallocate(allocator, old_values);
+        CFAllocatorDeallocate(allocator, old_values2);
+        CFAllocatorDeallocate(allocator, old_keys);
+        CFAllocatorDeallocate(allocator, old_keys2);
+        CFAllocatorDeallocate(allocator, old_counts);
+        CFAllocatorDeallocate(allocator, old_orders);
+        CFAllocatorDeallocate(allocator, old_hashes);
+    }
+
+    if (COCOA_HASHTABLE_REHASH_END_ENABLED()) COCOA_HASHTABLE_REHASH_END(ht, CFBasicHashGetNumBuckets(ht), CFBasicHashGetSize(ht, true));
+
+#if ENABLE_MEMORY_COUNTERS
+    int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), &__CFBasicHashTotalSize);
+    while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+    OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+}
+
+__private_extern__ void CFBasicHashSetCapacity(CFBasicHashRef ht, CFIndex capacity) {
+    if (!CFBasicHashIsMutable(ht)) HALT;
+    if (ht->bits.used_buckets < capacity) {
+        ht->bits.mutations++;
+        __CFBasicHashRehash(ht, capacity - ht->bits.used_buckets);
+    }
+}
+
+static void __CFBasicHashFindNewMarker(CFBasicHashRef ht, uintptr_t stack_key) {
+    uintptr_t marker = ht->bits.marker;
+    uintptr_t empty = (marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFBasicHashValue *keys = (0 != ht->bits.keys_offset) ? __CFBasicHashGetKeys(ht) : __CFBasicHashGetValues(ht);
+    Boolean strong = (0 != ht->bits.keys_offset) ? ht->bits.strong_keys : ht->bits.strong_values;
+    CFIndex cnt = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    if (0 == marker) marker = 4096;
+
+    again:;
+    marker++;
+    if ((1UL << 26) <= marker) HALT;
+    uintptr_t new_empty = (marker << __CFBasicHashMarkerShift), new_deleted = ~new_empty;
+    if (stack_key == new_empty || stack_key == new_deleted) {
+        goto again;
+    }
+    for (CFIndex idx = 0; idx < cnt; idx++) {
+        uintptr_t stack_curr = strong ? (uintptr_t)keys[idx].strong : keys[idx].weak;
+        if (stack_curr == new_empty || stack_curr == new_deleted) {
+            goto again;
+        }
+    }
+    for (CFIndex idx = 0; idx < cnt; idx++) {
+        uintptr_t stack_curr = strong ? (uintptr_t)keys[idx].strong : keys[idx].weak;
+        if (stack_curr == empty) {
+            if (strong) keys[idx].strong = (id)new_empty; else keys[idx].weak = new_empty;
+        } else if (stack_curr == deleted) {
+            if (strong) keys[idx].strong = (id)new_deleted; else keys[idx].weak = new_deleted;
+        }
+    }
+    ht->bits.marker = marker;
+}
+
+static void __CFBasicHashAddValue(CFBasicHashRef ht, CFBasicHashBucket bkt, uintptr_t stack_key, uintptr_t stack_key2, uintptr_t stack_value, uintptr_t stack_value2) {
+    ht->bits.mutations++;
+    stack_value = __CFBasicHashImportValue(ht, stack_value);
+    if (0 != ht->bits.keys_offset) {
+        stack_key = __CFBasicHashImportKey(ht, stack_key);
+    } else {
+        stack_key = stack_value;
+    }
+    if (0 != ht->bits.values2_offset) {
+        stack_value2 = __CFBasicHashImportValue2(ht, stack_value2);
+    }
+    if (0 != ht->bits.keys2_offset) {
+        stack_key2 = __CFBasicHashImportKey2(ht, stack_key2);
+    }
+    if (CFBasicHashGetCapacity(ht) < ht->bits.used_buckets + 1) {
+        __CFBasicHashRehash(ht, 1);
+        bkt = ___CFBasicHashFindBucket(ht, stack_key, 0, true);
+    }
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    if (bkt.weak_key == deleted) {
+        ht->bits.deleted--;
+    }
+    if (stack_key == empty || stack_key == deleted) {
+        __CFBasicHashFindNewMarker(ht, stack_key);
+    }
+    CFBasicHashValue *value = &(__CFBasicHashGetValues(ht)[bkt.idx]);
+    if (ht->bits.strong_values) value->strong = (id)stack_value; else value->weak = stack_value;
+    if (0 != ht->bits.values2_offset) {
+        CFBasicHashValue *value2 = &(__CFBasicHashGetValues2(ht)[bkt.idx]);
+        if (ht->bits.strong_values2) value2->strong = (id)stack_value2; else value2->weak = stack_value2;
+    }
+    if (0 != ht->bits.keys_offset) {
+        CFBasicHashValue *key = &(__CFBasicHashGetKeys(ht)[bkt.idx]);
+        if (ht->bits.strong_keys) key->strong = (id)stack_key; else key->weak = stack_key;
+    }
+    if (0 != ht->bits.keys2_offset) {
+        CFBasicHashValue *key2 = &(__CFBasicHashGetKeys2(ht)[bkt.idx]);
+        if (ht->bits.strong_keys2) key2->strong = (id)stack_key2; else key2->weak = stack_key2;
+    }
+    if (0 != ht->bits.counts_offset) {
+        __CFBasicHashGetCounts(ht)[bkt.idx] = 1;
+    }
+    if (0 != ht->bits.orders_offset) {
+        __CFBasicHashGetOrders(ht)[bkt.idx] = 0;
+    }
+    if (ht->bits.hashes_offset) {
+        __CFBasicHashGetHashes(ht)[bkt.idx] = __CFBasicHashHashKey(ht, stack_key);
+    }
+    ht->bits.used_buckets++;
+}
+
+static void __CFBasicHashReplaceValue(CFBasicHashRef ht, CFBasicHashBucket bkt, uintptr_t stack_key, uintptr_t stack_key2, uintptr_t stack_value, uintptr_t stack_value2) {
+    ht->bits.mutations++;
+    stack_value = __CFBasicHashImportValue(ht, stack_value);
+    if (0 != ht->bits.keys_offset) {
+        stack_key = __CFBasicHashImportKey(ht, stack_key);
+    } else {
+        stack_key = stack_value;
+    }
+    if (0 != ht->bits.values2_offset) {
+        stack_value2 = __CFBasicHashImportValue2(ht, stack_value2);
+    }
+    if (0 != ht->bits.keys2_offset) {
+        stack_key2 = __CFBasicHashImportKey2(ht, stack_key2);
+    }
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    if (stack_key == empty || stack_key == deleted) {
+        __CFBasicHashFindNewMarker(ht, stack_key);
+    }
+    CFBasicHashValue *value = &(__CFBasicHashGetValues(ht)[bkt.idx]);
+    uintptr_t old_value = value->weak;
+    if (ht->bits.strong_values) value->strong = (id)stack_value; else value->weak = stack_value;
+    __CFBasicHashEjectValue(ht, old_value);
+    if (0 != ht->bits.values2_offset) {
+        CFBasicHashValue *value2 = &(__CFBasicHashGetValues2(ht)[bkt.idx]);
+        uintptr_t old_value2 = value2->weak;
+        if (ht->bits.strong_values2) value2->strong = (id)stack_value2; else value2->weak = stack_value2;
+        __CFBasicHashEjectValue2(ht, old_value2);
+    }
+    if (0 != ht->bits.keys_offset) {
+        CFBasicHashValue *key = &(__CFBasicHashGetKeys(ht)[bkt.idx]);
+        uintptr_t old_key = key->weak;
+        if (ht->bits.strong_keys) key->strong = (id)stack_key; else key->weak = stack_key;
+        __CFBasicHashEjectKey(ht, old_key);
+    }
+    if (0 != ht->bits.keys2_offset) {
+        CFBasicHashValue *key2 = &(__CFBasicHashGetKeys2(ht)[bkt.idx]);
+        uintptr_t old_key2 = key2->weak;
+        if (ht->bits.strong_keys2) key2->strong = (id)stack_key2; else key2->weak = stack_key2;
+        __CFBasicHashEjectKey2(ht, old_key2);
+    }
+}
+
+static void __CFBasicHashRemoveValue(CFBasicHashRef ht, CFBasicHashBucket bkt, uintptr_t stack_key, uintptr_t stack_key2) {
+    ht->bits.mutations++;
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFBasicHashValue *value = &(__CFBasicHashGetValues(ht)[bkt.idx]);
+    uintptr_t old_value = value->weak;
+    if (ht->bits.strong_values) value->strong = (id)deleted; else value->weak = deleted;
+    __CFBasicHashEjectValue(ht, old_value);
+    if (0 != ht->bits.values2_offset) {
+        CFBasicHashValue *value2 = &(__CFBasicHashGetValues2(ht)[bkt.idx]);
+        uintptr_t old_value2 = value2->weak;
+        if (ht->bits.strong_values2) value2->strong = (id)deleted; else value2->weak = deleted;
+        __CFBasicHashEjectValue2(ht, old_value2);
+    }
+    if (0 != ht->bits.keys_offset) {
+        CFBasicHashValue *key = &(__CFBasicHashGetKeys(ht)[bkt.idx]);
+        uintptr_t old_key = key->weak;
+        if (ht->bits.strong_keys) key->strong = (id)deleted; else key->weak = deleted;
+        __CFBasicHashEjectKey(ht, old_key);
+    }
+    if (0 != ht->bits.keys2_offset) {
+        CFBasicHashValue *key2 = &(__CFBasicHashGetKeys2(ht)[bkt.idx]);
+        uintptr_t old_key2 = key2->weak;
+        if (ht->bits.strong_keys2) key2->strong = (id)deleted; else key2->weak = deleted;
+        __CFBasicHashEjectKey2(ht, old_key2);
+    }
+    if (0 != ht->bits.counts_offset) {
+        __CFBasicHashGetCounts(ht)[bkt.idx] = 0;
+    }
+    if (0 != ht->bits.orders_offset) {
+        __CFBasicHashGetOrders(ht)[bkt.idx] = 0;
+    }
+    if (ht->bits.hashes_offset) {
+        __CFBasicHashGetHashes(ht)[bkt.idx] = 0;
+    }
+    ht->bits.used_buckets--;
+    ht->bits.deleted++;
+    Boolean do_shrink = false;
+    if (ht->bits.fast_grow) { // == slow shrink
+        do_shrink = (5 < ht->bits.num_buckets_idx && ht->bits.used_buckets < __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx - 5));
+    } else {
+        do_shrink = (2 < ht->bits.num_buckets_idx && ht->bits.used_buckets < __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx - 2));
+    }
+    if (do_shrink) {
+        __CFBasicHashRehash(ht, -1);
+        return;
+    }
+    do_shrink = (0 == ht->bits.deleted); // .deleted roll-over
+    CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    do_shrink = do_shrink || ((20 <= num_buckets) && (num_buckets / 4 <= ht->bits.deleted));
+    if (do_shrink) {
+        __CFBasicHashRehash(ht, 0);
+    }
+}
+
+__private_extern__ void CFBasicHashAddValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) {
+    if (!CFBasicHashIsMutable(ht)) HALT;
+    CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
+    if (0 < bkt.count) {
+        ht->bits.mutations++;
+        if (0 != ht->bits.counts_offset) {
+            __CFBasicHashGetCounts(ht)[bkt.idx]++;
+        }
+    } else {
+        __CFBasicHashAddValue(ht, bkt, stack_key, 0, stack_value, 0);
+    }
+}
+
+__private_extern__ void CFBasicHashReplaceValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) {
+    if (!CFBasicHashIsMutable(ht)) HALT;
+    CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
+    if (0 < bkt.count) {
+        __CFBasicHashReplaceValue(ht, bkt, stack_key, 0, stack_value, 0);
+    }
+}
+
+__private_extern__ void CFBasicHashSetValue(CFBasicHashRef ht, uintptr_t stack_key, uintptr_t stack_value) {
+    if (!CFBasicHashIsMutable(ht)) HALT;
+    CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
+    if (0 < bkt.count) {
+        __CFBasicHashReplaceValue(ht, bkt, stack_key, 0, stack_value, 0);
+    } else {
+        __CFBasicHashAddValue(ht, bkt, stack_key, 0, stack_value, 0);
+    }
+}
+
+__private_extern__ CFIndex CFBasicHashRemoveValue(CFBasicHashRef ht, uintptr_t stack_key) {
+    if (!CFBasicHashIsMutable(ht)) HALT;
+    CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
+    if (1 < bkt.count) {
+        ht->bits.mutations++;
+        if (0 != ht->bits.counts_offset) {
+            __CFBasicHashGetCounts(ht)[bkt.idx]--;
+        }
+    } else if (0 < bkt.count) {
+        __CFBasicHashRemoveValue(ht, bkt, stack_key, 0);
+    }
+    return bkt.count;
+}
+
+__private_extern__ void CFBasicHashRemoveAllValues(CFBasicHashRef ht) {
+    if (!CFBasicHashIsMutable(ht)) HALT;
+    if (0 == ht->bits.num_buckets_idx) return;
+    __CFBasicHashDrain(ht, false);
+}
+
+__private_extern__ size_t CFBasicHashGetSize(CFBasicHashRef ht, Boolean total) {
+    size_t size = sizeof(struct __CFBasicHash);
+    if (0 != ht->bits.values2_offset) size += sizeof(CFBasicHashValue *);
+    if (0 != ht->bits.keys_offset) size += sizeof(CFBasicHashValue *);
+    if (0 != ht->bits.keys2_offset) size += sizeof(CFBasicHashValue *);
+    if (0 != ht->bits.counts_offset) size += sizeof(uintptr_t *);
+    if (0 != ht->bits.orders_offset) size += sizeof(uintptr_t *);
+    if (0 != ht->bits.hashes_offset) size += sizeof(uintptr_t *);
+    if (total) {
+        CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+        if (0 < num_buckets) {
+            size += malloc_size(__CFBasicHashGetValues(ht));
+            if (0 != ht->bits.values2_offset) size += malloc_size(__CFBasicHashGetValues2(ht));
+            if (0 != ht->bits.keys_offset) size += malloc_size(__CFBasicHashGetKeys(ht));
+            if (0 != ht->bits.keys2_offset) size += malloc_size(__CFBasicHashGetKeys2(ht));
+            if (0 != ht->bits.counts_offset) size += malloc_size(__CFBasicHashGetCounts(ht));
+            if (0 != ht->bits.orders_offset) size += malloc_size(__CFBasicHashGetOrders(ht));
+            if (0 != ht->bits.hashes_offset) size += malloc_size(__CFBasicHashGetHashes(ht));
+            size += malloc_size((void *)ht->callbacks);
+        }
+    }
+    return size;
+}
+
+__private_extern__ CFStringRef CFBasicHashCopyDescription(CFBasicHashRef ht, Boolean detailed, CFStringRef prefix, CFStringRef entryPrefix, Boolean describeElements) {
+    CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+    CFStringAppendFormat(result, NULL, CFSTR("%@{type = %s %s%s, count = %ld,\n"), prefix, (CFBasicHashIsMutable(ht) ? "mutable" : "immutable"), ((0 != ht->bits.counts_offset) ? "multi" : ""), ((0 != ht->bits.keys_offset) ? "dict" : "set"), CFBasicHashGetCount(ht));
+    if (detailed) {
+        const char *cb_type = "custom";
+        if (&CFBasicHashNullCallbacks == ht->callbacks) {
+            cb_type = "null";
+        } else if (&CFBasicHashStandardCallbacks == ht->callbacks) {
+            cb_type = "standard";
+        }
+        CFStringAppendFormat(result, NULL, CFSTR("%@hash cache = %s, strong values = %s, strong keys = %s, cb = %s,\n"), prefix, ((0 != ht->bits.hashes_offset) ? "yes" : "no"), (ht->bits.strong_values ? "yes" : "no"), (ht->bits.strong_keys ? "yes" : "no"), cb_type);
+        CFStringAppendFormat(result, NULL, CFSTR("%@num bucket index = %d, num buckets = %ld, capacity = %ld, num buckets used = %ld,\n"), prefix, ht->bits.num_buckets_idx, CFBasicHashGetNumBuckets(ht), CFBasicHashGetCapacity(ht), ht->bits.used_buckets);
+        uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+        CFStringAppendFormat(result, NULL, CFSTR("%@empty marker = 0x%lx, deleted marker = 0x%lx, finalized = %s,\n"), prefix, empty, deleted, (ht->bits.finalized ? "yes" : "no"));
+        CFStringAppendFormat(result, NULL, CFSTR("%@num mutations = %ld, num deleted = %ld, size = %ld, total size = %ld,\n"), prefix, ht->bits.mutations, ht->bits.deleted, CFBasicHashGetSize(ht, false), CFBasicHashGetSize(ht, true));
+        CFStringAppendFormat(result, NULL, CFSTR("%@values ptr = %p, keys ptr = %p, counts ptr = %p, hashes ptr = %p,\n"), prefix, __CFBasicHashGetValues(ht), ((0 != ht->bits.keys_offset) ? __CFBasicHashGetKeys(ht) : NULL), ((0 != ht->bits.counts_offset) ? __CFBasicHashGetCounts(ht) : NULL), ((0 != ht->bits.hashes_offset) ? __CFBasicHashGetHashes(ht) : NULL));
+    }
+    CFStringAppendFormat(result, NULL, CFSTR("%@entries =>\n"), prefix);
+    CFBasicHashApply(ht, ^(CFBasicHashBucket bkt) {
+            CFStringRef vDesc = NULL, kDesc = NULL;
+            CFBasicHashCallbackType cb = ht->callbacks->func;
+            if (!describeElements) cb = __CFBasicHashNullCallback;
+            vDesc = (CFStringRef)cb(ht, kCFBasicHashCallbackOpDescribeValue, bkt.weak_value, 0, ht->callbacks);
+            if (0 != ht->bits.keys_offset) {
+                kDesc = (CFStringRef)cb(ht, kCFBasicHashCallbackOpDescribeKey, bkt.weak_key, 0, ht->callbacks);
+            }
+            if ((0 != ht->bits.keys_offset) && (0 != ht->bits.counts_offset)) {
+                CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ = %@ (%ld)\n"), entryPrefix, bkt.idx, kDesc, vDesc, bkt.count);
+            } else if (0 != ht->bits.keys_offset) {
+                CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ = %@\n"), entryPrefix, bkt.idx, kDesc, vDesc);
+            } else if (0 != ht->bits.counts_offset) {
+                CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ (%ld)\n"), entryPrefix, bkt.idx, vDesc, bkt.count);
+            } else {
+                CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@\n"), entryPrefix, bkt.idx, vDesc);
+            }
+            if (kDesc) CFRelease(kDesc);
+            if (vDesc) CFRelease(vDesc);
+            return (Boolean)true;
+        });
+    CFStringAppendFormat(result, NULL, CFSTR("%@}\n"), prefix);
+    return result;
+}
+
+__private_extern__ void CFBasicHashShow(CFBasicHashRef ht) {
+    CFStringRef str = CFBasicHashCopyDescription(ht, true, CFSTR(""), CFSTR("\t"), false);
+    CFShow(str);
+    CFRelease(str);
+}
+
+__private_extern__ Boolean __CFBasicHashEqual(CFTypeRef cf1, CFTypeRef cf2) {
+    CFBasicHashRef ht1 = (CFBasicHashRef)cf1;
+    CFBasicHashRef ht2 = (CFBasicHashRef)cf2;
+//#warning this used to require that the key and value equal callbacks were pointer identical
+    return CFBasicHashesAreEqual(ht1, ht2);
+}
+
+__private_extern__ CFHashCode __CFBasicHashHash(CFTypeRef cf) {
+    CFBasicHashRef ht = (CFBasicHashRef)cf;
+    return CFBasicHashGetCount(ht);
+}
+
+__private_extern__ CFStringRef __CFBasicHashCopyDescription(CFTypeRef cf) {
+    CFBasicHashRef ht = (CFBasicHashRef)cf;
+    CFStringRef desc = CFBasicHashCopyDescription(ht, false, CFSTR(""), CFSTR("\t"), true);
+    CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFBasicHash %p [%p]>%@"), cf, CFGetAllocator(cf), desc);
+    CFRelease(desc);
+    return result;
+}
+
+__private_extern__ void __CFBasicHashDeallocate(CFTypeRef cf) {
+    CFBasicHashRef ht = (CFBasicHashRef)cf;
+    if (ht->bits.finalized) HALT;
+    ht->bits.finalized = 1;
+    __CFBasicHashDrain(ht, true);
+#if ENABLE_MEMORY_COUNTERS
+    OSAtomicAdd64Barrier(-1, &__CFBasicHashTotalCount);
+    OSAtomicAdd32Barrier(-1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+}
+
+static CFTypeID __kCFBasicHashTypeID = _kCFRuntimeNotATypeID;
+
+static const CFRuntimeClass __CFBasicHashClass = {
+    _kCFRuntimeScannedObject,
+    "CFBasicHash",
+    NULL,        // init
+    NULL,        // copy
+    __CFBasicHashDeallocate,
+    __CFBasicHashEqual,
+    __CFBasicHashHash,
+    NULL,        //
+    __CFBasicHashCopyDescription
+};
+
+__private_extern__ CFTypeID CFBasicHashGetTypeID(void) {
+    if (_kCFRuntimeNotATypeID == __kCFBasicHashTypeID) __kCFBasicHashTypeID = _CFRuntimeRegisterClass(&__CFBasicHashClass);
+    return __kCFBasicHashTypeID;
+}
+
+CFBasicHashRef CFBasicHashCreate(CFAllocatorRef allocator, CFOptionFlags flags, const CFBasicHashCallbacks *cb) {
+    size_t size = sizeof(struct __CFBasicHash) - sizeof(CFRuntimeBase);
+    if (flags & kCFBasicHashHasValues2) size += sizeof(CFBasicHashValue *); // values2
+    if (flags & kCFBasicHashHasKeys) size += sizeof(CFBasicHashValue *); // keys
+    if (flags & kCFBasicHashHasKeys2) size += sizeof(CFBasicHashValue *); // keys2
+    if (flags & kCFBasicHashHasCounts) size += sizeof(uintptr_t *); // counts
+    if (flags & kCFBasicHashHasOrder) size += sizeof(uintptr_t *); // order
+    if (flags & kCFBasicHashHasHashCache) size += sizeof(uintptr_t *); // hashes
+    CFBasicHashRef ht = (CFBasicHashRef)_CFRuntimeCreateInstance(allocator, CFBasicHashGetTypeID(), size, NULL);
+    if (NULL == ht) HALT;
+
+    ht->bits.finalized = 0;
+    ht->bits.strong_values = (flags & kCFBasicHashStrongValues) ? 1 : 0;
+    ht->bits.strong_values2 = 0;
+    ht->bits.strong_keys = (flags & kCFBasicHashStrongKeys) ? 1 : 0;
+    ht->bits.strong_keys2 = 0;
+    ht->bits.hash_style = (flags >> 13) & 0x3;
+    ht->bits.fast_grow = (flags & kCFBasicHashAggressiveGrowth) ? 1 : 0;
+    ht->bits.__0 = 0;
+    ht->bits.num_buckets_idx = 0;
+    ht->bits.used_buckets = 0;
+    ht->bits.marker = 0;
+    ht->bits.deleted = 0;
+    ht->bits.mutations = 1;
+
+    uint64_t offset = 1;
+    ht->bits.values2_offset = 0;
+    ht->bits.keys_offset = (flags & kCFBasicHashHasKeys) ? offset++ : 0;
+    ht->bits.keys2_offset = 0;
+    ht->bits.counts_offset = (flags & kCFBasicHashHasCounts) ? offset++ : 0;
+    ht->bits.orders_offset = 0;
+    ht->bits.hashes_offset = (flags & kCFBasicHashHasHashCache) ? offset++ : 0;
+
+    __AssignWithWriteBarrier(&ht->callbacks, cb);
+    for (CFIndex idx = 0; idx < offset; idx++) {
+        ht->pointers[idx] = NULL;
+    }
+
+#if ENABLE_MEMORY_COUNTERS
+    int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+    while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+    int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
+    while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
+    OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+
+    return ht;
+}
+
+CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFBasicHashRef src_ht) {
+    size_t size = CFBasicHashGetSize(src_ht, false) - sizeof(CFRuntimeBase);
+    CFBasicHashRef ht = (CFBasicHashRef)_CFRuntimeCreateInstance(allocator, CFBasicHashGetTypeID(), size, NULL);
+    if (NULL == ht) HALT;
+
+    memmove((uint8_t *)ht + sizeof(CFRuntimeBase), (uint8_t *)src_ht + sizeof(CFRuntimeBase), sizeof(ht->bits));
+    if (kCFUseCollectableAllocator && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+        ht->bits.strong_values = 0;
+        ht->bits.strong_values2 = 0;
+        ht->bits.strong_keys = 0;
+        ht->bits.strong_keys2 = 0;
+    }
+    ht->bits.finalized = 0;
+    ht->bits.mutations = 1;
+    __AssignWithWriteBarrier(&ht->callbacks, src_ht->callbacks->func(ht, kCFBasicHashCallbackOpCopyCallbacks, (uintptr_t)allocator, 0, src_ht->callbacks));
+    if (NULL == ht->callbacks) HALT;
+
+    CFIndex new_num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+    if (0 == new_num_buckets) {
+#if ENABLE_MEMORY_COUNTERS
+        int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+        while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+        int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
+        while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
+        OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+        return ht;
+    }
+
+    CFBasicHashValue *new_values = NULL, *new_values2 = NULL, *new_keys = NULL, *new_keys2 = NULL;
+    uintptr_t *new_counts = NULL, *new_orders = NULL, *new_hashes = NULL;
+
+    if (0 < new_num_buckets) {
+        new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), ht->bits.strong_values);
+        __SetLastAllocationEventName(new_values, "CFBasicHash (value-store)");
+        if (0 != ht->bits.values2_offset) {
+            new_values2 = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), ht->bits.strong_values2);
+            __SetLastAllocationEventName(new_values2, "CFBasicHash (value2-store)");
+        }
+        if (0 != ht->bits.keys_offset) {
+            new_keys = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), ht->bits.strong_keys);
+            __SetLastAllocationEventName(new_keys, "CFBasicHash (key-store)");
+        }
+        if (0 != ht->bits.keys2_offset) {
+            new_keys2 = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), ht->bits.strong_keys2);
+            __SetLastAllocationEventName(new_keys2, "CFBasicHash (key2-store)");
+        }
+        if (0 != ht->bits.counts_offset) {
+            new_counts = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false);
+            __SetLastAllocationEventName(new_counts, "CFBasicHash (count-store)");
+        }
+        if (0 != ht->bits.orders_offset) {
+            new_orders = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false);
+            __SetLastAllocationEventName(new_orders, "CFBasicHash (order-store)");
+        }
+        if (0 != ht->bits.hashes_offset) {
+            new_hashes = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false);
+            __SetLastAllocationEventName(new_hashes, "CFBasicHash (hash-store)");
+        }
+    }
+
+    uintptr_t empty = ((uintptr_t)ht->bits.marker << __CFBasicHashMarkerShift), deleted = ~empty;
+    CFBasicHashValue *old_values = NULL, *old_values2 = NULL, *old_keys = NULL, *old_keys2 = NULL;
+    uintptr_t *old_counts = NULL, *old_orders = NULL, *old_hashes = NULL;
+    old_values = __CFBasicHashGetValues(src_ht);
+    if (0 != src_ht->bits.values2_offset) {
+        old_values2 = __CFBasicHashGetValues2(src_ht);
+    }
+    if (0 != src_ht->bits.keys_offset) {
+        old_keys = __CFBasicHashGetKeys(src_ht);
+    }
+    if (0 != src_ht->bits.keys2_offset) {
+        old_keys2 = __CFBasicHashGetKeys2(src_ht);
+    }
+    if (0 != src_ht->bits.counts_offset) {
+        old_counts = __CFBasicHashGetCounts(src_ht);
+    }
+    if (0 != src_ht->bits.orders_offset) {
+        old_orders = __CFBasicHashGetOrders(src_ht);
+    }
+    if (0 != src_ht->bits.hashes_offset) {
+        old_hashes = __CFBasicHashGetHashes(src_ht);
+    }
+
+    CFBasicHashValue *keys = old_keys ? old_keys : old_values;
+    for (CFIndex idx = 0; idx < new_num_buckets; idx++) {
+        uintptr_t stack_key = keys[idx].weak;
+        if (stack_key != empty && stack_key != deleted) {
+            uintptr_t stack_value = __CFBasicHashImportValue(ht, old_values[idx].weak);
+            if (ht->bits.strong_values) new_values[idx].strong = (id)stack_value; else new_values[idx].weak = stack_value;
+            if (new_values2) {
+                uintptr_t stack_value2 = __CFBasicHashImportValue2(ht, old_values2[idx].weak);
+                if (ht->bits.strong_values2) new_values2[idx].strong = (id)stack_value2; else new_values2[idx].weak = stack_value2;
+            }
+            if (new_keys) {
+                uintptr_t stack_key = __CFBasicHashImportKey(ht, old_keys[idx].weak);
+                if (ht->bits.strong_keys) new_keys[idx].strong = (id)stack_key; else new_keys[idx].weak = stack_key;
+            }
+            if (new_keys2) {
+                uintptr_t stack_key2 = __CFBasicHashImportKey2(ht, old_keys2[idx].weak);
+                if (ht->bits.strong_keys2) new_keys2[idx].strong = (id)stack_key2; else new_keys2[idx].weak = stack_key2;
+            }
+        } else {
+            if (ht->bits.strong_values) new_values[idx].strong = (id)stack_key; else new_values[idx].weak = stack_key;
+            if (new_values2) {
+                if (ht->bits.strong_values2) new_values2[idx].strong = (id)stack_key; else new_values2[idx].weak = stack_key;
+            }
+            if (new_keys) {
+                if (ht->bits.strong_keys) new_keys[idx].strong = (id)stack_key; else new_keys[idx].weak = stack_key;
+            }
+            if (new_keys2) {
+                if (ht->bits.strong_keys2) new_keys2[idx].strong = (id)stack_key; else new_keys2[idx].weak = stack_key;
+            }
+        }
+    }
+    if (new_counts) memmove(new_counts, old_counts, new_num_buckets * sizeof(uintptr_t));
+    if (new_orders) memmove(new_orders, old_orders, new_num_buckets * sizeof(uintptr_t));
+    if (new_hashes) memmove(new_hashes, old_hashes, new_num_buckets * sizeof(uintptr_t));
+
+    __CFBasicHashSetValues(ht, new_values);
+    if (new_values2) {
+        __CFBasicHashSetValues2(ht, new_values2);
+    }
+    if (new_keys) {
+        __CFBasicHashSetKeys(ht, new_keys);
+    }
+    if (new_keys2) {
+        __CFBasicHashSetKeys2(ht, new_keys2);
+    }
+    if (new_counts) {
+        __CFBasicHashSetCounts(ht, new_counts);
+    }
+    if (new_orders) {
+        __CFBasicHashSetOrders(ht, new_orders);
+    }
+    if (new_hashes) {
+        __CFBasicHashSetHashes(ht, new_hashes);
+    }
+
+#if ENABLE_MEMORY_COUNTERS
+    int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+    while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+    int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
+    while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
+    OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+
+    return ht;
+}
+
+void _CFbhx588461(CFBasicHashRef ht, Boolean growth) {
+    if (!CFBasicHashIsMutable(ht)) HALT;
+    if (ht->bits.finalized) HALT;
+    ht->bits.fast_grow = growth ? 1 : 0;
+}
+
index 6e5f5a6285037c3584241d4e5515ede1eb913241..bd16c75901adb58bc959781b94ca59461946a181 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBinaryHeap.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #include <CoreFoundation/CFBinaryHeap.h>
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
 
 const CFBinaryHeapCallBacks kCFStringBinaryHeapCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, (CFComparisonResult (*)(const void *, const void *, void *))CFStringCompare};
@@ -235,7 +235,7 @@ static CFBinaryHeapRef __CFBinaryHeapInit(CFAllocatorRef allocator, UInt32 flags
        __CFBinaryHeapSetCapacity(memory, __CFBinaryHeapRoundUpCapacity(1));
        __CFBinaryHeapSetNumBuckets(memory, __CFBinaryHeapNumBucketsForCapacity(__CFBinaryHeapRoundUpCapacity(1)));
        void *buckets = _CFAllocatorAllocateGC(allocator, __CFBinaryHeapNumBuckets(memory) * sizeof(struct __CFBinaryHeapBucket), isStrongMemory_Heap(memory) ? __kCFAllocatorGCScannedMemory : 0);
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, memory, memory->_buckets, buckets);
+       __CFAssignWithWriteBarrier((void **)&memory->_buckets, buckets);
        if (__CFOASafe) __CFSetLastAllocationEventName(memory->_buckets, "CFBinaryHeap (store)");
        if (NULL == memory->_buckets) {
            CFRelease(memory);
@@ -254,12 +254,13 @@ static CFBinaryHeapRef __CFBinaryHeapInit(CFAllocatorRef allocator, UInt32 flags
        memory->_callbacks.copyDescription = 0;
        memory->_callbacks.compare = 0;
     }
+    if (compareContext) memcpy(&memory->_context, compareContext, sizeof(CFBinaryHeapCompareContext));
+// CF: retain info for proper operation
     __CFBinaryHeapSetMutableVariety(memory, kCFBinaryHeapMutable);
     for (idx = 0; idx < numValues; idx++) {
        CFBinaryHeapAddValue(memory, values[idx]);
     }
     __CFBinaryHeapSetMutableVariety(memory, __CFBinaryHeapMutableVarietyFromFlags(flags));
-    if (compareContext) memcpy(&memory->_context, compareContext, sizeof(CFBinaryHeapCompareContext));
     return memory;
 }
 
@@ -318,7 +319,7 @@ const void *CFBinaryHeapGetMinimum(CFBinaryHeapRef heap) {
 Boolean CFBinaryHeapGetMinimumIfPresent(CFBinaryHeapRef heap, const void **value) {
     __CFGenericValidateType(heap, __kCFBinaryHeapTypeID);
     if (0 == __CFBinaryHeapCount(heap)) return false;
-    if (NULL != value) __CFObjCStrongAssign(heap->_buckets[0]._item, value);
+    if (NULL != value) __CFAssignWithWriteBarrier((void **)&heap->_buckets[0]._item, value);
     return true;
 }
 
@@ -330,10 +331,6 @@ void CFBinaryHeapGetValues(CFBinaryHeapRef heap, const void **values) {
     CFAssert1(NULL != values, __kCFLogAssertion, "%s(): pointer to values may not be NULL", __PRETTY_FUNCTION__);
     cnt = __CFBinaryHeapCount(heap);
     if (0 == cnt) return;
-    if (CF_USING_COLLECTABLE_MEMORY) {
-       // GC: speculatively issue a write-barrier on the copied to buffers (3743553).
-       __CFObjCWriteBarrierRange(values, cnt * sizeof(void *));
-    }
     heapCopy = CFBinaryHeapCreateCopy(CFGetAllocator(heap), cnt, heap);
     idx = 0;
     while (0 < __CFBinaryHeapCount(heapCopy)) {
@@ -367,7 +364,7 @@ static void __CFBinaryHeapGrow(CFBinaryHeapRef heap, CFIndex numNewValues) {
     __CFBinaryHeapSetCapacity(heap, capacity);
     __CFBinaryHeapSetNumBuckets(heap, __CFBinaryHeapNumBucketsForCapacity(capacity));
     void *buckets = _CFAllocatorReallocateGC(allocator, heap->_buckets, __CFBinaryHeapNumBuckets(heap) * sizeof(struct __CFBinaryHeapBucket), isStrongMemory_Heap(heap) ? __kCFAllocatorGCScannedMemory : 0);
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, heap, heap->_buckets, buckets);
+    __CFAssignWithWriteBarrier((void **)&heap->_buckets, buckets);
     if (__CFOASafe) __CFSetLastAllocationEventName(heap->_buckets, "CFBinaryHeap (store)");
     if (NULL == heap->_buckets) HALT;
 }
@@ -387,18 +384,19 @@ void CFBinaryHeapAddValue(CFBinaryHeapRef heap, const void *value) {
     idx = cnt;
     __CFBinaryHeapSetNumBucketsUsed(heap, cnt + 1);
     __CFBinaryHeapSetCount(heap, cnt + 1);
+    CFComparisonResult (*compare)(const void *, const void *, void *) = heap->_callbacks.compare;
     pidx = (idx - 1) >> 1;
     while (0 < idx) {
        void *item = heap->_buckets[pidx]._item;
-       if (kCFCompareGreaterThan != heap->_callbacks.compare(item, value, heap->_context.info)) break;
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, heap->_buckets, heap->_buckets[idx]._item, item);
+       if ((!compare && item <= value) || (compare && kCFCompareGreaterThan != compare(item, value, heap->_context.info))) break;
+       __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, item);
        idx = pidx;
        pidx = (idx - 1) >> 1;
     }
     if (heap->_callbacks.retain) {
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, heap->_buckets, heap->_buckets[idx]._item, (void *)heap->_callbacks.retain(allocator, (void *)value));
+       __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, (void *)heap->_callbacks.retain(allocator, (void *)value));
     } else {
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, heap->_buckets, heap->_buckets[idx]._item, (void *)value);
+       __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, (void *)value);
     }
 }
 
@@ -413,6 +411,7 @@ void CFBinaryHeapRemoveMinimumValue(CFBinaryHeapRef heap) {
     idx = 0;
     __CFBinaryHeapSetNumBucketsUsed(heap, cnt - 1);
     __CFBinaryHeapSetCount(heap, cnt - 1);
+    CFComparisonResult (*compare)(const void *, const void *, void *) = heap->_callbacks.compare;
     allocator = CFGetAllocator(heap);
     if (heap->_callbacks.release)
        heap->_callbacks.release(allocator, heap->_buckets[idx]._item);
@@ -422,17 +421,17 @@ void CFBinaryHeapRemoveMinimumValue(CFBinaryHeapRef heap) {
        void *item = heap->_buckets[cidx]._item;
        if (cidx + 1 < __CFBinaryHeapCount(heap)) {
            void *item2 = heap->_buckets[cidx + 1]._item;
-           if (kCFCompareGreaterThan == heap->_callbacks.compare(item, item2, heap->_context.info)) {
+           if ((!compare && item > item2) || (compare && kCFCompareGreaterThan == compare(item, item2, heap->_context.info))) {
                cidx++;
                item = item2;
            }
        }
-       if (kCFCompareGreaterThan == heap->_callbacks.compare(item, val, heap->_context.info)) break;
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, heap->_buckets, heap->_buckets[idx]._item, item);
+       if ((!compare && item > val) || (compare && kCFCompareGreaterThan == compare(item, val, heap->_context.info))) break;
+       __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, item);
        idx = cidx;
        cidx = (idx << 1) + 1;
     }
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, heap->_buckets, heap->_buckets[idx]._item, val);
+    __CFAssignWithWriteBarrier((void **)&heap->_buckets[idx]._item, val);
 }
 
 void CFBinaryHeapRemoveAllValues(CFBinaryHeapRef heap) {
index b26e45713d9823a5e0039f7a8b1c01e5e73031d9..9195dede6a5ce1b2562af3b167b42da8df784654 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBinaryHeap.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 /*!
         @header CFBinaryHeap
index 8cbbf003153fed0d731aac892655b36cd03f4c78..a07d155c9e1069c681ac02a7d9812c3ba64e98ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,8 +21,8 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBinaryPList.c
-       Copyright 2000-2002, Apple, Inc. All rights reserved.
-       Responsibility: Christopher Kane
+       Copyright (c) 2000-2009, Apple Inc. All rights reserved.
+       Responsibility: Tony Parker
 */
 
 
@@ -30,6 +30,7 @@
 #include <CoreFoundation/CFNumber.h>
 #include <CoreFoundation/CFDate.h>
 #include <CoreFoundation/CFData.h>
+#include <CoreFoundation/CFError.h>
 #include <CoreFoundation/CFArray.h>
 #include <CoreFoundation/CFDictionary.h>
 #include <CoreFoundation/CFSet.h>
@@ -50,7 +51,8 @@ enum {
     kCFNumberSInt128Type = 17
 };
 
-extern CFNumberType _CFNumberGetType2(CFNumberRef number);
+CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number);
+__private_extern__ CFErrorRef __CFPropertyListCreateError(CFAllocatorRef allocator, CFIndex code, CFStringRef debugString, ...);
 
 enum {
        CF_NO_ERROR = 0,
@@ -153,7 +155,7 @@ uint32_t _CFKeyedArchiverUIDGetValue(CFKeyedArchiverUIDRef uid) {
 
 typedef struct {
     CFTypeRef stream;
-    CFTypeRef error;
+    CFErrorRef error;
     uint64_t written;
     int32_t used;
     bool streamIsData;
@@ -241,6 +243,36 @@ TRAILER
 static CFTypeID stringtype = -1, datatype = -1, numbertype = -1, datetype = -1;
 static CFTypeID booltype = -1, nulltype = -1, dicttype = -1, arraytype = -1, settype = -1;
 
+static void initStatics() {
+    if ((CFTypeID)-1 == stringtype) {
+        stringtype = CFStringGetTypeID();
+    }
+    if ((CFTypeID)-1 == datatype) {
+        datatype = CFDataGetTypeID();
+    }
+    if ((CFTypeID)-1 == numbertype) {
+        numbertype = CFNumberGetTypeID();
+    }
+    if ((CFTypeID)-1 == booltype) {
+        booltype = CFBooleanGetTypeID();
+    }
+    if ((CFTypeID)-1 == datetype) {
+        datetype = CFDateGetTypeID();
+    }
+    if ((CFTypeID)-1 == dicttype) {
+        dicttype = CFDictionaryGetTypeID();
+    }
+    if ((CFTypeID)-1 == arraytype) {
+        arraytype = CFArrayGetTypeID();
+    }
+    if ((CFTypeID)-1 == settype) {
+        settype = CFSetGetTypeID();
+    }
+    if ((CFTypeID)-1 == nulltype) {
+        nulltype = CFNullGetTypeID();
+    }
+}
+
 static void _appendInt(__CFBinaryPlistWriteBuffer *buf, uint64_t bigint) {
     uint8_t marker;
     uint8_t *bytes;
@@ -285,20 +317,7 @@ static void _appendUID(__CFBinaryPlistWriteBuffer *buf, CFKeyedArchiverUIDRef ui
     bufferWrite(buf, bytes, nbytes);
 }
 
-static Boolean __plistNumberEqual(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 (CFNumberIsFloatType((CFNumberRef)cf1) != CFNumberIsFloatType((CFNumberRef)cf2)) return false;
-    return CFEqual(cf1, cf2);
-}
-
-static CFHashCode __plistDataHash(CFTypeRef cf) {
-    CFDataRef data = (CFDataRef)cf;
-    return CFHashBytes((UInt8 *)CFDataGetBytePtr(data), __CFMin(CFDataGetLength(data), 1280));
-}
-
-static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CFMutableDictionaryRef objtable, CFMutableSetRef uniquingsets[]) {
+static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CFMutableDictionaryRef objtable, CFMutableSetRef uniquingset) {
     CFPropertyListRef unique;
     uint32_t refnum;
     CFTypeID type = __CFGenericTypeID_genericobj_inline(plist);
@@ -308,18 +327,7 @@ static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CF
     // 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 (datetype == type) {
-       which = 2;
-    } else if (datatype == type) {
-       which = 3;
-    }
-    if (1 && -1 != which) {
-       CFMutableSetRef uniquingset = uniquingsets[which];
+    if (stringtype == type || numbertype == type || datetype == type || datatype == type) {
        CFIndex before = CFSetGetCount(uniquingset);
        CFSetAddValue(uniquingset, plist);
        CFIndex after = CFSetGetCount(uniquingset);
@@ -340,7 +348,7 @@ static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CF
        list = (count <= 128) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), 0);
         CFDictionaryGetKeysAndValues((CFDictionaryRef)plist, list, list + count);
         for (idx = 0; idx < 2 * count; idx++) {
-            _flattenPlist(list[idx], objlist, objtable, uniquingsets);
+            _flattenPlist(list[idx], objlist, objtable, uniquingset);
         }
         if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
     } else if (arraytype == type) {
@@ -348,77 +356,61 @@ static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CF
        list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, count * sizeof(CFTypeRef), 0);
         CFArrayGetValues((CFArrayRef)plist, CFRangeMake(0, count), list);
         for (idx = 0; idx < count; idx++) {
-            _flattenPlist(list[idx], objlist, objtable, uniquingsets);
+            _flattenPlist(list[idx], objlist, objtable, uniquingset);
         }
         if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
     }
 }
 
+/* Get the number of bytes required to hold the value in 'count'. Will return a power of 2 value big enough to hold 'count'.
+ */
+CF_INLINE uint8_t _byteCount(uint64_t count) {
+    uint64_t mask = ~(uint64_t)0;
+    uint8_t size = 0;
+    
+    // Find something big enough to hold 'count'
+    while (count & mask) {
+        size++;
+        mask = mask << 8;
+    }
+    
+    // Ensure that 'count' is a power of 2
+    // For sizes bigger than 8, just use the required count
+    while ((size != 1 && size != 2 && size != 4 && size != 8) && size <= 8) {
+        size++;
+    }
+    
+    return size;
+}
+
+
 // stream must be a CFMutableDataRef
-CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream) {
+/* Write a property list to a stream, in binary format. plist is the property list to write (one of the basic property list types), stream is the destination of the property list, and estimate is a best-guess at the total number of objects in the property list. The estimate parameter is for efficiency in pre-allocating memory for the uniquing step. Pass in a 0 if no estimate is available. The options flag specifies sort options. If the error parameter is non-NULL and an error occurs, it will be used to return a CFError explaining the problem. It is the callers responsibility to release the error. */
+CFIndex __CFBinaryPlistWrite(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate, CFOptionFlags options, CFErrorRef *error) {
     CFMutableDictionaryRef objtable;
     CFMutableArrayRef objlist;
+    CFMutableSetRef uniquingset;
     CFBinaryPlistTrailer trailer;
     uint64_t *offsets, length_so_far;
-    uint64_t mask, refnum;
+    uint64_t refnum;
     int64_t idx, idx2, cnt;
     __CFBinaryPlistWriteBuffer *buf;
-
-    if ((CFTypeID)-1 == stringtype) {
-       stringtype = CFStringGetTypeID();
-    }
-    if ((CFTypeID)-1 == datatype) {
-       datatype = CFDataGetTypeID();
-    }
-    if ((CFTypeID)-1 == numbertype) {
-       numbertype = CFNumberGetTypeID();
-    }
-    if ((CFTypeID)-1 == booltype) {
-       booltype = CFBooleanGetTypeID();
-    }
-    if ((CFTypeID)-1 == datetype) {
-       datetype = CFDateGetTypeID();
-    }
-    if ((CFTypeID)-1 == dicttype) {
-       dicttype = CFDictionaryGetTypeID();
-    }
-    if ((CFTypeID)-1 == arraytype) {
-       arraytype = CFArrayGetTypeID();
-    }
-    if ((CFTypeID)-1 == settype) {
-       settype = CFSetGetTypeID();
-    }
-    if ((CFTypeID)-1 == nulltype) {
-       nulltype = CFNullGetTypeID();
-    }
+    
+    initStatics();
 
     objtable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, NULL);
-    _CFDictionarySetCapacity(objtable, 640);
     objlist = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
-    _CFArraySetCapacity(objlist, 640);
-    CFSetCallBacks cb = kCFTypeSetCallBacks;
-    cb.retain = NULL;
-    cb.release = NULL;
-    CFMutableSetRef uniquingsets[4];
-    uniquingsets[0] = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
-    _CFSetSetCapacity(uniquingsets[0], 1000);
-    cb.equal = __plistNumberEqual;
-    uniquingsets[1] = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
-    _CFSetSetCapacity(uniquingsets[1], 500);
-    cb.equal = kCFTypeSetCallBacks.equal;
-    uniquingsets[2] = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
-    _CFSetSetCapacity(uniquingsets[2], 500);
-    cb.hash = __plistDataHash;
-    uniquingsets[3] = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &cb);
-    _CFSetSetCapacity(uniquingsets[3], 500);
-
-    _flattenPlist(plist, objlist, objtable, uniquingsets);
-
-    CFRelease(uniquingsets[0]);
-    CFRelease(uniquingsets[1]);
-    CFRelease(uniquingsets[2]);
-    CFRelease(uniquingsets[3]);
+    uniquingset = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
+#if DEPLOYMENT_TARGET_MACOSX
+    _CFDictionarySetCapacity(objtable, estimate ? estimate : 650);
+    _CFArraySetCapacity(objlist, estimate ? estimate : 650);
+    _CFSetSetCapacity(uniquingset, estimate ? estimate : 1000);
+#endif
+
+    _flattenPlist(plist, objlist, objtable, uniquingset);
 
+    CFRelease(uniquingset);
+    
     cnt = CFArrayGetCount(objlist);
     offsets = (uint64_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, (CFIndex)(cnt * sizeof(*offsets)), 0);
 
@@ -433,12 +425,7 @@ CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream)
     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;
-    }
-
+    trailer._objectRefSize = _byteCount(cnt);    
     for (idx = 0; idx < cnt; idx++) {
        CFPropertyListRef obj = CFArrayGetValueAtIndex(objlist, (CFIndex)idx);
        CFTypeID type = __CFGenericTypeID_genericobj_inline(obj);
@@ -540,24 +527,27 @@ CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream)
            swapped = CFConvertFloat64HostToSwapped(CFDateGetAbsoluteTime((CFDateRef)obj));
            bufferWrite(buf, (uint8_t *)&swapped, sizeof(swapped));
        } else if (dicttype == type) {
-           CFIndex count = CFDictionaryGetCount((CFDictionaryRef)obj);
-           CFPropertyListRef *list, buffer[512];
-           uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerDict | (count < 15 ? count : 0xf));
-           bufferWrite(buf, &marker, 1);
-           if (15 <= count) {
-               _appendInt(buf, (uint64_t)count);
-           }
-           list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), 0);
-           CFDictionaryGetKeysAndValues((CFDictionaryRef)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;
+            CFIndex count = CFDictionaryGetCount((CFDictionaryRef)obj);
+
+            uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerDict | (count < 15 ? count : 0xf));
+            bufferWrite(buf, &marker, 1);
+            if (15 <= count) {
+                _appendInt(buf, (uint64_t)count);
+            }
+            
+            CFPropertyListRef *list, buffer[512];
+
+            list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2 * count * sizeof(CFTypeRef), 0);
+            CFDictionaryGetKeysAndValues((CFDictionaryRef)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)(uintptr_t)CFDictionaryGetValue(objtable, value);
                 swapped = CFSwapInt32HostToBig((uint32_t)refnum);
-               bufferWrite(buf, source + sizeof(swapped) - trailer._objectRefSize, trailer._objectRefSize);
-           }
-           if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
+                bufferWrite(buf, source + sizeof(swapped) - trailer._objectRefSize, trailer._objectRefSize);
+            }
+            if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
        } else if (arraytype == type) {
            CFIndex count = CFArrayGetCount((CFArrayRef)obj);
            CFPropertyListRef *list, buffer[256];
@@ -580,7 +570,13 @@ CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream)
        } else {
            CFRelease(objtable);
            CFRelease(objlist);
-           if (buf->error) CFRelease(buf->error);
+           if (error && buf->error) {
+               // caller will release error
+               *error = buf->error;
+           } else if (buf->error) {
+               // caller is not interested in error, release it here
+               CFRelease(buf->error);
+           }
            CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf);
             CFAllocatorDeallocate(kCFAllocatorSystemDefault, offsets);
            return 0;
@@ -588,16 +584,11 @@ CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream)
     }
     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;
-    }
-
+    trailer._offsetIntSize = _byteCount(length_so_far);
+    
     for (idx = 0; idx < cnt; idx++) {
        uint64_t swapped = CFSwapInt64HostToBig(offsets[idx]);
        uint8_t *source = (uint8_t *)&swapped;
@@ -609,7 +600,12 @@ CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream)
     bufferFlush(buf);
     length_so_far += sizeof(trailer);
     if (buf->error) {
-       CFRelease(buf->error);
+       if (error) {
+           // caller will release error
+           *error = buf->error;
+       } else {
+           CFRelease(buf->error);
+       }
        return 0;
     }
     CFAllocatorDeallocate(kCFAllocatorSystemDefault, buf);
@@ -618,44 +614,64 @@ CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream)
 }
 
 
+CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream) {
+    return __CFBinaryPlistWrite(plist, stream, 0, 0, NULL);
+}
+
+// to be removed soon
+CFIndex __CFBinaryPlistWriteToStreamWithEstimate(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate) {
+    return __CFBinaryPlistWrite(plist, stream, estimate, 0, NULL);
+}
+
+// to be removed soon
+CFIndex __CFBinaryPlistWriteToStreamWithOptions(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate, CFOptionFlags options) {
+    return __CFBinaryPlistWrite(plist, stream, estimate, options, NULL);
+}
+
 #define FAIL_FALSE     do { return false; } while (0)
 #define FAIL_MAXOFFSET do { return UINT64_MAX; } while (0)
 
+/* Grab a valSize-bytes integer out of the buffer pointed at by data and return it.
+ */
+CF_INLINE uint64_t _getSizedInt(const uint8_t *data, uint8_t valSize) {
+    if (valSize == 1) {
+        return (uint64_t)*data;
+    } else if (valSize == 2) {
+        uint16_t val = *(uint16_t *)data;
+        return (uint64_t)CFSwapInt16BigToHost(val);
+    } else if (valSize == 4) {
+        uint32_t val = *(uint32_t *)data;
+        return (uint64_t)CFSwapInt32BigToHost(val);
+    } else if (valSize == 8) {
+        uint64_t val = *(uint64_t *)data;
+        return CFSwapInt64BigToHost(val);
+    } else {
+        // Compatability with existing archives, including anything with a non-power-of-2 size and 16-byte values
+        uint64_t res = 0;
+        for (CFIndex idx = 0; idx < valSize; idx++) {
+            res = (res << 8) + data[idx];
+        }
+        return res;
+    }
+    // shouldn't get here
+    return 0;
+}
+
 bool __CFBinaryPlistGetTopLevelInfo(const uint8_t *databytes, uint64_t datalen, uint8_t *marker, uint64_t *offset, CFBinaryPlistTrailer *trailer) {
     CFBinaryPlistTrailer trail;
 
-    if ((CFTypeID)-1 == stringtype) {
-       stringtype = CFStringGetTypeID();
-    }
-    if ((CFTypeID)-1 == datatype) {
-       datatype = CFDataGetTypeID();
-    }
-    if ((CFTypeID)-1 == numbertype) {
-       numbertype = CFNumberGetTypeID();
-    }
-    if ((CFTypeID)-1 == booltype) {
-       booltype = CFBooleanGetTypeID();
-    }
-    if ((CFTypeID)-1 == datetype) {
-       datetype = CFDateGetTypeID();
-    }
-    if ((CFTypeID)-1 == dicttype) {
-       dicttype = CFDictionaryGetTypeID();
-    }
-    if ((CFTypeID)-1 == arraytype) {
-       arraytype = CFArrayGetTypeID();
-    }
-    if ((CFTypeID)-1 == settype) {
-       settype = CFSetGetTypeID();
-    }
-    if ((CFTypeID)-1 == nulltype) {
-       nulltype = CFNullGetTypeID();
-    }
+    initStatics();
 
     if (!databytes || datalen < sizeof(trail) + 8 + 1) FAIL_FALSE;
-    if (0 != memcmp("bplist00", databytes, 8) && 0 != memcmp("bplist01", databytes, 8)) return false;
+    // Tiger and earlier will parse "bplist00"
+    // Leopard will parse "bplist00" or "bplist01"
+    // SnowLeopard will parse "bplist0?" where ? is any one character
+    if (0 != memcmp("bplist0", databytes, 7)) {
+       return false;
+    }
     memmove(&trail, databytes + datalen - sizeof(trail), sizeof(trail));
-    if (trail._unused[0] != 0 || trail._unused[1] != 0 || trail._unused[2] != 0 || trail._unused[3] != 0 || trail._unused[4] != 0 || trail._unused[5] != 0) FAIL_FALSE;
+    // In Leopard, the unused bytes in the trailer must be 0 or the parse will fail
+    // This check is not present in Tiger and earlier or after Leopard
     trail._numObjects = CFSwapInt64BigToHost(trail._numObjects);
     trail._topObject = CFSwapInt64BigToHost(trail._topObject);
     trail._offsetTableOffset = CFSwapInt64BigToHost(trail._offsetTableOffset);
@@ -692,19 +708,13 @@ bool __CFBinaryPlistGetTopLevelInfo(const uint8_t *databytes, uint64_t datalen,
     const uint8_t *bytesptr = databytes + trail._offsetTableOffset;
     uint64_t maxOffset = trail._offsetTableOffset - 1;
     for (CFIndex idx = 0; idx < trail._numObjects; idx++) {
-       uint64_t off = 0;
-       for (CFIndex idx2 = 0; idx2 < trail._offsetIntSize; idx2++) {
-           off = (off << 8) + bytesptr[idx2];
-       }
+       uint64_t off = _getSizedInt(bytesptr, trail._offsetIntSize);
        if (maxOffset < off) FAIL_FALSE;
        bytesptr += trail._offsetIntSize;
     }
 
     bytesptr = databytes + trail._offsetTableOffset + trail._topObject * trail._offsetIntSize;
-    uint64_t off = 0;
-    for (CFIndex idx = 0; idx < trail._offsetIntSize; idx++) {
-       off = (off << 8) + bytesptr[idx];
-    }
+    uint64_t off = _getSizedInt(bytesptr, trail._offsetIntSize);
     if (off < 8 || trail._offsetTableOffset <= off) FAIL_FALSE;
     if (trailer) *trailer = trail;
     if (offset) *offset = off;
@@ -728,10 +738,8 @@ CF_INLINE bool _readInt(const uint8_t *ptr, const uint8_t *end_byte_ptr, uint64_
     if (CF_NO_ERROR != err) FAIL_FALSE;
     if (end_byte_ptr < extent) FAIL_FALSE;
     // integers are not required to be in the most compact possible representation, but only the last 64 bits are significant currently
-    *bigint = 0;
-    for (CFIndex idx = 0; idx < cnt; idx++) {
-       *bigint = (*bigint << 8) + *ptr++;
-    }
+    *bigint = _getSizedInt(ptr, cnt);
+    ptr += cnt;
     if (newptr) *newptr = ptr;
     return true;
 }
@@ -745,22 +753,14 @@ CF_INLINE uint64_t _getOffsetOfRefAt(const uint8_t *databytes, const uint8_t *by
     const uint8_t *offsetsFirstByte = databytes + trailer->_offsetTableOffset;
     if (bytesptr < objectsFirstByte || offsetsFirstByte - trailer->_objectRefSize < bytesptr) FAIL_MAXOFFSET;
 
-    uint64_t ref = 0;
-    for (CFIndex idx = 0; idx < trailer->_objectRefSize; idx++) {
-       ref = (ref << 8) + bytesptr[idx];
-    }
+    uint64_t ref = _getSizedInt(bytesptr, trailer->_objectRefSize);
     if (trailer->_numObjects <= ref) FAIL_MAXOFFSET;
 
     bytesptr = databytes + trailer->_offsetTableOffset + ref * trailer->_offsetIntSize;
-    uint64_t off = 0;
-    for (CFIndex idx = 0; idx < trailer->_offsetIntSize; idx++) {
-       off = (off << 8) + bytesptr[idx];
-    }
+    uint64_t off = _getSizedInt(bytesptr, trailer->_offsetIntSize);
     return off;
 }
 
-static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFPropertyListRef *plist);
-
 bool __CFBinaryPlistGetOffsetForValueFromArray2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFIndex idx, uint64_t *offset, CFMutableDictionaryRef objects) {
     uint64_t objectsRangeStart = 8, objectsRangeEnd = trailer->_offsetTableOffset - 1;
     if (startOffset < objectsRangeStart || objectsRangeEnd < startOffset) FAIL_FALSE;
@@ -788,13 +788,40 @@ bool __CFBinaryPlistGetOffsetForValueFromArray2(const uint8_t *databytes, uint64
     return true;
 }
 
-bool __CFBinaryPlistGetOffsetForValueFromDictionary2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFTypeRef key, uint64_t *koffset, uint64_t *voffset, CFMutableDictionaryRef objects) {
+// Compatibility method, to be removed soon
+CF_EXPORT bool __CFBinaryPlistGetOffsetForValueFromDictionary2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFTypeRef key, uint64_t *koffset, uint64_t *voffset, CFMutableDictionaryRef objects) {
+    return __CFBinaryPlistGetOffsetForValueFromDictionary3(databytes, datalen, startOffset, trailer, key, koffset, voffset, false, objects);
+}
+
+/* Get the offset for a value in a dictionary in a binary property list.
+ @param databytes A pointer to the start of the binary property list data.
+ @param datalen The length of the data.
+ @param startOffset The offset at which the dictionary starts.
+ @param trailer A pointer to a filled out trailer structure (use __CFBinaryPlistGetTopLevelInfo).
+ @param key A string key in the dictionary that should be searched for.
+ @param koffset Will be filled out with the offset to the key in the data bytes.
+ @param voffset Will be filled out with the offset to the value in the data bytes.
+ @param unused Unused parameter.
+ @param objects Used for caching objects. Should be a valid CFMutableDictionaryRef.
+ @return True if the key was found, false otherwise.
+*/
+bool __CFBinaryPlistGetOffsetForValueFromDictionary3(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFTypeRef key, uint64_t *koffset, uint64_t *voffset, Boolean unused, CFMutableDictionaryRef objects) {
+    
+    // Require a key that is a plist primitive
     if (!key || !_plistIsPrimitive(key)) FAIL_FALSE;
+    
+    // Require that startOffset is in the range of the object table
     uint64_t objectsRangeStart = 8, objectsRangeEnd = trailer->_offsetTableOffset - 1;
     if (startOffset < objectsRangeStart || objectsRangeEnd < startOffset) FAIL_FALSE;
+    
+    // ptr is the start of the dictionary we are reading
     const uint8_t *ptr = databytes + startOffset;
+    
+    // Check that the data pointer actually points to a dictionary
     uint8_t marker = *ptr;
     if ((marker & 0xf0) != kCFBinaryPlistMarkerDict) FAIL_FALSE;
+    
+    // Get the number of objects in this dictionary
     int32_t err = CF_NO_ERROR;
     ptr = check_ptr_add(ptr, 1, &err);
     if (CF_NO_ERROR != err) FAIL_FALSE;
@@ -805,71 +832,91 @@ bool __CFBinaryPlistGetOffsetForValueFromDictionary2(const uint8_t *databytes, u
        if (LONG_MAX < bigint) FAIL_FALSE;
        cnt = bigint;
     }
+    
+    // Total number of objects (keys + values) is cnt * 2
     cnt = check_size_t_mul(cnt, 2, &err);
     if (CF_NO_ERROR != err) FAIL_FALSE;
     size_t byte_cnt = check_size_t_mul(cnt, trailer->_objectRefSize, &err);
     if (CF_NO_ERROR != err) FAIL_FALSE;
+    
+    // Find the end of the dictionary
     const uint8_t *extent = check_ptr_add(ptr, byte_cnt, &err) - 1;
     if (CF_NO_ERROR != err) FAIL_FALSE;
+    
+    // Check that we didn't overflow the size of the dictionary
     if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
+    
+    // For short keys (15 bytes or less) in ASCII form, we can do a quick comparison check
+    // We get the pointer or copy the buffer here, outside of the loop
     CFIndex stringKeyLen = -1;
-    UniChar ubuffer[16];
     if (__CFGenericTypeID_genericobj_inline(key) == stringtype) {
        stringKeyLen = CFStringGetLength((CFStringRef)key);
-       if (stringKeyLen < 0xf) {
-           CFStringGetCharacters((CFStringRef)key, CFRangeMake(0, stringKeyLen), ubuffer);
-       }
     }
+    
+    // Find the object in the dictionary with this key
     cnt = cnt / 2;
+    uint64_t totalKeySize = cnt * trailer->_objectRefSize;
+    uint64_t off;
+    Boolean match = false;
+    CFPropertyListRef keyInData = NULL;
+    
+    char keyBuffer[16];
+    const char *keyBufferPtr = keyBuffer;
+    
+    if (stringKeyLen < 0xf) {
+       // Since we will only be comparing ASCII strings, we can attempt to get a pointer using MacRoman encoding
+       // (this is cheaper than a copy)
+       if (!(keyBufferPtr = CFStringGetCStringPtr((CFStringRef)key, kCFStringEncodingMacRoman))) {
+           CFStringGetCString((CFStringRef)key, keyBuffer, 16, kCFStringEncodingMacRoman);
+           // The pointer should now point to our keyBuffer instead of the original string buffer, since we've copied it
+           keyBufferPtr = keyBuffer;
+       }
+    }
+    
+    // Perform linear search of the keys
     for (CFIndex idx = 0; idx < cnt; idx++) {
-       uint64_t off = _getOffsetOfRefAt(databytes, ptr, trailer);
-       uint8_t marker = *(databytes + off);
+       off = _getOffsetOfRefAt(databytes, ptr, trailer);
+       marker = *(databytes + off);
        CFIndex len = marker & 0x0f;
        // if it is a short ascii string in the data, and the key is a string
-       if ((marker & 0xf0) == kCFBinaryPlistMarkerASCIIString && len < 0xf && stringKeyLen != -1) {
-           if (len != stringKeyLen) goto miss;
-           err = CF_NO_ERROR;
-           const uint8_t *ptr2 = databytes + off;
-           extent = check_ptr_add(ptr2, len, &err);
-           if (CF_NO_ERROR != err) FAIL_FALSE;
-           if (databytes + trailer->_offsetTableOffset <= extent) FAIL_FALSE;
-            for (CFIndex idx2 = 0; idx2 < stringKeyLen; idx2++) {
-                if ((UniChar)ptr2[idx2 + 1] != ubuffer[idx2]) goto miss;
-            }
-           if (koffset) *koffset = off;
-           if (voffset) {
-               off = _getOffsetOfRefAt(databytes, ptr + cnt * trailer->_objectRefSize, trailer);
-               *voffset = off;
+       if (stringKeyLen != -1 && len < 0xf && (marker & 0xf0) == kCFBinaryPlistMarkerASCIIString) {
+           if (len == stringKeyLen) {                
+               err = CF_NO_ERROR;
+               const uint8_t *ptr2 = databytes + off;
+               extent = check_ptr_add(ptr2, len, &err);
+               if (CF_NO_ERROR != err) FAIL_FALSE;
+               
+               if (databytes + trailer->_offsetTableOffset <= extent) FAIL_FALSE;
+               
+               // Compare the key to this potential match (ptr2 + 1 moves past the marker)
+               if (memcmp(ptr2 + 1, keyBufferPtr, stringKeyLen) == 0) {
+                   match = true;
+               }
            }
-           return true;
-           miss:;
        } else {
-           CFPropertyListRef pl = NULL;
-           if (!__CFBinaryPlistCreateObject2(databytes, datalen, off, trailer, kCFAllocatorSystemDefault, kCFPropertyListImmutable, objects, NULL, 0, &pl) || !_plistIsPrimitive(pl)) {
-               if (pl) CFRelease(pl);
-               FAIL_FALSE;
+           keyInData = NULL;
+           if (!__CFBinaryPlistCreateObject2(databytes, datalen, off, trailer, kCFAllocatorSystemDefault, kCFPropertyListImmutable, objects, NULL, 0, &keyInData) || !_plistIsPrimitive(keyInData)) {
+               if (keyInData) CFRelease(keyInData);
+               return false;
            }
-           if (CFEqual(key, pl)) {
-               CFRelease(pl);
-               if (koffset) *koffset = off;
-               if (voffset) {
-                   off = _getOffsetOfRefAt(databytes, ptr + cnt * trailer->_objectRefSize, trailer);
-                   *voffset = off;
-               }
-               return true;
-           }
-           CFRelease(pl);
+           
+           match = CFEqual(key, keyInData);            
+           CFRelease(keyInData);
+       }            
+       
+       if (match) {
+           if (koffset) *koffset = off;
+           if (voffset) *voffset = _getOffsetOfRefAt(databytes, ptr + totalKeySize, trailer);
+           return true;
        }
+        
        ptr += trailer->_objectRefSize;
     }
+    
     return false;
 }
 
-extern CFArrayRef _CFArrayCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const void **values, CFIndex numValues);
-extern CFSetRef _CFSetCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const void **values, CFIndex numValues);
-extern CFDictionaryRef _CFDictionaryCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const void **keys, const void **values, CFIndex numValues);
-
-static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFPropertyListRef *plist) {
+CF_EXPORT bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFPropertyListRef *plist) {
 
     if (objects) {
        *plist = CFDictionaryGetValue(objects, (const void *)(uintptr_t)startOffset);
@@ -920,11 +967,9 @@ static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t data
        // in format version '00', 1, 2, and 4-byte integers have to be interpreted as unsigned,
        // whereas 8-byte integers are signed (and 16-byte when available)
        // negative 1, 2, 4-byte integers are always emitted as 8 bytes in format '00'
-       uint64_t bigint = 0;
        // integers are not required to be in the most compact possible representation, but only the last 64 bits are significant currently
-       for (CFIndex idx = 0; idx < cnt; idx++) {
-           bigint = (bigint << 8) + *ptr++;
-       }
+       uint64_t bigint = _getSizedInt(ptr, cnt);
+       ptr += cnt;
        if (8 < cnt) {
            CFSInt128Struct val;
            val.high = 0;
@@ -1100,10 +1145,8 @@ static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t data
        if (CF_NO_ERROR != err) FAIL_FALSE;
        if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
        // uids are not required to be in the most compact possible representation, but only the last 64 bits are significant currently
-       uint64_t bigint = 0;
-       for (CFIndex idx = 0; idx < cnt; idx++) {
-           bigint = (bigint << 8) + *ptr++;
-       }
+       uint64_t bigint = _getSizedInt(ptr, cnt);
+       ptr += cnt;
        if (UINT32_MAX < bigint) FAIL_FALSE;
        *plist = _CFKeyedArchiverUIDCreate(allocator, (uint32_t)bigint);
        // these are always immutable
@@ -1132,7 +1175,7 @@ static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t data
        if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
        byte_cnt = check_size_t_mul(cnt, sizeof(CFPropertyListRef), &err);
        if (CF_NO_ERROR != err) FAIL_FALSE;
-       list = (cnt <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, __kCFAllocatorGCScannedMemory);
+       list = (cnt <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, 0);
        listAllocator = (list == buffer ? kCFAllocatorNull : kCFAllocatorSystemDefault);
        if (!list) FAIL_FALSE;
        Boolean madeSet = false;
@@ -1145,19 +1188,13 @@ static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t data
            CFPropertyListRef pl;
            off = _getOffsetOfRefAt(databytes, ptr, trailer);
            if (!__CFBinaryPlistCreateObject2(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, &pl)) {
-               if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-                   while (idx--) {
-                       CFRelease(list[idx]);
-                   }
-               }
+               while (idx--) {
+                   CFRelease(list[idx]);
+               }           
                if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
                FAIL_FALSE;
            }
-           if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-               CF_WRITE_BARRIER_BASE_ASSIGN(listAllocator, list, list[idx], CFMakeCollectable(pl));
-           } else {
-               list[idx] = pl;
-           }
+           list[idx] = pl;
            ptr += trailer->_objectRefSize;
        }
        if (set) CFSetRemoveValue(set, (const void *)(uintptr_t)startOffset);
@@ -1166,9 +1203,24 @@ static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t data
            set = NULL;
        }
        if ((marker & 0xf0) == kCFBinaryPlistMarkerArray) {
-           *plist = _CFArrayCreate_ex(allocator, (mutabilityOption != kCFPropertyListImmutable), list, cnt);
+           if (mutabilityOption != kCFPropertyListImmutable) {
+               *plist = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
+               CFArrayReplaceValues((CFMutableArrayRef)*plist, CFRangeMake(0, 0), list, cnt);
+           } else {
+               *plist = CFArrayCreate(allocator, list, cnt, &kCFTypeArrayCallBacks);
+           }
        } else {
-           *plist = _CFSetCreate_ex(allocator, (mutabilityOption != kCFPropertyListImmutable), list, cnt);
+           if (mutabilityOption != kCFPropertyListImmutable) {
+               *plist = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
+               for (CFIndex idx = 0; idx < cnt; idx++) {
+                   CFSetAddValue((CFMutableSetRef)*plist, list[idx]);
+               }
+           } else {
+               *plist = CFSetCreate(allocator, list, cnt, &kCFTypeSetCallBacks);
+           }
+       }
+       for (CFIndex idx = 0; idx < cnt; idx++) {
+           CFRelease(list[idx]);
        }
        if (objects && *plist && (mutabilityOption == kCFPropertyListImmutable)) {
            CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
@@ -1197,7 +1249,7 @@ static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t data
        if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
        byte_cnt = check_size_t_mul(cnt, sizeof(CFPropertyListRef), &err);
        if (CF_NO_ERROR != err) FAIL_FALSE;
-       list = (cnt <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, __kCFAllocatorGCScannedMemory);
+       list = (cnt <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, 0);
        listAllocator = (list == buffer ? kCFAllocatorNull : kCFAllocatorSystemDefault);
        if (!list) FAIL_FALSE;
        Boolean madeSet = false;
@@ -1210,20 +1262,14 @@ static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t data
            CFPropertyListRef pl = NULL;
            off = _getOffsetOfRefAt(databytes, ptr, trailer);
            if (!__CFBinaryPlistCreateObject2(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, &pl) || (idx < cnt / 2 && !_plistIsPrimitive(pl))) {
-               if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-                   if (pl) CFRelease(pl);
-                   while (idx--) {
-                       CFRelease(list[idx]);
-                   }
+               if (pl) CFRelease(pl);
+               while (idx--) {
+                   CFRelease(list[idx]);
                }
                if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
                FAIL_FALSE;
            }
-           if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-               CF_WRITE_BARRIER_BASE_ASSIGN(listAllocator, list, list[idx], CFMakeCollectable(pl));
-           } else {
-               list[idx] = pl;
-           }
+           list[idx] = pl;
            ptr += trailer->_objectRefSize;
        }
        if (set) CFSetRemoveValue(set, (const void *)(uintptr_t)startOffset);
@@ -1231,7 +1277,17 @@ static bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t data
            CFRelease(set);
            set = NULL;
        }
-       *plist = _CFDictionaryCreate_ex(allocator, (mutabilityOption != kCFPropertyListImmutable), list, list + cnt / 2, cnt / 2);
+       if (mutabilityOption != kCFPropertyListImmutable) {
+           *plist = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+           for (CFIndex idx = 0; idx < cnt / 2; idx++) {
+               CFDictionaryAddValue((CFMutableDictionaryRef)*plist, list[idx], list[idx + cnt / 2]);
+           }
+       } else {
+           *plist = CFDictionaryCreate(allocator, list, list + cnt / 2, cnt / 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+       }
+       for (CFIndex idx = 0; idx < cnt; idx++) {
+               CFRelease(list[idx]);
+       }
        if (objects && *plist && (mutabilityOption == kCFPropertyListImmutable)) {
            CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
        }
@@ -1262,7 +1318,7 @@ __private_extern__ bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFData
        // and the later key will cause the previous one to be released when we set the second
        // in the dictionary.
        CFMutableDictionaryRef objects = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
-       _CFDictionarySetCapacity(objects, 4000);
+       _CFDictionarySetCapacity(objects, trailer._numObjects);
        CFPropertyListRef pl = NULL;
         if (__CFBinaryPlistCreateObject2(databytes, datalen, offset, &trailer, allocator, option, objects, NULL, 0, &pl)) {
            if (plist) *plist = pl;
@@ -1275,4 +1331,3 @@ __private_extern__ bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFData
     }
     return false;
 }
-
index 60c090a268360cedc4066031c5955fb37a4714db..1ff33e460aa2c0bcf7e654d515c1a41beb88e971 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBitVector.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 typedef uint8_t __CFBitVectorBucket;
 
 enum {
-    __CF_BITS_PER_BYTE = 8
+    __CF_BITS_PER_BYTE = 8,
+    __CF_BITS_PER_BYTE_MASK = 0x07
 };
 
 enum {
-    __CF_BITS_PER_BUCKET = (__CF_BITS_PER_BYTE * sizeof(__CFBitVectorBucket))
+    __CF_BITS_PER_BUCKET = (__CF_BITS_PER_BYTE * sizeof(__CFBitVectorBucket)),
+    __CF_BITS_PER_BUCKET_MASK = 0x07    // __CF_BITS_PER_BYTE_MASK * lg2(sizeof(__CFBitVectorBucket))
 };
 
 CF_INLINE CFIndex __CFBitVectorRoundUpCapacity(CFIndex capacity) {
+    if (0 == capacity) capacity = 1;
     return ((capacity + 63) / 64) * 64;
 }
 
 CF_INLINE CFIndex __CFBitVectorNumBucketsForCapacity(CFIndex capacity) {
-    return (capacity + __CF_BITS_PER_BUCKET - 1) / __CF_BITS_PER_BUCKET;
+    return capacity / __CF_BITS_PER_BUCKET + ((capacity & __CF_BITS_PER_BUCKET_MASK) ? 1 : 0);
 }
 
 struct __CFBitVector {
@@ -195,17 +198,14 @@ static CFStringRef __CFBitVectorCopyDescription(CFTypeRef cf) {
 }
 
 enum {
-    kCFBitVectorImmutable = 0x0,               /* unchangable and fixed capacity; default */
+    kCFBitVectorImmutable = 0x0,       /* unchangable and fixed capacity; default */
     kCFBitVectorMutable = 0x1,         /* changeable and variable capacity */
-    kCFBitVectorFixedMutable = 0x3     /* changeable and fixed capacity */
 };
 
 static void __CFBitVectorDeallocate(CFTypeRef cf) {
     CFMutableBitVectorRef bv = (CFMutableBitVectorRef)cf;
     CFAllocatorRef allocator = CFGetAllocator(bv);
-    if (__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable) {
-       _CFAllocatorDeallocateGC(allocator, bv->_buckets);
-    }
+    if (bv->_buckets) _CFAllocatorDeallocateGC(allocator, bv->_buckets);
 }
 
 static CFTypeID __kCFBitVectorTypeID = _kCFRuntimeNotATypeID;
@@ -234,39 +234,26 @@ static CFMutableBitVectorRef __CFBitVectorInit(CFAllocatorRef allocator, CFOptio
     CFMutableBitVectorRef memory;
     CFIndex size;
     CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%d) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
-    CFAssert3(kCFBitVectorFixedMutable != __CFBitVectorMutableVarietyFromFlags(flags) || numBits <= capacity, __kCFLogAssertion, "%s(): for fixed mutable bit vectors, capacity (%d) must be greater than or equal to number of initial elements (%d)", __PRETTY_FUNCTION__, capacity, numBits);
     CFAssert2(0 <= numBits, __kCFLogAssertion, "%s(): numValues (%d) cannot be less than zero", __PRETTY_FUNCTION__, numBits);
     size = sizeof(struct __CFBitVector) - sizeof(CFRuntimeBase);
-    if (__CFBitVectorMutableVarietyFromFlags(flags) != kCFBitVectorMutable)
-       size += sizeof(__CFBitVectorBucket) * __CFBitVectorNumBucketsForCapacity(capacity);
     memory = (CFMutableBitVectorRef)_CFRuntimeCreateInstance(allocator, __kCFBitVectorTypeID, size, NULL);
     if (NULL == memory) {
        return NULL;
     }
-    switch (__CFBitVectorMutableVarietyFromFlags(flags)) {
-    case kCFBitVectorMutable:
-       __CFBitVectorSetCapacity(memory, __CFBitVectorRoundUpCapacity(1));
-       __CFBitVectorSetNumBuckets(memory, __CFBitVectorNumBucketsForCapacity(__CFBitVectorRoundUpCapacity(1)));
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, memory, memory->_buckets, _CFAllocatorAllocateGC(allocator, __CFBitVectorNumBuckets(memory) * sizeof(__CFBitVectorBucket), 0));
-       if (__CFOASafe) __CFSetLastAllocationEventName(memory->_buckets, "CFBitVector (store)");
-       if (NULL == memory->_buckets) {
-           CFRelease(memory);
-           return NULL;
-       }
-       break;
-    case kCFBitVectorFixedMutable:
-    case kCFBitVectorImmutable:
-       /* Don't round up capacity */
-       __CFBitVectorSetCapacity(memory, capacity);
-       __CFBitVectorSetNumBuckets(memory, __CFBitVectorNumBucketsForCapacity(capacity));
-       memory->_buckets = (__CFBitVectorBucket *)((int8_t *)memory + sizeof(struct __CFBitVector));
-       break;
+    __CFBitVectorSetCapacity(memory, __CFBitVectorRoundUpCapacity(numBits));
+    __CFBitVectorSetNumBuckets(memory, __CFBitVectorNumBucketsForCapacity(__CFBitVectorRoundUpCapacity(numBits)));
+    __CFAssignWithWriteBarrier((void **)&memory->_buckets, _CFAllocatorAllocateGC(allocator, __CFBitVectorNumBuckets(memory) * sizeof(__CFBitVectorBucket), 0));
+    if (__CFOASafe) __CFSetLastAllocationEventName(memory->_buckets, "CFBitVector (store)");
+    if (NULL == memory->_buckets) {
+       CFRelease(memory);
+       return NULL;
     }
+    memset(memory->_buckets, 0, __CFBitVectorNumBuckets(memory) * sizeof(__CFBitVectorBucket));
     __CFBitVectorSetNumBucketsUsed(memory, numBits / __CF_BITS_PER_BUCKET + 1);
     __CFBitVectorSetCount(memory, numBits);
     if (bytes) {
        /* This move is possible because bits are numbered from 0 on the left */
-       memmove(memory->_buckets, bytes, (numBits + __CF_BITS_PER_BYTE - 1) / __CF_BITS_PER_BYTE);
+       memmove(memory->_buckets, bytes, numBits / __CF_BITS_PER_BYTE + (numBits & __CF_BITS_PER_BYTE_MASK ? 1 : 0));
     }
     __CFBitVectorSetMutableVariety(memory, __CFBitVectorMutableVarietyFromFlags(flags));
     return memory;
@@ -277,7 +264,7 @@ CFBitVectorRef CFBitVectorCreate(CFAllocatorRef allocator, const uint8_t *bytes,
 }
 
 CFMutableBitVectorRef CFBitVectorCreateMutable(CFAllocatorRef allocator, CFIndex capacity) {
-   return __CFBitVectorInit(allocator, (0 == capacity) ? kCFBitVectorMutable : kCFBitVectorFixedMutable, capacity, NULL, 0);
+   return __CFBitVectorInit(allocator, kCFBitVectorMutable, capacity, NULL, 0);
 }
 
 CFBitVectorRef CFBitVectorCreateCopy(CFAllocatorRef allocator, CFBitVectorRef bv) {
@@ -287,7 +274,7 @@ CFBitVectorRef CFBitVectorCreateCopy(CFAllocatorRef allocator, CFBitVectorRef bv
 
 CFMutableBitVectorRef CFBitVectorCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFBitVectorRef bv) {
    __CFGenericValidateType(bv, __kCFBitVectorTypeID);
-    return __CFBitVectorInit(allocator, (0 == capacity) ? kCFBitVectorMutable : kCFBitVectorFixedMutable, capacity, (const uint8_t *)bv->_buckets, __CFBitVectorCount(bv));
+    return __CFBitVectorInit(allocator, kCFBitVectorMutable, capacity, (const uint8_t *)bv->_buckets, __CFBitVectorCount(bv));
 }
 
 CFIndex CFBitVectorGetCount(CFBitVectorRef bv) {
@@ -452,7 +439,7 @@ static void __CFBitVectorGrow(CFMutableBitVectorRef bv, CFIndex numNewValues) {
     CFAllocatorRef allocator = CFGetAllocator(bv);
     __CFBitVectorSetCapacity(bv, capacity);
     __CFBitVectorSetNumBuckets(bv, __CFBitVectorNumBucketsForCapacity(capacity));
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, bv, bv->_buckets, CFAllocatorReallocate(allocator, bv->_buckets, __CFBitVectorNumBuckets(bv) * sizeof(__CFBitVectorBucket), 0));
+    __CFAssignWithWriteBarrier((void **)&bv->_buckets, CFAllocatorReallocate(allocator, bv->_buckets, __CFBitVectorNumBuckets(bv) * sizeof(__CFBitVectorBucket), 0));
     if (__CFOASafe) __CFSetLastAllocationEventName(bv->_buckets, "CFBitVector (store)");
     if (NULL == bv->_buckets) HALT;
 }
@@ -467,7 +454,7 @@ static __CFBitVectorBucket __CFBitVectorOneBits(__CFBitVectorBucket bucketValue,
 
 void CFBitVectorSetCount(CFMutableBitVectorRef bv, CFIndex count) {
     CFIndex cnt;
-    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
     cnt = __CFBitVectorCount(bv);
     switch (__CFBitVectorMutableVariety(bv)) {
     case kCFBitVectorMutable:
@@ -475,9 +462,6 @@ void CFBitVectorSetCount(CFMutableBitVectorRef bv, CFIndex count) {
            __CFBitVectorGrow(bv, count - cnt);
        }
        break;
-    case kCFBitVectorFixedMutable:
-       CFAssert1(count <= __CFBitVectorCapacity(bv), __kCFLogAssertion, "%s(): fixed-capacity bit vector is full", __PRETTY_FUNCTION__);
-       break;
     }
     if (cnt < count) {
        CFRange range = CFRangeMake(cnt, count - cnt);
@@ -490,7 +474,7 @@ void CFBitVectorSetCount(CFMutableBitVectorRef bv, CFIndex count) {
 void CFBitVectorFlipBitAtIndex(CFMutableBitVectorRef bv, CFIndex idx) {
     __CFGenericValidateType(bv, __kCFBitVectorTypeID);
     CFAssert2(0 <= idx && idx < __CFBitVectorCount(bv), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
-    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
     __CFFlipBitVectorBit(bv->_buckets, idx);
 }
 
@@ -501,7 +485,7 @@ static __CFBitVectorBucket __CFBitVectorFlipBits(__CFBitVectorBucket bucketValue
 void CFBitVectorFlipBits(CFMutableBitVectorRef bv, CFRange range) {
     __CFGenericValidateType(bv, __kCFBitVectorTypeID);
     __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__);
-    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
     if (0 == range.length) return;
     __CFBitVectorInternalMap(bv, range, __CFBitVectorFlipBits, NULL);
 }
@@ -509,14 +493,14 @@ void CFBitVectorFlipBits(CFMutableBitVectorRef bv, CFRange range) {
 void CFBitVectorSetBitAtIndex(CFMutableBitVectorRef bv, CFIndex idx, CFBit value) {
     __CFGenericValidateType(bv, __kCFBitVectorTypeID);
     CFAssert2(0 <= idx && idx < __CFBitVectorCount(bv), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
-    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
     __CFSetBitVectorBit(bv->_buckets, idx, value);
 }
 
 void CFBitVectorSetBits(CFMutableBitVectorRef bv, CFRange range, CFBit value) {
     __CFGenericValidateType(bv, __kCFBitVectorTypeID);
     __CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__);
-    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable , __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
     if (0 == range.length) return;
     if (value) {
        __CFBitVectorInternalMap(bv, range, __CFBitVectorOneBits, NULL);
@@ -528,7 +512,7 @@ void CFBitVectorSetBits(CFMutableBitVectorRef bv, CFRange range, CFBit value) {
 void CFBitVectorSetAllBits(CFMutableBitVectorRef bv, CFBit value) {
     CFIndex nBuckets, leftover;
     __CFGenericValidateType(bv, __kCFBitVectorTypeID);
-    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable , __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
     nBuckets = __CFBitVectorCount(bv) / __CF_BITS_PER_BUCKET;
     leftover = __CFBitVectorCount(bv) - nBuckets * __CF_BITS_PER_BUCKET;
     if (0 < leftover) {
index 6dc5b1310e33e08b15393938e2273355c8b4eca0..ad9defc10a508f7d402c7f2177be772df8519449 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBitVector.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFBITVECTOR__)
index 92baa98203682f7fee6b47cedf8afe356149e29e..af6fb88d2131f0e33431dced4ba09f6a3f69cb84 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBuiltinConverters.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Aki Inoue
 */
 
@@ -78,7 +78,7 @@ UniChar CFStringEncodingPrecomposeLatinCharacter(const UniChar *character, CFInd
             ++usedCharLen;
         }
         if (usedChars) (*usedChars) = usedCharLen;
-        return ch;
+        if (usedCharLen > 1) return ch;
     }
     return 0xFFFD;
 }
index f8c702becc7e9fbb9770b329d2421aa155ea4206..2560072970db2cc55ff4e0f07154ec0837f4416a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -20,9 +20,9 @@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
-/*     CFBundle.c
-       Copyright (c) 1999-2007 Apple Inc.  All rights reserved.
-       Responsibility: Doug Davidson
+/*      CFBundle.c
+        Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
+        Responsibility: Doug Davidson
 */
 
 #include "CFBundle_Internal.h"
@@ -32,7 +32,7 @@
 #include <CoreFoundation/CFURLAccess.h>
 #include <CoreFoundation/CFError.h>
 #include <string.h>
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
 #include <CoreFoundation/CFByteOrder.h>
 #include "CFBundle_BinaryTypes.h"
 #include <sys/stat.h>
 #include <stdlib.h>
 
+#define AVOID_WEAK_COLLECTIONS 1
+
+#if !defined(AVOID_WEAK_COLLECTIONS)
+#include "CFHashTable.h"
+#include "CFMapTable.h"
+#include "CFPointerArray.h"
+#endif /* !AVOID_WEAK_COLLECTIONS */
+
 #if defined(BINARY_SUPPORT_DYLD)
 // Import the mach-o headers that define the macho magic numbers
 #include <mach-o/loader.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/mman.h>
+#include <crt_externs.h>
+#if defined(USE_DYLD_PRIV)
+#include <mach-o/dyld_priv.h>
+#endif /* USE_DYLD_PRIV */
 #endif /* BINARY_SUPPORT_DYLD */
 
 #if defined(BINARY_SUPPORT_DLFCN)
 #include <dlfcn.h>
 #endif /* BINARY_SUPPORT_DLFCN */
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <fcntl.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define strncasecmp_l(a, b, c, d) _strnicmp(a, b, c)
+#include <fcntl.h>
+#include <io.h>
+
+#define open _NS_open
+#define stat(x,y) _NS_stat(x,y)
+
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 
@@ -71,6 +93,11 @@ CONST_STRING_DECL(kCFBundleVersionKey, "CFBundleVersion")
 CONST_STRING_DECL(kCFBundleDevelopmentRegionKey, "CFBundleDevelopmentRegion")
 CONST_STRING_DECL(kCFBundleLocalizationsKey, "CFBundleLocalizations")
 
+// Private CFBundle Info plist keys, possible candidates for public constants
+CONST_STRING_DECL(_kCFBundleAllowMixedLocalizationsKey, "CFBundleAllowMixedLocalizations")
+CONST_STRING_DECL(_kCFBundleSupportedPlatformsKey, "CFBundleSupportedPlatforms")
+CONST_STRING_DECL(_kCFBundleResourceSpecificationKey, "CFBundleResourceSpecification")
+
 // Finder stuff
 CONST_STRING_DECL(_kCFBundlePackageTypeKey, "CFBundlePackageType")
 CONST_STRING_DECL(_kCFBundleSignatureKey, "CFBundleSignature")
@@ -121,7 +148,6 @@ CONST_STRING_DECL(_kCFBundleNumericVersionKey, "CFBundleNumericVersion")
 CONST_STRING_DECL(_kCFBundleExecutablePathKey, "CFBundleExecutablePath")
 CONST_STRING_DECL(_kCFBundleResourcesFileMappedKey, "CSResourcesFileMapped")
 CONST_STRING_DECL(_kCFBundleCFMLoadAsBundleKey, "CFBundleCFMLoadAsBundle")
-CONST_STRING_DECL(_kCFBundleAllowMixedLocalizationsKey, "CFBundleAllowMixedLocalizations")
 
 // Keys used by NSBundle for loaded Info plists.
 CONST_STRING_DECL(_kCFBundleInitialPathKey, "NSBundleInitialPath")
@@ -164,6 +190,8 @@ struct __CFBundle {
 
     _CFPlugInData _plugInData;
 
+    CFSpinLock_t _bundleLoadingLock;
+
 #if defined(BINARY_SUPPORT_DLL)
     HMODULE _hModule;
 #endif /* BINARY_SUPPORT_DLL */
@@ -172,22 +200,22 @@ struct __CFBundle {
 
 static CFSpinLock_t CFBundleGlobalDataLock = CFSpinLockInit;
 
-static CFMutableDictionaryRef _bundlesByURL = NULL;
 static CFMutableDictionaryRef _bundlesByIdentifier = NULL;
-
-// For scheduled lazy unloading.  Used by CFPlugIn.
+#if defined(AVOID_WEAK_COLLECTIONS)
+static CFMutableDictionaryRef _bundlesByURL = NULL;
+static CFMutableArrayRef _allBundles = NULL;
 static CFMutableSetRef _bundlesToUnload = NULL;
+#else /* AVOID_WEAK_COLLECTIONS */
+static __CFMapTable *_bundlesByURL = nil;
+static __CFHashTable *_allBundles = nil;
+static __CFHashTable *_bundlesToUnload = nil;
+#endif /* AVOID_WEAK_COLLECTIONS */
 static Boolean _scheduledBundlesAreUnloading = false;
 
-// Various lists of all bundles.
-static CFMutableArrayRef _allBundles = NULL;
-
 static Boolean _initedMainBundle = false;
 static CFBundleRef _mainBundle = NULL;
 static CFStringRef _defaultLocalization = NULL;
 
-static Boolean _useDlfcn = false;
-
 // Forward declares functions.
 static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, Boolean alreadyLocked, Boolean doFinalProcessing);
 static CFStringRef _CFBundleCopyExecutableName(CFAllocatorRef alloc, CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict);
@@ -198,20 +226,26 @@ static void _CFBundleCheckWorkarounds(CFBundleRef bundle);
 static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath);
 static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths);
 #if defined(BINARY_SUPPORT_DYLD)
-static CFDictionaryRef _CFBundleGrokInfoDictFromMainExecutable(void);
+static CFMutableDictionaryRef _CFBundleGrokInfoDictFromMainExecutable(void);
 static Boolean _CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion, uint32_t *objcFlags);
 static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p);
+#if !defined(BINARY_SUPPORT_DLFCN)
 static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch);
+#endif /* !BINARY_SUPPORT_DLFCN */
 #endif /* BINARY_SUPPORT_DYLD */
 #if defined(BINARY_SUPPORT_DLFCN)
-static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p);
 static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch);
+#if !defined(BINARY_SUPPORT_DYLD)
+static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p);
+#endif /* !BINARY_SUPPORT_DYLD */
 #endif /* BINARY_SUPPORT_DLFCN */
 #if defined(BINARY_SUPPORT_DYLD) && defined(BINARY_SUPPORT_CFM)
 static void *_CFBundleFunctionPointerForTVector(CFAllocatorRef allocator, void *tvp);
 static void *_CFBundleTVectorForFunctionPointer(CFAllocatorRef allocator, void *fp);
 #endif /* BINARY_SUPPORT_DYLD && BINARY_SUPPORT_CFM */
 
+#if defined(AVOID_WEAK_COLLECTIONS)
+
 static void _CFBundleAddToTables(CFBundleRef bundle, Boolean alreadyLocked) {
     CFStringRef bundleID = CFBundleGetIdentifier(bundle);
 
@@ -270,11 +304,8 @@ static void _CFBundleAddToTables(CFBundleRef bundle, Boolean alreadyLocked) {
     if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
 }
 
-static void _CFBundleRemoveFromTables(CFBundleRef bundle) {
-    CFStringRef bundleID = CFBundleGetIdentifier(bundle);
-
+static void _CFBundleRemoveFromTables(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef bundleID) {
     __CFSpinLock(&CFBundleGlobalDataLock);
-
     // Remove from the various lists
     if (_allBundles) {
         CFIndex i = CFArrayGetFirstIndexOfValue(_allBundles, CFRangeMake(0, CFArrayGetCount(_allBundles)), bundle);
@@ -282,7 +313,10 @@ static void _CFBundleRemoveFromTables(CFBundleRef bundle) {
     }
 
     // Remove from the table that maps urls to bundles
-    if (_bundlesByURL) CFDictionaryRemoveValue(_bundlesByURL, bundle->_url);
+    if (bundleURL && _bundlesByURL) {
+        CFBundleRef bundleForURL = (CFBundleRef)CFDictionaryGetValue(_bundlesByURL, bundleURL);
+        if (bundleForURL == bundle) CFDictionaryRemoveValue(_bundlesByURL, bundleURL);
+    }
     
     // Remove from the table that maps identifiers to bundles
     if (bundleID && _bundlesByIdentifier) {
@@ -293,18 +327,182 @@ static void _CFBundleRemoveFromTables(CFBundleRef bundle) {
             if (0 == CFArrayGetCount(bundlesWithThisID)) CFDictionaryRemoveValue(_bundlesByIdentifier, bundleID);
         }
     }
-    
     __CFSpinUnlock(&CFBundleGlobalDataLock);
 }
 
-__private_extern__ CFBundleRef _CFBundleFindByURL(CFURLRef url, Boolean alreadyLocked) {
+static CFBundleRef _CFBundleCopyBundleForURL(CFURLRef url, Boolean alreadyLocked) {
     CFBundleRef result = NULL;
     if (!alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
     if (_bundlesByURL) result = (CFBundleRef)CFDictionaryGetValue(_bundlesByURL, url);
+    if (result && !result->_url) {
+        result = NULL;
+        CFDictionaryRemoveValue(_bundlesByURL, url);
+    }
+    if (result) CFRetain(result);
+    if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
+    return result;
+}
+
+static CFBundleRef _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(CFStringRef bundleID) {
+    CFBundleRef result = NULL, bundle;
+    if (_bundlesByIdentifier && bundleID) {
+        // Note that this array is maintained in descending order by version number
+        CFArrayRef bundlesWithThisID = (CFArrayRef)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
+        if (bundlesWithThisID) {
+            CFIndex i, count = CFArrayGetCount(bundlesWithThisID);
+            if (count > 0) {
+                // First check for loaded bundles so we will always prefer a loaded to an unloaded bundle
+                for (i = 0; !result && i < count; i++) {
+                    bundle = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, i);
+                    if (CFBundleIsExecutableLoaded(bundle)) result = bundle;
+                }
+                // If no loaded bundle, simply take the first item in the array, i.e. the one with the latest version number
+                if (!result) result = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, 0);
+            }
+        }
+    }
+    return result;
+}
+
+#else /* AVOID_WEAK_COLLECTIONS */
+
+static void _CFBundleAddToTables(CFBundleRef bundle, Boolean alreadyLocked) {
+    CFStringRef bundleID = CFBundleGetIdentifier(bundle);
+
+    if (!alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
+    
+    // Add to the _allBundles list
+    if (!_allBundles) _allBundles = [[__CFHashTable alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory capacity:0];
+    [_allBundles addObject:(id)bundle];
+    
+    // Add to the table that maps urls to bundles
+    if (!_bundlesByURL) _bundlesByURL = [[__CFMapTable alloc] initWithKeyOptions:CFPointerFunctionsStrongMemory valueOptions:CFPointerFunctionsZeroingWeakMemory capacity:0];
+    [_bundlesByURL setObject:(id)bundle forKey:(id)bundle->_url];
+
+    // Add to the table that maps identifiers to bundles
+    if (bundleID) {
+        __CFPointerArray *bundlesWithThisID = nil;
+        CFBundleRef existingBundle = NULL;
+        if (!_bundlesByIdentifier) {
+            // Create this from the default allocator
+            _bundlesByIdentifier = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        }
+        bundlesWithThisID = (__CFPointerArray *)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
+        if (bundlesWithThisID) {
+            CFIndex i, count = (CFIndex)[bundlesWithThisID count];
+            UInt32 existingVersion, newVersion = CFBundleGetVersionNumber(bundle);
+            for (i = 0; i < count; i++) {
+                existingBundle = (CFBundleRef)[bundlesWithThisID pointerAtIndex:i];
+                if (!existingBundle) continue;
+                existingVersion = CFBundleGetVersionNumber(existingBundle);
+                // If you load two bundles with the same identifier and the same version, the last one wins.
+                if (newVersion >= existingVersion) break;
+            }
+            if (i < count) {
+                [bundlesWithThisID insertPointer:bundle atIndex:i];
+            } else {
+                [bundlesWithThisID addPointer:bundle];
+            }
+        } else {
+            bundlesWithThisID = [[__CFPointerArray alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory];
+            [bundlesWithThisID addPointer:bundle];
+            CFDictionarySetValue(_bundlesByIdentifier, bundleID, bundlesWithThisID);
+            [bundlesWithThisID release];
+        }
+    }
+    if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
+}
+
+static void _CFBundleRemoveFromTables(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef bundleID) {
+    __CFSpinLock(&CFBundleGlobalDataLock);
+    // Remove from the various lists
+    if (_allBundles && [_allBundles member:(id)bundle]) [_allBundles removeObject:(id)bundle];
+
+    // Remove from the table that maps urls to bundles
+    if (bundleURL && _bundlesByURL) {
+        CFBundleRef bundleForURL = (CFBundleRef)[_bundlesByURL objectForKey:(id)bundleURL];
+        if (bundleForURL == bundle) [_bundlesByURL removeObjectForKey:(id)bundleURL];
+    }
+    
+    // Remove from the table that maps identifiers to bundles
+    if (bundleID && _bundlesByIdentifier) {
+        __CFPointerArray *bundlesWithThisID = (__CFPointerArray *)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
+        if (bundlesWithThisID) {
+            CFIndex count = (CFIndex)[bundlesWithThisID count];
+            while (count-- > 0) if (bundle == (CFBundleRef)[bundlesWithThisID pointerAtIndex:count]) [bundlesWithThisID removePointerAtIndex:count];
+            [bundlesWithThisID compact];
+            if (0 == [bundlesWithThisID count]) CFDictionaryRemoveValue(_bundlesByIdentifier, bundleID);
+        }
+    }
+    __CFSpinUnlock(&CFBundleGlobalDataLock);
+}
+
+static CFBundleRef _CFBundleCopyBundleForURL(CFURLRef url, Boolean alreadyLocked) {
+    CFBundleRef result = NULL;
+    if (!alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
+    if (_bundlesByURL) result = (CFBundleRef)[_bundlesByURL objectForKey:(id)url];
+    if (result && !result->_url) {
+        result = NULL;
+        [_bundlesByURL removeObjectForKey:(id)url];
+    }
+    if (result) CFRetain(result);
     if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
     return result;
 }
 
+static CFBundleRef _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(CFStringRef bundleID) {
+    CFBundleRef result = NULL;
+    if (_bundlesByIdentifier && bundleID) {
+        // Note that this array is maintained in descending order by version number
+        __CFPointerArray *bundlesWithThisID = (__CFPointerArray *)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
+        if (bundlesWithThisID && [bundlesWithThisID count] > 0) {
+            // First check for loaded bundles so we will always prefer a loaded to an unloaded bundle
+            for (id bundle in bundlesWithThisID) {
+                if (bundle && CFBundleIsExecutableLoaded((CFBundleRef)bundle)) {
+                    result = (CFBundleRef)bundle;
+                    break;
+                }
+            }
+            // If no loaded bundle, simply take the first item in the array, i.e. the one with the latest version number
+            if (!result) {
+                for (id bundle in bundlesWithThisID) {
+                    if (bundle) {
+                        result = (CFBundleRef)bundle;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+#endif /* AVOID_WEAK_COLLECTIONS */
+
+#if 0 && DEPLOYMENT_TARGET_WINDOWS_SYNC
+static CFStringRef _CFBundleCopyWrapperInBinaryDirectory(CFStringRef strippedExeName) {
+    char buff[CFMaxPathSize];
+    CFIndex buffLen;
+    int i;
+
+    CFArrayRef binaryDirs = _CFGetWindowsBinaryDirectories();
+    int count = CFArrayGetCount(binaryDirs);
+    CFStringRef str;
+    struct stat garbage;
+    for (i = 0; i < count; i++) {
+        str = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@\\%@.app"), CFArrayGetValueAtIndex(binaryDirs,i), strippedExeName);
+        buffLen = CFStringGetLength(str);
+        CFStringGetFileSystemRepresentation(str, buff, CFMaxPathSize);
+        if (stat(buff, &garbage) == 0) return str;
+        CFRelease(str);
+    }
+    return NULL;
+}
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
 static CFURLRef _CFBundleCopyBundleURLForExecutablePath(CFStringRef str) {
     //!!! need to handle frameworks, NT; need to integrate with NSBundle - drd
     UniChar buff[CFMaxPathSize];
@@ -316,14 +514,54 @@ static CFURLRef _CFBundleCopyBundleURLForExecutablePath(CFStringRef str) {
     if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
     CFStringGetCharacters(str, CFRangeMake(0, buffLen), buff);
 
+#if 0 && DEPLOYMENT_TARGET_WINDOWS_SYNC
+    CFIndex startOfBinaryName = _CFLengthAfterDeletingLastPathComponent(buff, buffLen) + 1;  // Remove exe name
+    CFIndex endOfBinaryName = _CFLengthAfterDeletingPathExtension(buff, buffLen);
+    if (startOfBinaryName > 0 && startOfBinaryName < buffLen && endOfBinaryName > 0 && endOfBinaryName <= buffLen) {
+        CFStringRef strippedExeName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfBinaryName]), endOfBinaryName - startOfBinaryName);
+        CFStringRef wrapperInBinaryDirectory = _CFBundleCopyWrapperInBinaryDirectory(strippedExeName);
+        if (wrapperInBinaryDirectory) {
+            buffLen = CFStringGetLength(wrapperInBinaryDirectory);
+            if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
+            CFStringGetCharacters(wrapperInBinaryDirectory, CFRangeMake(0, buffLen), buff);
+            CFRelease(wrapperInBinaryDirectory);
+            outstr = CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault, buff, buffLen, kCFAllocatorNull);
+            url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, outstr, PLATFORM_PATH_STYLE, true);
+            CFRelease(outstr);
+            return url;
+        }
+    }
+#elif DEPLOYMENT_TARGET_WINDOWS
+    // Is this a .dll or .exe?
+    if (buffLen >= 5 && (_wcsnicmp((wchar_t *)&(buff[buffLen-4]), L".dll", 4) == 0 || _wcsnicmp((wchar_t *)&(buff[buffLen-4]), L".exe", 4) == 0)) {
+        CFIndex extensionLength = CFStringGetLength(_CFBundleWindowsResourceDirectoryExtension);
+        buffLen -= 4;
+        // If this is an _debug, we should strip that before looking for the bundle
+        if (buffLen >= 7 && (_wcsnicmp((wchar_t *)&buff[buffLen-6], L"_debug", 6) == 0)) buffLen -= 6;
+
+        if (buffLen + 1 + extensionLength < CFMaxPathSize) {
+            buff[buffLen] = '.';
+            buffLen ++;
+            CFStringGetCharacters(_CFBundleWindowsResourceDirectoryExtension, CFRangeMake(0, extensionLength), buff + buffLen);
+            buffLen += extensionLength;
+            outstr = CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault, buff, buffLen, kCFAllocatorNull);
+            url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, outstr, PLATFORM_PATH_STYLE, true);
+            CFRelease(outstr);
+        }
+    }
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
     if (!url) {
-       buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);  // Remove exe name
+        buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);  // Remove exe name
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
         if (buffLen > 0) {
             // See if this is a new bundle.  If it is, we have to remove more path components.
             CFIndex startOfLastDir = _CFStartOfLastPathComponent(buff, buffLen);
-            if ((startOfLastDir > 0) && (startOfLastDir < buffLen)) {
+            if (startOfLastDir > 0 && startOfLastDir < buffLen) {
                 CFStringRef lastDirName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfLastDir]), buffLen - startOfLastDir);
 
                 if (CFEqual(lastDirName, _CFBundleGetPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetAlternatePlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetOtherPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName())) {
@@ -335,7 +573,7 @@ static CFURLRef _CFBundleCopyBundleURLForExecutablePath(CFStringRef str) {
                     if (buffLen > 0) {
                         // Remove executables folder (if present)
                         CFIndex startOfNextDir = _CFStartOfLastPathComponent(buff, buffLen);
-                        if ((startOfNextDir > 0) && (startOfNextDir < buffLen)) {
+                        if (startOfNextDir > 0 && startOfNextDir < buffLen) {
                             CFStringRef nextDirName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfNextDir]), buffLen - startOfNextDir);
                             if (CFEqual(nextDirName, _CFBundleExecutablesDirectoryName)) buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
                             CFRelease(nextDirName);
@@ -344,13 +582,46 @@ static CFURLRef _CFBundleCopyBundleURLForExecutablePath(CFStringRef str) {
                     if (buffLen > 0) {
                         // Remove support files folder
                         buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
+#elif 0 && DEPLOYMENT_TARGET_WINDOWS_SYNC
+    if (buffLen > 0) {
+        // See if this is a new bundle.  If it is, we have to remove more path components.
+        CFIndex startOfLastDir = _CFStartOfLastPathComponent(buff, buffLen);
+        if (startOfLastDir > 0 && startOfLastDir < buffLen) {
+            CFStringRef lastDirName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfLastDir]), buffLen - startOfLastDir);
+
+            if (CFEqual(lastDirName, _CFBundleGetPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetAlternatePlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetOtherPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName())) {
+                // This is a new bundle.  Back off a few more levels
+                if (buffLen > 0) {
+                    // Remove platform folder
+                    buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
+                }
+                if (buffLen > 0) {
+                    // Remove executables folder (if present)
+                    CFIndex startOfNextDir = _CFStartOfLastPathComponent(buff, buffLen);
+                    if (startOfNextDir > 0 && startOfNextDir < buffLen) {
+                        CFStringRef nextDirName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfNextDir]), buffLen - startOfNextDir);
+                        if (CFEqual(nextDirName, _CFBundleExecutablesDirectoryName)) buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
+                        CFRelease(nextDirName);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
                     }
                 }
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
                 CFRelease(lastDirName);
             }
         }
+#elif 0 && DEPLOYMENT_TARGET_WINDOWS_SYNC
+                if (buffLen > 0) {
+                    // Remove support files folder
+                    buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
+                }
+            }
+            CFRelease(lastDirName);
+        }
+    }
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
         if (buffLen > 0) {
@@ -374,9 +645,16 @@ static CFURLRef _CFBundleCopyResolvedURLForExecutableURL(CFURLRef url) {
         if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
         CFStringGetCharacters(str, CFRangeMake(0, buffLen), buff);
         len1 = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
-        if (len1 > 0 && len1 + 1 < buffLen) {
+        if (len1 > 0 && len1 + 1 < buffLen) {          
             str1 = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, buff, len1);
-            str2 = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, buff + len1 + 1, buffLen - len1 - 1);
+            CFIndex skipSlashCount = 1;
+#if DEPLOYMENT_TARGET_WINDOWS
+            // On Windows, _CFLengthAfterDeletingLastPathComponent will return a value of 3 if the path is at the root (e.g. C:\). This includes the \, which is not the case for URLs with subdirectories
+            if (len1 == 3 && buff[1] == ':' && buff[2] == '\\') {
+                skipSlashCount = 0;
+            }
+#endif
+            str2 = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, buff + len1 + skipSlashCount, buffLen - len1 - skipSlashCount);
             if (str1 && str2) {
                 url1 = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str1, PLATFORM_PATH_STYLE, true);
                 if (url1) {
@@ -414,41 +692,48 @@ CFURLRef _CFBundleCopyBundleURLForExecutableURL(CFURLRef url) {
     return outurl;
 }
 
-CFBundleRef _CFBundleCreateIfLooksLikeBundle(CFAllocatorRef allocator, CFURLRef url) {
-    CFBundleRef bundle = CFBundleCreate(allocator, url);
-    
+static uint8_t _CFBundleEffectiveLayoutVersion(CFBundleRef bundle) {
+    uint8_t localVersion = bundle->_version;
     // exclude type 0 bundles with no binary (or CFM binary) and no Info.plist, since they give too many false positives
-    if (bundle && 0 == bundle->_version) {
+    if (0 == localVersion) {
         CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
         if (!infoDict || 0 == CFDictionaryGetCount(infoDict)) {
-#if defined(BINARY_SUPPORT_CFM) && defined(BINARY_SUPPORT_DYLD)
+#if defined(BINARY_SUPPORT_DYLD)
             CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
             if (executableURL) {
                 if (bundle->_binaryType == __CFBundleUnknownBinary) bundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
                 if (bundle->_binaryType == __CFBundleCFMBinary || bundle->_binaryType == __CFBundleUnreadableBinary) {
-                    bundle->_version = 4;
+                    localVersion = 4;
                 } else {
                     bundle->_resourceData._executableLacksResourceFork = true;
                 }
                 CFRelease(executableURL);
             } else {
-                bundle->_version = 4;
+                localVersion = 4;
             }
 #elif defined(BINARY_SUPPORT_CFM)
-            bundle->_version = 4;
+            localVersion = 4;
 #else 
             CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
             if (executableURL) {
                 CFRelease(executableURL);
             } else {
-                bundle->_version = 4;
+                localVersion = 4;
             }
 #endif /* BINARY_SUPPORT_CFM && BINARY_SUPPORT_DYLD */
         }
     }
-    if (bundle && (3 == bundle->_version || 4 == bundle->_version)) {
-        CFRelease(bundle);
-        bundle = NULL;
+    return localVersion;
+}
+
+CFBundleRef _CFBundleCreateIfLooksLikeBundle(CFAllocatorRef allocator, CFURLRef url) {
+    CFBundleRef bundle = CFBundleCreate(allocator, url);
+    if (bundle) {
+        uint8_t localVersion = _CFBundleEffectiveLayoutVersion(bundle);
+        if (3 == localVersion || 4 == localVersion) {
+            CFRelease(bundle);
+            bundle = NULL;
+        }
     }
     return bundle;
 }
@@ -484,6 +769,64 @@ CFBundleRef _CFBundleCreateWithExecutableURLIfLooksLikeBundle(CFAllocatorRef all
     return bundle;
 }
 
+CFBundleRef _CFBundleCreateIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url) {
+    CFBundleRef bundle = CFBundleCreate(allocator, url);
+    if (bundle) {
+        Boolean mightBeBundle = true, isDir = false;
+        uint8_t localVersion = _CFBundleEffectiveLayoutVersion(bundle);
+        if (3 == localVersion) {
+            CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
+            CFURLRef executableURL, supportFilesURL, resourceSpecificationFileURL;
+            CFArrayRef supportedPlatforms;
+            CFStringRef resourceSpecificationFile;
+            
+            mightBeBundle = false;
+            if (infoDict && CFDictionaryGetValue(infoDict, kCFBundleExecutableKey) && (executableURL = _CFBundleCopyExecutableURLIgnoringCache(bundle))) {
+                supportedPlatforms = _CFBundleGetSupportedPlatforms(bundle);
+                resourceSpecificationFile = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundleResourceSpecificationKey);
+                if (supportedPlatforms && CFArrayGetCount(supportedPlatforms) > 0 && CFArrayGetFirstIndexOfValue(supportedPlatforms, CFRangeMake(0, CFArrayGetCount(supportedPlatforms)), CFSTR("iPhoneOS")) >= 0) {
+                    mightBeBundle = true;
+                } else if (resourceSpecificationFile && CFGetTypeID(resourceSpecificationFile) == CFStringGetTypeID() && (supportFilesURL = CFBundleCopySupportFilesDirectoryURL(bundle))) {
+                    resourceSpecificationFileURL = CFURLCreateWithFileSystemPathRelativeToBase(allocator, resourceSpecificationFile, kCFURLPOSIXPathStyle, false, supportFilesURL);
+                    if (resourceSpecificationFileURL) {
+                        if (_CFIsResourceAtURL(resourceSpecificationFileURL, &isDir) && !isDir) mightBeBundle = true;
+                        CFRelease(resourceSpecificationFileURL);
+                    }
+                    CFRelease(supportFilesURL);
+                }
+                CFRelease(executableURL);
+            }
+        } else if (4 == localVersion) {
+            mightBeBundle = false;
+        }
+        if (!mightBeBundle) {
+            CFRelease(bundle);
+            bundle = NULL;
+        }
+    }
+    return bundle;
+}
+
+CFBundleRef _CFBundleCreateWithExecutableURLIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url) {
+    CFBundleRef bundle = NULL;
+    CFURLRef bundleURL = _CFBundleCopyBundleURLForExecutableURL(url), resolvedURL = _CFBundleCopyResolvedURLForExecutableURL(url);
+    if (bundleURL && resolvedURL) {
+        bundle = _CFBundleCreateIfMightBeBundle(allocator, bundleURL);
+        if (bundle) {
+            CFURLRef executableURL = _CFBundleCopyExecutableURLIgnoringCache(bundle);
+            char buff1[CFMaxPathSize], buff2[CFMaxPathSize];
+            if (!executableURL || !CFURLGetFileSystemRepresentation(resolvedURL, true, (uint8_t *)buff1, CFMaxPathSize) || !CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff2, CFMaxPathSize) || 0 != strcmp(buff1, buff2)) {
+                CFRelease(bundle);
+                bundle = NULL;
+            }
+            if (executableURL) CFRelease(executableURL);
+        }
+    }
+    if (bundleURL) CFRelease(bundleURL);
+    if (resolvedURL) CFRelease(resolvedURL);
+    return bundle;
+}
+
 CFURLRef _CFBundleCopyMainBundleExecutableURL(Boolean *looksLikeBundle) {
     // This function is for internal use only; _mainBundle is deliberately accessed outside of the lock to get around a reentrancy issue
     const char *processPath;
@@ -522,7 +865,7 @@ static void _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(CFStringRef
 #if defined(BINARY_SUPPORT_DYLD)
         if (_mainBundle->_binaryType == __CFBundleDYLDExecutableBinary) {
             if (_mainBundle->_infoDict) CFRelease(_mainBundle->_infoDict);
-            _mainBundle->_infoDict = _CFBundleGrokInfoDictFromMainExecutable();
+            _mainBundle->_infoDict = (CFDictionaryRef)_CFBundleGrokInfoDictFromMainExecutable();
         }
 #endif /* BINARY_SUPPORT_DYLD */
 #if defined(BINARY_SUPPORT_CFM)
@@ -553,6 +896,21 @@ static void _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(CFStringRef
             if (_mainBundle->_binaryType == __CFBundleUnreadableBinary && _mainBundle->_infoDict && CFDictionaryGetValue(_mainBundle->_infoDict, kCFBundleDevelopmentRegionKey)) versRegionOverrides = true;
         }
 #endif /* BINARY_SUPPORT_CFM */
+    } else {
+#if defined(BINARY_SUPPORT_DYLD)
+        if (_mainBundle->_binaryType == __CFBundleDYLDExecutableBinary) {
+            // if dyld and not main executable for bundle, prefer info dictionary from executable
+            CFStringRef executableName = _CFBundleCopyExecutableName(kCFAllocatorSystemDefault, _mainBundle, NULL, NULL);
+            if (!executableName || !executablePath || !CFStringHasSuffix(executablePath, executableName)) {
+                CFDictionaryRef infoDictFromExecutable = (CFDictionaryRef)_CFBundleGrokInfoDictFromMainExecutable();
+                if (infoDictFromExecutable && CFDictionaryGetCount(infoDictFromExecutable) > 0) {
+                    if (_mainBundle->_infoDict) CFRelease(_mainBundle->_infoDict);
+                    _mainBundle->_infoDict = infoDictFromExecutable;
+                }
+            }
+            if (executableName) CFRelease(executableName);
+        }
+#endif /* BINARY_SUPPORT_DYLD */
     }
     if (!_mainBundle->_infoDict) _mainBundle->_infoDict = CFDictionaryCreateMutable(CFGetAllocator(_mainBundle), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     if (!CFDictionaryGetValue(_mainBundle->_infoDict, _kCFBundleExecutablePathKey)) CFDictionarySetValue((CFMutableDictionaryRef)(_mainBundle->_infoDict), _kCFBundleExecutablePathKey, executablePath);
@@ -632,22 +990,26 @@ static CFBundleRef _CFBundleGetMainBundleAlreadyLocked(void) {
                         _mainBundle->_binaryType = __CFBundleNoBinary;
                     } else {
                         _mainBundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
-#if defined(BINARY_SUPPORT_CFM)
                         if (_mainBundle->_binaryType != __CFBundleCFMBinary && _mainBundle->_binaryType != __CFBundleUnreadableBinary) _mainBundle->_resourceData._executableLacksResourceFork = true;
-#endif /* BINARY_SUPPORT_CFM */
                     }
                 }                
 #endif /* BINARY_SUPPORT_DYLD */
-#if defined(BINARY_SUPPORT_DYLD)
                 // get cookie for already-loaded main bundle
+#if defined(BINARY_SUPPORT_DLFCN)
+                if (!_mainBundle->_handleCookie) {
+                    _mainBundle->_handleCookie = dlopen(NULL, RTLD_NOLOAD | RTLD_FIRST);
+#if LOG_BUNDLE_LOAD
+                    printf("main bundle %p getting handle %p\n", _mainBundle, _mainBundle->_handleCookie);
+#endif /* LOG_BUNDLE_LOAD */
+                }
+#elif defined(BINARY_SUPPORT_DYLD)
                 if (_mainBundle->_binaryType == __CFBundleDYLDExecutableBinary && !_mainBundle->_imageCookie) {
-                    // ??? need better way to specify main executable image
                     _mainBundle->_imageCookie = (void *)_dyld_get_image_header(0);
 #if LOG_BUNDLE_LOAD
                     printf("main bundle %p getting image %p\n", _mainBundle, _mainBundle->_imageCookie);
 #endif /* LOG_BUNDLE_LOAD */
                 }
-#endif /* BINARY_SUPPORT_DYLD */
+#endif /* BINARY_SUPPORT_DLFCN */
                 _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(str);
                 // Perform delayed final processing steps.
                 // This must be done after _isLoaded has been set, for security reasons (3624341).
@@ -676,52 +1038,41 @@ CFBundleRef CFBundleGetMainBundle(void) {
 
 CFBundleRef CFBundleGetBundleWithIdentifier(CFStringRef bundleID) {
     CFBundleRef result = NULL;
-    CFArrayRef bundlesWithThisID;
     if (bundleID) {
         __CFSpinLock(&CFBundleGlobalDataLock);
         (void)_CFBundleGetMainBundleAlreadyLocked();
-        if (_bundlesByIdentifier) {
-            bundlesWithThisID = (CFArrayRef)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
-            if (bundlesWithThisID && CFArrayGetCount(bundlesWithThisID) > 0) result = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, 0);
-        }
-#if DEPLOYMENT_TARGET_MACOSX
+        result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
         if (!result) {
             // Try to create the bundle for the caller and try again
             void *p = __builtin_return_address(0);
             if (p) {
                 CFStringRef imagePath = NULL;
-#if defined(BINARY_SUPPORT_DLFCN)
-                if (!imagePath && _useDlfcn) imagePath = _CFBundleDlfcnCopyLoadedImagePathForPointer(p);
-#endif /* BINARY_SUPPORT_DLFCN */
 #if defined(BINARY_SUPPORT_DYLD)
                 if (!imagePath) imagePath = _CFBundleDYLDCopyLoadedImagePathForPointer(p);
+#elif defined(BINARY_SUPPORT_DLFCN)
+                if (!imagePath) imagePath = _CFBundleDlfcnCopyLoadedImagePathForPointer(p);
 #endif /* BINARY_SUPPORT_DYLD */
                 if (imagePath) {
                     _CFBundleEnsureBundleExistsForImagePath(imagePath);
                     CFRelease(imagePath);
                 }
-                if (_bundlesByIdentifier) {
-                    bundlesWithThisID = (CFArrayRef)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
-                    if (bundlesWithThisID && CFArrayGetCount(bundlesWithThisID) > 0) result = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, 0);
-                }
+                result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
             }
         }
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
         if (!result) {
             // Try to guess the bundle from the identifier and try again
             _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(bundleID);
-            if (_bundlesByIdentifier) {
-                bundlesWithThisID = (CFArrayRef)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
-                if (bundlesWithThisID && CFArrayGetCount(bundlesWithThisID) > 0) result = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, 0);
-            }
+            result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
         }
         if (!result) {
             // Make sure all bundles have been created and try again.
             _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
-            if (_bundlesByIdentifier) {
-                bundlesWithThisID = (CFArrayRef)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
-                if (bundlesWithThisID && CFArrayGetCount(bundlesWithThisID) > 0) result = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, 0);
-            }
+            result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
         }
         __CFSpinUnlock(&CFBundleGlobalDataLock);
     }
@@ -756,9 +1107,9 @@ static CFStringRef __CFBundleCopyDescription(CFTypeRef cf) {
             break;
     }
     if (((CFBundleRef)cf)->_plugInData._isPlugIn) {
-        retval = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFBundle/CFPlugIn %p <%@> (%@%sloaded)"), cf, path, binaryType, ((CFBundleRef)cf)->_isLoaded ? "" : "not ");
+        retval = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFBundle/CFPlugIn %p <%@> (%@%@loaded)"), cf, path, binaryType, ((CFBundleRef)cf)->_isLoaded ? CFSTR("") : CFSTR("not "));
     } else {
-        retval = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFBundle %p <%@> (%@%sloaded)"), cf, path, binaryType, ((CFBundleRef)cf)->_isLoaded ? "" : "not ");
+        retval = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFBundle %p <%@> (%@%@loaded)"), cf, path, binaryType, ((CFBundleRef)cf)->_isLoaded ? CFSTR("") : CFSTR("not "));
     }
     if (path) CFRelease(path);
     return retval;
@@ -772,22 +1123,20 @@ static void _CFBundleDeallocateGlue(const void *key, const void *value, void *co
 static void __CFBundleDeallocate(CFTypeRef cf) {
     CFBundleRef bundle = (CFBundleRef)cf;
     CFAllocatorRef allocator;
+    CFURLRef bundleURL;
+    CFStringRef bundleID = NULL;
     
     __CFGenericValidateType(cf, __kCFBundleTypeID);
-
     allocator = CFGetAllocator(bundle);
-
-    /* Unload it */
+    bundleURL = bundle->_url;
+    bundle->_url = NULL;
+    if (bundle->_infoDict) bundleID = (CFStringRef)CFDictionaryGetValue(bundle->_infoDict, kCFBundleIdentifierKey);
+    _CFBundleRemoveFromTables(bundle, bundleURL, bundleID);
     CFBundleUnloadExecutable(bundle);
-
-    // Clean up plugIn stuff
-    _CFBundleDeallocatePlugIn(bundle);
-    
-    _CFBundleRemoveFromTables(bundle);
-
-    if (bundle->_url) {
-        _CFBundleFlushCachesForURL(bundle->_url);
-        CFRelease(bundle->_url);
+    _CFBundleDeallocatePlugIn(bundle);    
+    if (bundleURL) {
+        _CFBundleFlushCachesForURL(bundleURL);
+        CFRelease(bundleURL);
     }
     if (bundle->_infoDict) CFRelease(bundle->_infoDict);
     if (bundle->_modDate) CFRelease(bundle->_modDate);
@@ -814,16 +1163,6 @@ static const CFRuntimeClass __CFBundleClass = {
 
 __private_extern__ void __CFBundleInitialize(void) {
     __kCFBundleTypeID = _CFRuntimeRegisterClass(&__CFBundleClass);
-#if defined(BINARY_SUPPORT_DLFCN)
-    _useDlfcn = true;
-#if defined(BINARY_SUPPORT_DYLD)
-    if (getenv("CFBundleUseDYLD")) _useDlfcn = false;
-#endif /* BINARY_SUPPORT_DYLD */
-#endif /* BINARY_SUPPORT_DLFCN */
-}
-
-Boolean _CFBundleUseDlfcn(void) {
-    return _useDlfcn;
 }
 
 CFTypeID CFBundleGetTypeID(void) {
@@ -839,7 +1178,8 @@ CFBundleRef _CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL) {
     
     newURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)buff, strlen(buff), true);
     if (!newURL) newURL = (CFURLRef)CFRetain(bundleURL);
-    bundle = _CFBundleFindByURL(newURL, false);
+    bundle = _CFBundleCopyBundleForURL(newURL, false);
+    if (bundle) CFRelease(bundle);
     CFRelease(newURL);
     return bundle;
 }
@@ -857,16 +1197,29 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL,
 
     newURL = CFURLCreateFromFileSystemRepresentation(allocator, (uint8_t *)buff, strlen(buff), true);
     if (!newURL) newURL = (CFURLRef)CFRetain(bundleURL);
-    bundle = _CFBundleFindByURL(newURL, alreadyLocked);
+    bundle = _CFBundleCopyBundleForURL(newURL, alreadyLocked);
     if (bundle) {
-        CFRetain(bundle);
         CFRelease(newURL);
         return bundle;
     }
     
     if (!_CFBundleURLLooksLikeBundleVersion(newURL, &localVersion)) {
         localVersion = 3;
-        if (_CFGetFileProperties(allocator, newURL, &exists, &mode, NULL, &modDate, NULL, NULL) == 0) {
+        SInt32 res = _CFGetFileProperties(allocator, newURL, &exists, &mode, NULL, &modDate, NULL, NULL);
+#if DEPLOYMENT_TARGET_WINDOWS
+        if (!(res == 0 && exists && ((mode & S_IFMT) == S_IFDIR))) {
+            // 2nd chance at finding a bundle path - remove the last path component (e.g., mybundle.resources) and try again
+            if (modDate) {
+                CFRelease(modDate);
+                modDate = NULL;
+            }
+            CFURLRef shorterPath = CFURLCreateCopyDeletingLastPathComponent(allocator, newURL);
+            CFRelease(newURL);
+            newURL = shorterPath;
+            res = _CFGetFileProperties(allocator, newURL, &exists, &mode, NULL, &modDate, NULL, NULL);
+        }
+#endif
+        if (res == 0) {
             if (!exists || ((mode & S_IFMT) != S_IFDIR)) {
                 if (modDate) CFRelease(modDate);
                 CFRelease(newURL);
@@ -910,11 +1263,14 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL,
     bundle->_isLoaded = false;
     bundle->_sharesStringsFiles = false;
     
-    if (!getenv("CFBundleDisableStringsSharing") && 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    if (!__CFgetenv("CFBundleDisableStringsSharing") && 
         (strncmp(buff, "/System/Library/Frameworks", 26) == 0) && 
-#endif
         (strncmp(buff + strlen(buff) - 10, ".framework", 10) == 0)) bundle->_sharesStringsFiles = true;
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 
     bundle->_connectionCookie = NULL;
     bundle->_handleCookie = NULL;
@@ -923,11 +1279,7 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL,
 
     bundle->_glueDict = NULL;
     
-#if defined(BINARY_SUPPORT_CFM)
     bundle->_resourceData._executableLacksResourceFork = false;
-#else /* BINARY_SUPPORT_CFM */
-    bundle->_resourceData._executableLacksResourceFork = true;
-#endif /* BINARY_SUPPORT_CFM */
     bundle->_resourceData._infoDictionaryFromResourceFork = false;
     bundle->_resourceData._stringTableCache = NULL;
 
@@ -937,6 +1289,8 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL,
     bundle->_plugInData._instanceCount = 0;
     bundle->_plugInData._factories = NULL;
 
+    bundle->_bundleLoadingLock = CFSpinLockInit;
+    
     CFBundleGetInfoDictionary(bundle);
     
     _CFBundleAddToTables(bundle, alreadyLocked);
@@ -953,7 +1307,9 @@ static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL,
     return bundle;
 }
 
-CFBundleRef CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL) {return _CFBundleCreate(allocator, bundleURL, false, true);}
+CFBundleRef CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL) {
+    return _CFBundleCreate(allocator, bundleURL, false, true);
+}
 
 CFArrayRef CFBundleCreateBundlesFromDirectory(CFAllocatorRef alloc, CFURLRef directoryURL, CFStringRef bundleType) {
     CFMutableArrayRef bundles = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
@@ -975,9 +1331,7 @@ CFArrayRef CFBundleCreateBundlesFromDirectory(CFAllocatorRef alloc, CFURLRef dir
 }
 
 CFURLRef CFBundleCopyBundleURL(CFBundleRef bundle) {
-    if (bundle->_url) {
-        CFRetain(bundle->_url);
-    }
+    if (bundle->_url) CFRetain(bundle->_url);
     return bundle->_url;
 }
 
@@ -991,7 +1345,10 @@ CFArrayRef _CFBundleGetLanguageSearchList(CFBundleRef bundle) {
     if (!bundle->_searchLanguages) {
         CFMutableArrayRef langs = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
         CFStringRef devLang = CFBundleGetDevelopmentRegion(bundle);
-        
+
+#if DEPLOYMENT_TARGET_WINDOWS
+        if (_defaultLocalization) CFArrayAppendValue(langs, _defaultLocalization);
+#endif
         _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version, bundle->_infoDict, langs, devLang);
 
         if (CFArrayGetCount(langs) == 0) {
@@ -1002,9 +1359,7 @@ CFArrayRef _CFBundleGetLanguageSearchList(CFBundleRef bundle) {
             // if none of the preferred localizations are present, fall back on a random localization that is present
             CFArrayRef localizations = CFBundleCopyBundleLocalizations(bundle);
             if (localizations) {
-                if (CFArrayGetCount(localizations) > 0) {
-                    _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version, bundle->_infoDict, langs, (CFStringRef)CFArrayGetValueAtIndex(localizations, 0));
-                }
+                if (CFArrayGetCount(localizations) > 0) _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version, bundle->_infoDict, langs, (CFStringRef)CFArrayGetValueAtIndex(localizations, 0));
                 CFRelease(localizations);
             }
         }
@@ -1036,22 +1391,28 @@ CFArrayRef _CFBundleGetLanguageSearchList(CFBundleRef bundle) {
                 CFArrayAppendValue(langs, CFSTR("en"));
             }
         }
-        bundle->_searchLanguages = langs;
+        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)langs, (void * volatile *)&(bundle->_searchLanguages))) CFRelease(langs);
     }
     return bundle->_searchLanguages;
 }
 
-CFDictionaryRef CFBundleCopyInfoDictionaryInDirectory(CFURLRef url) {return _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault, url, NULL);}
+CFDictionaryRef CFBundleCopyInfoDictionaryInDirectory(CFURLRef url) {
+    return _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault, url, NULL);
+}
 
 CFDictionaryRef CFBundleGetInfoDictionary(CFBundleRef bundle) {
     if (!bundle->_infoDict) bundle->_infoDict = _CFBundleCopyInfoDictionaryInDirectoryWithVersion(CFGetAllocator(bundle), bundle->_url, bundle->_version);
     return bundle->_infoDict;
 }
 
-CFDictionaryRef _CFBundleGetLocalInfoDictionary(CFBundleRef bundle) {return CFBundleGetLocalInfoDictionary(bundle);}
+CFDictionaryRef _CFBundleGetLocalInfoDictionary(CFBundleRef bundle) {
+    return CFBundleGetLocalInfoDictionary(bundle);
+}
 
 CFDictionaryRef CFBundleGetLocalInfoDictionary(CFBundleRef bundle) {
-    if (!bundle->_localInfoDict) {
+    static CFSpinLock_t CFBundleLocalInfoLock = CFSpinLockInit;
+    CFDictionaryRef localInfoDict = bundle->_localInfoDict;
+    if (!localInfoDict) {
         CFURLRef url = CFBundleCopyResourceURL(bundle, _CFBundleLocalInfoName, _CFBundleStringTableType, NULL);
         if (url) {
             CFDataRef data;
@@ -1059,21 +1420,31 @@ CFDictionaryRef CFBundleGetLocalInfoDictionary(CFBundleRef bundle) {
             CFStringRef errStr = NULL;
             
             if (CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(bundle), url, &data, NULL, NULL, &errCode)) {
-                bundle->_localInfoDict = (CFDictionaryRef)CFPropertyListCreateFromXMLData(CFGetAllocator(bundle), data, kCFPropertyListImmutable, &errStr);
+                localInfoDict = (CFDictionaryRef)CFPropertyListCreateFromXMLData(CFGetAllocator(bundle), data, kCFPropertyListImmutable, &errStr);
                 if (errStr) CFRelease(errStr);
-                if (bundle->_localInfoDict && CFDictionaryGetTypeID() != CFGetTypeID(bundle->_localInfoDict)) {
-                    CFRelease(bundle->_localInfoDict);
-                    bundle->_localInfoDict = NULL;
+                if (localInfoDict && CFDictionaryGetTypeID() != CFGetTypeID(localInfoDict)) {
+                    CFRelease(localInfoDict);
+                    localInfoDict = NULL;
                 }
                 CFRelease(data);
             }
             CFRelease(url);
         }
+        __CFSpinLock(&CFBundleLocalInfoLock);
+        if (!bundle->_localInfoDict) {
+            bundle->_localInfoDict = localInfoDict;
+        } else {
+            if (localInfoDict) CFRelease(localInfoDict);
+            localInfoDict = bundle->_localInfoDict;
+        }
+        __CFSpinUnlock(&CFBundleLocalInfoLock);
     }
-    return bundle->_localInfoDict;
+    return localInfoDict;
 }
 
-CFPropertyListRef _CFBundleGetValueForInfoKey(CFBundleRef bundle, CFStringRef key) {return (CFPropertyListRef)CFBundleGetValueForInfoDictionaryKey(bundle, key);}
+CFPropertyListRef _CFBundleGetValueForInfoKey(CFBundleRef bundle, CFStringRef key) {
+    return (CFPropertyListRef)CFBundleGetValueForInfoDictionaryKey(bundle, key);
+}
 
 CFTypeRef CFBundleGetValueForInfoDictionaryKey(CFBundleRef bundle, CFStringRef key) {
     // Look in InfoPlist.strings first.  Then look in Info.plist
@@ -1103,7 +1474,7 @@ CFStringRef CFBundleGetIdentifier(CFBundleRef bundle) {
 
 #define MAX_VERS_LEN 10
 
-CF_INLINE Boolean _isDigit(UniChar aChar) {return (((aChar >= (UniChar)'0') && (aChar <= (UniChar)'9')) ? true : false);}
+CF_INLINE Boolean _isDigit(UniChar aChar) {return ((aChar >= (UniChar)'0' && aChar <= (UniChar)'9') ? true : false);}
 
 __private_extern__ CFStringRef _CFCreateStringFromVersionNumber(CFAllocatorRef alloc, UInt32 vers) {
     CFStringRef result = NULL;
@@ -1124,9 +1495,9 @@ __private_extern__ CFStringRef _CFCreateStringFromVersionNumber(CFAllocatorRef a
         }
     } else {
         if (major1 > 0) {
-            result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d%d.%d.%d%s%d"), major1, major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? "d" : ((stage == ALPHA_STAGE) ? "a" : "b")), build);
+            result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d%d.%d.%d%C%d"), major1, major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? 'd' : ((stage == ALPHA_STAGE) ? 'a' : 'b')), build);
         } else {
-            result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d.%d.%d%s%d"), major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? "d" : ((stage == ALPHA_STAGE) ? "a" : "b")), build);
+            result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d.%d.%d%C%d"), major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? 'd' : ((stage == ALPHA_STAGE) ? 'a' : 'b')), build);
         }
     }
     return result;
@@ -1143,10 +1514,8 @@ __private_extern__ UInt32 _CFVersionNumberFromString(CFStringRef versStr) {
     Boolean digitsDone = false;
 
     if (!versStr) return 0;
-
     len = CFStringGetLength(versStr);
-
-    if ((len == 0) || (len > MAX_VERS_LEN)) return 0;
+    if (len <= 0 || len > MAX_VERS_LEN) return 0;
 
     CFStringGetCharacters(versStr, CFRangeMake(0, len), versChars);
     chars = versChars;
@@ -1278,7 +1647,7 @@ __private_extern__ UInt32 _CFVersionNumberFromString(CFStringRef versStr) {
     }
 
     // Range check the build number and make sure we exhausted the string.
-    if ((build > 0xFF) || (len > 0)) return 0;
+    if (build > 0xFF || len > 0) return 0;
 
     // Build the number
     theVers = major1 << 28;
@@ -1363,6 +1732,24 @@ static Boolean _urlExists(CFAllocatorRef alloc, CFURLRef url) {
     return url && (0 == _CFGetFileProperties(alloc, url, &exists, NULL, NULL, NULL, NULL, NULL)) && exists;
 }
 
+// This is here because on iPhoneOS with the dyld shared cache, we remove binaries from their
+// original locations on disk, so checking whether a binary's path exists is no longer sufficient.
+// For performance reasons, we only call dlopen_preflight() after we've verified that the binary 
+// does not exist at its original path with _urlExists().
+// See <rdar://problem/6956670>
+static Boolean _binaryLoadable(CFAllocatorRef alloc, CFURLRef url) {
+    Boolean loadable = _urlExists(alloc, url);
+#if DEPLOYMENT_TARGET_EMBEDDED
+    if (!loadable) {
+       uint8_t path[PATH_MAX];
+       if (url && CFURLGetFileSystemRepresentation(url, true, path, sizeof(path))) {
+           loadable = dlopen_preflight((char *)path);
+       }
+    }
+#endif
+    return loadable;
+}
+
 __private_extern__ CFURLRef _CFBundleCopySupportFilesDirectoryURLInDirectory(CFAllocatorRef alloc, CFURLRef bundleURL, uint8_t version) {
     CFURLRef result = NULL;
     if (bundleURL) {
@@ -1377,7 +1764,9 @@ __private_extern__ CFURLRef _CFBundleCopySupportFilesDirectoryURLInDirectory(CFA
     return result;
 }
 
-CF_EXPORT CFURLRef CFBundleCopySupportFilesDirectoryURL(CFBundleRef bundle) {return _CFBundleCopySupportFilesDirectoryURLInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version);}
+CF_EXPORT CFURLRef CFBundleCopySupportFilesDirectoryURL(CFBundleRef bundle) {
+    return _CFBundleCopySupportFilesDirectoryURLInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version);
+}
 
 __private_extern__ CFURLRef _CFBundleCopyResourcesDirectoryURLInDirectory(CFAllocatorRef alloc, CFURLRef bundleURL, uint8_t version) {
     CFURLRef result = NULL;
@@ -1395,15 +1784,17 @@ __private_extern__ CFURLRef _CFBundleCopyResourcesDirectoryURLInDirectory(CFAllo
     return result;
 }
 
-CFURLRef CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle) {return _CFBundleCopyResourcesDirectoryURLInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version);}
+CFURLRef CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle) {
+    return _CFBundleCopyResourcesDirectoryURLInDirectory(CFGetAllocator(bundle), bundle->_url, bundle->_version);
+}
 
 static CFURLRef _CFBundleCopyExecutableURLRaw(CFAllocatorRef alloc, CFURLRef urlPath, CFStringRef exeName) {
     // Given an url to a folder and a name, this returns the url to the executable in that folder with that name, if it exists, and NULL otherwise.  This function deals with appending the ".exe" or ".dll" on Windows.
     CFURLRef executableURL = NULL;
     if (!urlPath || !exeName) return NULL;
     
-#if DEPLOYMENT_TARGET_MACOSX
-    const uint8_t *image_suffix = (uint8_t *)getenv("DYLD_IMAGE_SUFFIX");
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    const uint8_t *image_suffix = (uint8_t *)__CFgetenv("DYLD_IMAGE_SUFFIX");
     if (image_suffix) {
         CFStringRef newExeName, imageSuffix;
         imageSuffix = CFStringCreateWithCString(kCFAllocatorSystemDefault, (char *)image_suffix, kCFStringEncodingUTF8);
@@ -1415,27 +1806,81 @@ static CFURLRef _CFBundleCopyExecutableURLRaw(CFAllocatorRef alloc, CFURLRef url
             newExeName = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%@"), exeName, imageSuffix);
         }
         executableURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, newExeName, kCFURLPOSIXPathStyle, false, urlPath);
-        if (executableURL && !_urlExists(alloc, executableURL)) {
+        if (executableURL && !_binaryLoadable(alloc, executableURL)) {
             CFRelease(executableURL);
             executableURL = NULL;
         }
         CFRelease(newExeName);
         CFRelease(imageSuffix);
     }
-#endif
     if (!executableURL) {
         executableURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, exeName, kCFURLPOSIXPathStyle, false, urlPath);
+        if (executableURL && !_binaryLoadable(alloc, executableURL)) {
+            CFRelease(executableURL);
+            executableURL = NULL;
+        }
+    }
+#elif DEPLOYMENT_TARGET_WINDOWS
+    if (!executableURL) {
+        executableURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, exeName, kCFURLWindowsPathStyle, false, urlPath);
         if (executableURL && !_urlExists(alloc, executableURL)) {
             CFRelease(executableURL);
             executableURL = NULL;
         }
     }
-    return executableURL;
-}
-
-static CFStringRef _CFBundleCopyExecutableName(CFAllocatorRef alloc, CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict) {
-    CFStringRef executableName = NULL;
-    
+    if (!executableURL) {
+        if (!CFStringFindWithOptions(exeName, CFSTR(".dll"), CFRangeMake(0, CFStringGetLength(exeName)), kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL)) {
+            CFStringRef newExeName = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%@"), exeName, CFSTR(".dll"));
+            executableURL = CFURLCreateWithString(alloc, newExeName, urlPath);
+            if (executableURL && !_binaryLoadable(alloc, executableURL)) {
+                CFRelease(executableURL);
+                executableURL = NULL;
+            }
+            CFRelease(newExeName);
+        }
+    }
+    if (!executableURL) {
+        if (!CFStringFindWithOptions(exeName, CFSTR(".dll"), CFRangeMake(0, CFStringGetLength(exeName)), kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL)) {
+            CFStringRef newExeName = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%@"), exeName, CFSTR("_debug.dll"));
+            executableURL = CFURLCreateWithString(alloc, newExeName, urlPath);
+            if (executableURL && !_urlExists(alloc, executableURL)) {
+                CFRelease(executableURL);
+                executableURL = NULL;
+            }
+            CFRelease(newExeName);
+        }
+    }
+    if (!executableURL) {
+        if (!CFStringFindWithOptions(exeName, CFSTR(".exe"), CFRangeMake(0, CFStringGetLength(exeName)), kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL)) {
+            CFStringRef newExeName = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%@"), exeName, CFSTR(".exe"));
+            executableURL = CFURLCreateWithString(alloc, newExeName, urlPath);
+            if (executableURL && !_binaryLoadable(alloc, executableURL)) {
+                CFRelease(executableURL);
+                executableURL = NULL;
+            }
+            CFRelease(newExeName);
+        }
+    }
+    if (!executableURL) {
+        if (!CFStringFindWithOptions(exeName, CFSTR(".exe"), CFRangeMake(0, CFStringGetLength(exeName)), kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL)) {
+            CFStringRef newExeName = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%@"), exeName, CFSTR("_debug.exe"));
+            executableURL = CFURLCreateWithString(alloc, newExeName, urlPath);
+            if (executableURL && !_urlExists(alloc, executableURL)) {
+                CFRelease(executableURL);
+                executableURL = NULL;
+            }
+            CFRelease(newExeName);
+        }
+    }
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+    return executableURL;
+}
+
+static CFStringRef _CFBundleCopyExecutableName(CFAllocatorRef alloc, CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict) {
+    CFStringRef executableName = NULL;
+    
     if (!alloc && bundle) alloc = CFGetAllocator(bundle);
     if (!infoDict && bundle) infoDict = CFBundleGetInfoDictionary(bundle);
     if (!url && bundle) url = bundle->_url;
@@ -1466,9 +1911,7 @@ static CFStringRef _CFBundleCopyExecutableName(CFAllocatorRef alloc, CFBundleRef
         startOfBundleName = _CFStartOfLastPathComponent(buff, len);
         endOfBundleName = _CFLengthAfterDeletingPathExtension(buff, len);
 
-        if ((startOfBundleName <= len) && (endOfBundleName <= len) && (startOfBundleName < endOfBundleName)) {
-            executableName = CFStringCreateWithCharacters(alloc, &(buff[startOfBundleName]), (endOfBundleName - startOfBundleName));
-        }
+        if (startOfBundleName <= len && endOfBundleName <= len && startOfBundleName < endOfBundleName) executableName = CFStringCreateWithCharacters(alloc, &(buff[startOfBundleName]), endOfBundleName - startOfBundleName);
         CFRelease(bundlePath);
     }
     
@@ -1490,7 +1933,9 @@ __private_extern__ CFURLRef _CFBundleCopyResourceForkURLMayBeLocal(CFBundleRef b
     return resourceForkURL;
 }
 
-CFURLRef _CFBundleCopyResourceForkURL(CFBundleRef bundle) {return _CFBundleCopyResourceForkURLMayBeLocal(bundle, true);}
+CFURLRef _CFBundleCopyResourceForkURL(CFBundleRef bundle) {
+    return _CFBundleCopyResourceForkURLMayBeLocal(bundle, true);
+}
 
 static CFURLRef _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFAllocatorRef alloc, CFBundleRef bundle, CFURLRef url, CFStringRef executableName, Boolean ignoreCache, Boolean useOtherPlatform) {
     uint8_t version = 0;
@@ -1499,6 +1944,7 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFAllocatorRe
     CFURLRef executableURL = NULL;
     Boolean foundIt = false;
     Boolean lookupMainExe = (executableName ? false : true);
+    static CFSpinLock_t CFBundleExecutablePathLock = CFSpinLockInit;
     
     if (bundle) {
         infoDict = CFBundleGetInfoDictionary(bundle);
@@ -1509,27 +1955,37 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFAllocatorRe
 
     // If we have a bundle instance and an info dict, see if we have already cached the path
     if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && infoDict) {
+        __CFSpinLock(&CFBundleExecutablePathLock);
         executablePath = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundleExecutablePathKey);
+        if (executablePath) CFRetain(executablePath);
+        __CFSpinUnlock(&CFBundleExecutablePathLock);
         if (executablePath) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
             executableURL = CFURLCreateWithFileSystemPath(alloc, executablePath, kCFURLPOSIXPathStyle, false);
+#elif DEPLOYMENT_TARGET_WINDOWS
+            executableURL = CFURLCreateWithFileSystemPath(alloc, executablePath, kCFURLWindowsPathStyle, false);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif 
-            if (executableURL) foundIt = true;
-            if (!foundIt) {
-                executablePath = NULL;
+            if (executableURL) {
+                foundIt = true;
+            } else {
+                __CFSpinLock(&CFBundleExecutablePathLock);
                 CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, _kCFBundleExecutablePathKey);
+                __CFSpinUnlock(&CFBundleExecutablePathLock);
             }
+            CFRelease(executablePath);
         }
     }
 
     if (!foundIt) {
-        if (lookupMainExe) {
-            executableName = _CFBundleCopyExecutableName(alloc, bundle, url, infoDict);
-        }
+        if (lookupMainExe) executableName = _CFBundleCopyExecutableName(alloc, bundle, url, infoDict);
         if (executableName) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_EMBEDDED
+            Boolean doExecSearch = false;
+#else
             Boolean doExecSearch = true;
-#endif 
+#endif
             // Now, look for the executable inside the bundle.
             if (doExecSearch && 0 != version) {
                 CFURLRef exeDirURL;
@@ -1540,8 +1996,18 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFAllocatorRe
                 } else if (2 == version) {
                     exeDirURL = CFURLCreateWithString(alloc, _CFBundleExecutablesURLFromBase2, url);
                 } else {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+                    // On Windows, if the bundle URL is foo.resources, then the executable is at the same level as the .resources directory
+                    CFStringRef extension = CFURLCopyPathExtension(url);
+                    if (extension && CFEqual(extension, _CFBundleWindowsResourceDirectoryExtension)) {
+                        exeDirURL = CFURLCreateCopyDeletingLastPathComponent(alloc, url);
+                    } else {
+                        exeDirURL = (CFURLRef)CFRetain(url);
+                    }
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
                     exeDirURL = (CFURLRef)CFRetain(url);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
                 }
                 CFStringRef platformSubDir = useOtherPlatform ? _CFBundleGetOtherPlatformExecutablesSubdirectoryName() : _CFBundleGetPlatformExecutablesSubdirectoryName();
@@ -1565,48 +2031,74 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFAllocatorRe
                     exeSubdirURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, platformSubDir, kCFURLPOSIXPathStyle, true, exeDirURL);
                     executableURL = _CFBundleCopyExecutableURLRaw(alloc, exeSubdirURL, executableName);
                 }
-                if (!executableURL) {
-                    executableURL = _CFBundleCopyExecutableURLRaw(alloc, exeDirURL, executableName);
-                }
-
+                if (!executableURL) executableURL = _CFBundleCopyExecutableURLRaw(alloc, exeDirURL, executableName);
                 CFRelease(exeDirURL);
                 CFRelease(exeSubdirURL);
             }
 
-            // If this was an old bundle, or we did not find the executable in the Excutables subdirectory, look directly in the bundle wrapper.
+            // If this was an old bundle, or we did not find the executable in the Executables subdirectory, look directly in the bundle wrapper.
             if (!executableURL) executableURL = _CFBundleCopyExecutableURLRaw(alloc, url, executableName);
 
+#if DEPLOYMENT_TARGET_WINDOWS
+            // Windows only: If we still haven't found the exe, look in the Executables folder.
+            // But only for the main bundle exe
+            if (lookupMainExe && !executableURL) {
+                CFURLRef exeDirURL = CFURLCreateWithString(alloc, CFSTR("../../Executables"), url);
+                executableURL = _CFBundleCopyExecutableURLRaw(alloc, exeDirURL, executableName);
+                CFRelease(exeDirURL);
+            }
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
             if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && infoDict && executableURL) {
                 // We found it.  Cache the path.
                 CFURLRef absURL = CFURLCopyAbsoluteURL(executableURL);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+                executablePath = CFURLCopyFileSystemPath(absURL, kCFURLWindowsPathStyle);
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
                 executablePath = CFURLCopyFileSystemPath(absURL, kCFURLPOSIXPathStyle);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
                 CFRelease(absURL);
+                __CFSpinLock(&CFBundleExecutablePathLock);
                 CFDictionarySetValue((CFMutableDictionaryRef)infoDict, _kCFBundleExecutablePathKey, executablePath);
+                __CFSpinUnlock(&CFBundleExecutablePathLock);
                 CFRelease(executablePath);
             }
             if (lookupMainExe && !useOtherPlatform && bundle && !executableURL) bundle->_binaryType = __CFBundleNoBinary;
             if (lookupMainExe) CFRelease(executableName);
         }
     }
-
     if (!bundle && infoDict) CFRelease(infoDict);
-
     return executableURL;
 }
 
-CFURLRef _CFBundleCopyExecutableURLInDirectory(CFURLRef url) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(kCFAllocatorSystemDefault, NULL, url, NULL, true, false);}
+CFURLRef _CFBundleCopyExecutableURLInDirectory(CFURLRef url) {
+    return _CFBundleCopyExecutableURLInDirectoryWithAllocator(kCFAllocatorSystemDefault, NULL, url, NULL, true, false);
+}
 
-CFURLRef _CFBundleCopyOtherExecutableURLInDirectory(CFURLRef url) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(kCFAllocatorSystemDefault, NULL, url, NULL, true, true);}
+CFURLRef _CFBundleCopyOtherExecutableURLInDirectory(CFURLRef url) {
+    return _CFBundleCopyExecutableURLInDirectoryWithAllocator(kCFAllocatorSystemDefault, NULL, url, NULL, true, true);
+}
 
-CFURLRef CFBundleCopyExecutableURL(CFBundleRef bundle) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle), bundle, bundle->_url, NULL, false, false);}
+CFURLRef CFBundleCopyExecutableURL(CFBundleRef bundle) {
+    return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle), bundle, bundle->_url, NULL, false, false);
+}
 
-static CFURLRef _CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle), bundle, bundle->_url, NULL, true, false);}
+static CFURLRef _CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle) {
+    return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle), bundle, bundle->_url, NULL, true, false);
+}
 
-CFURLRef CFBundleCopyAuxiliaryExecutableURL(CFBundleRef bundle, CFStringRef executableName) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle), bundle, bundle->_url, executableName, true, false);}
+CFURLRef CFBundleCopyAuxiliaryExecutableURL(CFBundleRef bundle, CFStringRef executableName) {
+    return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle), bundle, bundle->_url, executableName, true, false);
+}
 
-Boolean CFBundleIsExecutableLoaded(CFBundleRef bundle) {return bundle->_isLoaded;}
+Boolean CFBundleIsExecutableLoaded(CFBundleRef bundle) {
+    return bundle->_isLoaded;
+}
 
 CFBundleExecutableType CFBundleGetExecutableType(CFBundleRef bundle) {
     CFBundleExecutableType result = kCFBundleOtherExecutableType;
@@ -1616,9 +2108,7 @@ CFBundleExecutableType CFBundleGetExecutableType(CFBundleRef bundle) {
 #if defined(BINARY_SUPPORT_DYLD)
     if (bundle->_binaryType == __CFBundleUnknownBinary) {
         bundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
-#if defined(BINARY_SUPPORT_CFM)
         if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
-#endif /* BINARY_SUPPORT_CFM */
     }
 #endif /* BINARY_SUPPORT_DYLD */
     if (executableURL) CFRelease(executableURL);
@@ -1635,6 +2125,23 @@ CFBundleExecutableType CFBundleGetExecutableType(CFBundleRef bundle) {
     return result;
 }
 
+static SInt32 _CFBundleCurrentArchitecture(void) {
+    SInt32 arch = 0;
+#if defined(__ppc__)
+    arch = kCFBundleExecutableArchitecturePPC;
+#elif defined(__ppc64__)
+    arch = kCFBundleExecutableArchitecturePPC64;
+#elif defined(__i386__)
+    arch = kCFBundleExecutableArchitectureI386;
+#elif defined(__x86_64__)
+    arch = kCFBundleExecutableArchitectureX86_64;
+#elif defined(BINARY_SUPPORT_DYLD)
+    const NXArchInfo *archInfo = NXGetLocalArchInfo();
+    if (archInfo) arch = archInfo->cputype;
+#endif
+    return arch;
+}
+
 #define UNKNOWN_FILETYPE 0x0
 #define PEF_FILETYPE 0x1000
 #define PEF_MAGIC 0x4a6f7921
@@ -1643,6 +2150,8 @@ CFBundleExecutableType CFBundleGetExecutableType(CFBundleRef bundle) {
 #define PLIST_SECTION "__info_plist"
 #define OBJC_SEGMENT "__OBJC"
 #define IMAGE_INFO_SECTION "__image_info"
+#define OBJC_SEGMENT_64 "__DATA"
+#define IMAGE_INFO_SECTION_64 "__objc_imageinfo"
 #define LIB_X11 "/usr/X11R6/lib/libX"
 
 #define XLS_NAME "Book"
@@ -1661,7 +2170,7 @@ static const uint32_t __CFBundleMagicNumbersArray[] = {
     0x53495444, 0x53747566, 0x30373037, 0x3c212d2d, 0x25215053, 0xd0cf11e0, 0x62656769, 0x3d796265,
     0x6b6f6c79, 0x3026b275, 0x0000000c, 0xfe370023, 0x09020600, 0x09040600, 0x4f676753, 0x664c6143, 
     0x00010000, 0x74727565, 0x4f54544f, 0x41433130, 0xc809fe02, 0x0809fe02, 0x2356524d, 0x67696d70, 
-    0x3c435058, 0x28445746, 0x424f4d53, 0x49544f4c, 0x72746664
+    0x3c435058, 0x28445746, 0x424f4d53, 0x49544f4c, 0x72746664, 0x63616666, 0x802a5fd7, 0x762f3101
 };
 
 // string, with groups of 5 characters being 1 element in the array
@@ -1673,13 +2182,13 @@ static const char * __CFBundleExtensionsArray =
     "sit\0\0" "sit\0\0" "cpio\0"  "html\0"  "ps\0\0\0""ole\0\0" "uu\0\0\0""ync\0\0"
     "dmg\0\0" "wmv\0\0" "jp2\0\0" "doc\0\0" "xls\0\0" "xls\0\0" "ogg\0\0" "flac\0"
     "ttf\0\0" "ttf\0\0" "otf\0\0" "dwg\0\0" "dgn\0\0" "dgn\0\0" "wrl\0\0" "xcf\0\0"
-    "cpx\0\0" "dwf\0\0" "bom\0\0" "lit\0\0" "rtfd\0";
+    "cpx\0\0" "dwf\0\0" "bom\0\0" "lit\0\0" "rtfd\0"  "caf\0\0" "cin\0\0" "exr\0\0";
 
 static const char * __CFBundleOOExtensionsArray = "sxc\0\0" "sxd\0\0" "sxg\0\0" "sxi\0\0" "sxm\0\0" "sxw\0\0";
 static const char * __CFBundleODExtensionsArray = "odc\0\0" "odf\0\0" "odg\0\0" "oth\0\0" "odi\0\0" "odm\0\0" "odp\0\0" "ods\0\0" "odt\0\0";
 
 #define EXTENSION_LENGTH                5
-#define NUM_EXTENSIONS                  61
+#define NUM_EXTENSIONS                  64
 #define MAGIC_BYTES_TO_READ             512
 #define DMG_BYTES_TO_READ               512
 #define ZIP_BYTES_TO_READ               1024
@@ -1692,7 +2201,7 @@ static const char * __CFBundleODExtensionsArray = "odc\0\0" "odf\0\0" "odg\0\0"
 CF_INLINE uint32_t _CFBundleSwapInt32Conditional(uint32_t arg, Boolean swap) {return swap ? CFSwapInt32(arg) : arg;}
 CF_INLINE uint32_t _CFBundleSwapInt64Conditional(uint64_t arg, Boolean swap) {return swap ? CFSwapInt64(arg) : arg;}
 
-static CFDictionaryRef _CFBundleGrokInfoDictFromData(const char *bytes, uint32_t length) {
+static CFMutableDictionaryRef _CFBundleGrokInfoDictFromData(const char *bytes, uint32_t length) {
     CFMutableDictionaryRef result = NULL;
     CFDataRef infoData = NULL;
     if (bytes && 0 < length) {
@@ -1710,22 +2219,54 @@ static CFDictionaryRef _CFBundleGrokInfoDictFromData(const char *bytes, uint32_t
     return result;
 }
 
-static CFDictionaryRef _CFBundleGrokInfoDictFromMainExecutable() {
+static char *_CFBundleGetSectData(const char *segname, const char *sectname, unsigned long *size) {
+    char *retval = NULL;
+    unsigned long localSize = 0;
+    uint32_t i, numImages = _dyld_image_count();
+    const void *mhp = (const void *)_NSGetMachExecuteHeader();
+    
+    for (i = 0; i < numImages; i++) {
+        if (mhp == (void *)_dyld_get_image_header(i)) {
+#if __LP64__
+            const struct section_64 *sp = getsectbynamefromheader_64((const struct mach_header_64 *)mhp, segname, sectname);
+            if (sp) {
+                retval = (char *)(sp->addr + _dyld_get_image_vmaddr_slide(i));
+                localSize = (unsigned long)sp->size;
+            }
+#else /* __LP64__ */
+            const struct section *sp = getsectbynamefromheader((const struct mach_header *)mhp, segname, sectname);
+            if (sp) {
+                retval = (char *)(sp->addr + _dyld_get_image_vmaddr_slide(i));
+                localSize = (unsigned long)sp->size;
+            }
+#endif /* __LP64__ */
+            break;
+        }
+    }
+    if (size) *size = localSize;
+    return retval;
+}
+
+static CFMutableDictionaryRef _CFBundleGrokInfoDictFromMainExecutable() {
+    char *bytes = NULL;
     unsigned long length = 0;
-    char *bytes = getsectdata(TEXT_SEGMENT, PLIST_SECTION, &length);
+    if (getsegbyname(TEXT_SEGMENT)) bytes = _CFBundleGetSectData(TEXT_SEGMENT, PLIST_SECTION, &length);
     return _CFBundleGrokInfoDictFromData(bytes, length);
 }
 
 static Boolean _CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion, uint32_t *objcFlags) {
     Boolean retval = false;
     uint32_t localVersion = 0, localFlags = 0;
-    if (getsegbyname(OBJC_SEGMENT)) {
-        unsigned long length = 0;
-        char *bytes = getsectdata(OBJC_SEGMENT, IMAGE_INFO_SECTION, &length);
-        if (bytes && length >= 8) {
-            localVersion = *(uint32_t *)bytes;
-            localFlags = *(uint32_t *)(bytes + 4);
-        }
+    char *bytes = NULL;
+    unsigned long length = 0;
+#if __LP64__
+    if (getsegbyname(OBJC_SEGMENT_64)) bytes = _CFBundleGetSectData(OBJC_SEGMENT_64, IMAGE_INFO_SECTION_64, &length);
+#else /* __LP64__ */
+    if (getsegbyname(OBJC_SEGMENT)) bytes = _CFBundleGetSectData(OBJC_SEGMENT, IMAGE_INFO_SECTION, &length);
+#endif /* __LP64__ */
+    if (bytes && length >= 8) {
+        localVersion = *(uint32_t *)bytes;
+        localFlags = *(uint32_t *)(bytes + 4);
         retval = true;
     }
     if (objcVersion) *objcVersion = localVersion;
@@ -1779,9 +2320,7 @@ static Boolean _CFBundleGrokX11FromFile(int fd, const void *bytes, CFIndex lengt
             }
         }
     }
-    
     if (buffer) free(buffer);
-    
     return result;
 }
     
@@ -1819,7 +2358,7 @@ static CFDictionaryRef _CFBundleGrokInfoDictFromFile(int fd, const void *bytes,
                             uint32_t sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped);
                             const char *sectbytes = loc + offset + sectoffset;
                             // we don't support huge-sized plists
-                            if (sectlength64 <= 0xffffffff && loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = _CFBundleGrokInfoDictFromData(sectbytes, sectlength);
+                            if (sectlength64 <= 0xffffffff && loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = (CFDictionaryRef)_CFBundleGrokInfoDictFromData(sectbytes, sectlength);
                             foundit = true;
                         }
                         sp = (struct section_64 *)((char *)sp + sizeof(struct section_64));
@@ -1843,7 +2382,7 @@ static CFDictionaryRef _CFBundleGrokInfoDictFromFile(int fd, const void *bytes,
                             uint32_t sectlength = _CFBundleSwapInt32Conditional(sp->size, swapped);
                             uint32_t sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped);
                             const char *sectbytes = loc + offset + sectoffset;
-                            if (loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = _CFBundleGrokInfoDictFromData(sectbytes, sectlength);
+                            if (loc <= sectbytes && sectbytes + sectlength <= loc + fileLength) result = (CFDictionaryRef)_CFBundleGrokInfoDictFromData(sectbytes, sectlength);
                             foundit = true;
                         }
                         sp = (struct section *)((char *)sp + sizeof(struct section));
@@ -1884,8 +2423,8 @@ static void _CFBundleGrokObjcImageInfoFromFile(int fd, const void *bytes, CFInde
                     struct section_64 *sp = (struct section_64 *)((char *)sgp + sizeof(struct segment_command_64));
                     uint32_t nsects = _CFBundleSwapInt32Conditional(sgp->nsects, swapped);
                     for (j = 0; !foundit && j < nsects && startofcmds <= (char *)sp && (char *)sp < endofcmds; j++) {
-                        if (0 == strncmp(sp->segname, OBJC_SEGMENT, sizeof(sp->segname))) localHasObjc = true;
-                        if (0 == strncmp(sp->sectname, IMAGE_INFO_SECTION, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, OBJC_SEGMENT, sizeof(sp->segname))) {
+                        if (0 == strncmp(sp->segname, OBJC_SEGMENT_64, sizeof(sp->segname))) localHasObjc = true;
+                        if (0 == strncmp(sp->sectname, IMAGE_INFO_SECTION_64, sizeof(sp->sectname)) && 0 == strncmp(sp->segname, OBJC_SEGMENT_64, sizeof(sp->segname))) {
                             uint64_t sectlength64 = _CFBundleSwapInt64Conditional(sp->size, swapped);
                             sectlength = (uint32_t)(sectlength64 & 0xffffffff);
                             sectoffset = _CFBundleSwapInt32Conditional(sp->offset, swapped);
@@ -1930,19 +2469,21 @@ static void _CFBundleGrokObjcImageInfoFromFile(int fd, const void *bytes, CFInde
             }
         }
     }
-    
     if (buffer) free(buffer);
-    
     if (hasObjc) *hasObjc = localHasObjc;
     if (objcVersion) *objcVersion = localVersion;
     if (objcFlags) *objcFlags = localFlags;
 }
     
-static UInt32 _CFBundleGrokMachTypeForFatFile(int fd, const void *bytes, CFIndex length, Boolean *isX11, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) {
-    UInt32 machtype = UNKNOWN_FILETYPE, magic, numFatHeaders = ((struct fat_header *)bytes)->nfat_arch, maxFatHeaders = (length - sizeof(struct fat_header)) / sizeof(struct fat_arch), i;
+static UInt32 _CFBundleGrokMachTypeForFatFile(int fd, const void *bytes, CFIndex length, Boolean swap, Boolean *isX11, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) {
+    CFIndex headerLength = length;
+    unsigned char headerBuffer[MAGIC_BYTES_TO_READ];
+    UInt32 machtype = UNKNOWN_FILETYPE, magic, numFatHeaders, maxFatHeaders, i;
     unsigned char buffer[sizeof(struct mach_header_64)];
     const unsigned char *moreBytes = NULL;
     const NXArchInfo *archInfo = NXGetLocalArchInfo();
+    SInt32 curArch = _CFBundleCurrentArchitecture();
+    
     struct fat_arch *fat = NULL;
 
     if (isX11) *isX11 = false;
@@ -1951,14 +2492,23 @@ static UInt32 _CFBundleGrokMachTypeForFatFile(int fd, const void *bytes, CFIndex
     if (hasObjc) *hasObjc = false;
     if (objcVersion) *objcVersion = 0;
     if (objcFlags) *objcFlags = 0;
+
+    if (headerLength > MAGIC_BYTES_TO_READ) headerLength = MAGIC_BYTES_TO_READ;
+    (void)memmove(headerBuffer, bytes, headerLength);
+    if (swap) {
+        for (i = 0; i < headerLength; i += 4) *(UInt32 *)(headerBuffer + i) = CFSwapInt32(*(UInt32 *)(headerBuffer + i));
+    }
+    numFatHeaders = ((struct fat_header *)headerBuffer)->nfat_arch;
+    maxFatHeaders = (headerLength - sizeof(struct fat_header)) / sizeof(struct fat_arch);
     if (numFatHeaders > maxFatHeaders) numFatHeaders = maxFatHeaders;
     if (numFatHeaders > 0) {
-        fat = NXFindBestFatArch(archInfo->cputype, archInfo->cpusubtype, (struct fat_arch *)(bytes + sizeof(struct fat_header)), numFatHeaders);
-        if (!fat) fat = (struct fat_arch *)(bytes + sizeof(struct fat_header));
+        if (archInfo) fat = NXFindBestFatArch(archInfo->cputype, archInfo->cpusubtype, (struct fat_arch *)(headerBuffer + sizeof(struct fat_header)), numFatHeaders);
+        if (!fat && curArch != 0) fat = NXFindBestFatArch((cpu_type_t)curArch, (cpu_subtype_t)0, (struct fat_arch *)(headerBuffer + sizeof(struct fat_header)), numFatHeaders);
+        if (!fat) fat = (struct fat_arch *)(headerBuffer + sizeof(struct fat_header));
         if (architectures) {
             CFMutableArrayRef mutableArchitectures = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
             for (i = 0; i < numFatHeaders; i++) {
-                CFNumberRef architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, bytes + sizeof(struct fat_header) + i * sizeof(struct fat_arch));
+                CFNumberRef architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, headerBuffer + sizeof(struct fat_header) + i * sizeof(struct fat_arch));
                 if (CFArrayGetFirstIndexOfValue(mutableArchitectures, CFRangeMake(0, CFArrayGetCount(mutableArchitectures)), architecture) < 0) CFArrayAppendValue(mutableArchitectures, architecture);
                 CFRelease(architecture);
             }
@@ -2000,9 +2550,8 @@ static UInt32 _CFBundleGrokMachTypeForFatFile(int fd, const void *bytes, CFIndex
 }
 
 static UInt32 _CFBundleGrokMachType(int fd, const void *bytes, CFIndex length, Boolean *isX11, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) {
-    unsigned int magic = *((UInt32 *)bytes), machtype = UNKNOWN_FILETYPE;
+    unsigned int magic = *((UInt32 *)bytes), machtype = UNKNOWN_FILETYPE, cputype;
     CFNumberRef architecture = NULL;
-    CFIndex i;
 
     if (isX11) *isX11 = false;
     if (architectures) *architectures = NULL;
@@ -2012,35 +2561,36 @@ static UInt32 _CFBundleGrokMachType(int fd, const void *bytes, CFIndex length, B
     if (objcFlags) *objcFlags = 0;
     if (MH_MAGIC == magic) {
         machtype = ((struct mach_header *)bytes)->filetype;
+        cputype = ((struct mach_header *)bytes)->cputype;
+        if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype);
         if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, false, false);
-        if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, bytes + 4);
         if (infodict) *infodict = _CFBundleGrokInfoDictFromFile(fd, bytes, length, 0, false, false);
         if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, false, false, hasObjc, objcVersion, objcFlags);
     } else if (MH_CIGAM == magic) {
-        for (i = 0; i < length; i += 4) *(UInt32 *)(bytes + i) = CFSwapInt32(*(UInt32 *)(bytes + i));
-        machtype = ((struct mach_header *)bytes)->filetype;
+        machtype = CFSwapInt32(((struct mach_header *)bytes)->filetype);
+        cputype = CFSwapInt32(((struct mach_header *)bytes)->cputype);
+        if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype);
         if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, true, false);
-        if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, bytes + 4);
         if (infodict) *infodict = _CFBundleGrokInfoDictFromFile(fd, bytes, length, 0, true, false);
         if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, true, false, hasObjc, objcVersion, objcFlags);
     } else if (MH_MAGIC_64 == magic) {
         machtype = ((struct mach_header_64 *)bytes)->filetype;
+        cputype = ((struct mach_header_64 *)bytes)->cputype;
+        if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype);
         if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, false, true);
-        if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, bytes + 4);
         if (infodict) *infodict = _CFBundleGrokInfoDictFromFile(fd, bytes, length, 0, false, true);
         if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, false, true, hasObjc, objcVersion, objcFlags);
     } else if (MH_CIGAM_64 == magic) {
-        for (i = 0; i < length; i += 4) *(UInt32 *)(bytes + i) = CFSwapInt32(*(UInt32 *)(bytes + i));
-        machtype = ((struct mach_header_64 *)bytes)->filetype;
+        machtype = CFSwapInt32(((struct mach_header_64 *)bytes)->filetype);
+        cputype = CFSwapInt32(((struct mach_header_64 *)bytes)->cputype);
+        if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, &cputype);
         if (isX11 && MH_EXECUTE == machtype) *isX11 = _CFBundleGrokX11FromFile(fd, bytes, length, 0, true, true);
-        if (architectures) architecture = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, bytes + 4);
         if (infodict) *infodict = _CFBundleGrokInfoDictFromFile(fd, bytes, length, 0, true, true);
         if (hasObjc || objcVersion || objcFlags) _CFBundleGrokObjcImageInfoFromFile(fd, bytes, length, 0, true, true, hasObjc, objcVersion, objcFlags);
     } else if (FAT_MAGIC == magic) {
-        machtype = _CFBundleGrokMachTypeForFatFile(fd, bytes, length, isX11, architectures, infodict, hasObjc, objcVersion, objcFlags);
+        machtype = _CFBundleGrokMachTypeForFatFile(fd, bytes, length, false, isX11, architectures, infodict, hasObjc, objcVersion, objcFlags);
     } else if (FAT_CIGAM == magic) {
-        for (i = 0; i < length; i += 4) *(UInt32 *)(bytes + i) = CFSwapInt32(*(UInt32 *)(bytes + i));
-        machtype = _CFBundleGrokMachTypeForFatFile(fd, bytes, length, isX11, architectures, infodict, hasObjc, objcVersion, objcFlags);
+        machtype = _CFBundleGrokMachTypeForFatFile(fd, bytes, length, true, isX11, architectures, infodict, hasObjc, objcVersion, objcFlags);
     } else if (PEF_MAGIC == magic || PEF_CIGAM == magic) {
         machtype = PEF_FILETYPE;
     }
@@ -2208,16 +2758,20 @@ static const char *_CFBundleGrokFileTypeForOLEFile(int fd, const void *bytes, CF
             else foundit = false;
         }
     }
-
     if (buffer) free(buffer);
-
     return ext;
 }
 
+#if DEPLOYMENT_TARGET_WINDOWS
+// Windows isspace implementation limits the input chars to < 256 in the ASCII range.  It will
+// assert in debug builds.  This is annoying.  We merrily grok chars > 256.
+static inline BOOL isspace(char c) {
+    return (c == ' ' || c == '\t' || c == '\n' || c == '\r'|| c == '\v' || c == '\f');
+}
+#endif
+
 static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *extension, UInt32 *machtype, CFArrayRef *architectures, CFDictionaryRef *infodict, Boolean *hasObjc, uint32_t *objcVersion, uint32_t *objcFlags) {
-    struct stat statBuf;
     int fd = -1;
-    char path[CFMaxPathSize];
     const unsigned char *bytes = NULL;
     unsigned char buffer[MAGIC_BYTES_TO_READ];
     CFIndex i, length = 0;
@@ -2227,8 +2781,8 @@ static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *
 #if defined(BINARY_SUPPORT_DYLD)
     Boolean isX11 = false;
 #endif /* BINARY_SUPPORT_DYLD */
-    Boolean isFile = false, isPlain = true, isZero = true, isHTML = false;
-    // extensions returned:  o, tool, x11app, pef, core, dylib, bundle, elf, jpeg, jp2, tiff, gif, png, pict, icns, ico, rtf, rtfd, pdf, ra, rm, au, aiff, aifc, wav, avi, wmv, ogg, flac, psd, mpeg, mid, zip, jar, sit, cpio, html, ps, mov, qtif, ttf, otf, sfont, bmp, hqx, bin, class, tar, txt, gz, Z, uu, ync, bz, bz2, sh, pl, py, rb, dvi, sgi, tga, mp3, xml, plist, xls, doc, ppt, mp4, m4a, m4b, m4p, dmg, cwk, webarchive, dwg, dgn, pfa, pfb, afm, tfm, xcf, cpx, dwf, swf, swc, abw, bom, lit, svg, rdf, x3d, oeb, dtb, docx, xlsx, pptx, sxc, sxd, sxg, sxi, sxm, sxw, odc, odf, odg, oth, odi, odm, odp, ods
+    Boolean isFile = false, isPlain = true, isZero = true, isSpace = true, hasBOM = false;
+    // extensions returned:  o, tool, x11app, pef, core, dylib, bundle, elf, jpeg, jp2, tiff, gif, png, pict, icns, ico, rtf, rtfd, pdf, ra, rm, au, aiff, aifc, caf, wav, avi, wmv, ogg, flac, psd, mpeg, mid, zip, jar, sit, cpio, html, ps, mov, qtif, ttf, otf, sfont, bmp, hqx, bin, class, tar, txt, gz, Z, uu, ync, bz, bz2, sh, pl, py, rb, dvi, sgi, tga, mp3, xml, plist, xls, doc, ppt, mp4, m4a, m4b, m4p, m4v, 3gp, 3g2, dmg, cwk, webarchive, dwg, dgn, pfa, pfb, afm, tfm, xcf, cpx, dwf, swf, swc, abw, bom, lit, svg, rdf, x3d, oeb, dtb, docx, xlsx, pptx, sxc, sxd, sxg, sxi, sxm, sxw, odc, odf, odg, oth, odi, odm, odp, ods, cin, exr
     // ??? we do not distinguish between different wm types, returning wmv for any of wmv, wma, or asf
     // ??? we do not distinguish between ordinary documents and template versions (often there is no difference in file contents)
     // ??? the distinctions between docx, xlsx, and pptx may not be entirely reliable
@@ -2237,12 +2791,25 @@ static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *
     if (hasObjc) *hasObjc = false;
     if (objcVersion) *objcVersion = 0;
     if (objcFlags) *objcFlags = 0;
-    if (url && CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize) && stat(path, &statBuf) == 0 && (statBuf.st_mode & S_IFMT) == S_IFREG && (fd = open(path, O_RDONLY, 0777)) >= 0) {
-        length = read(fd, buffer, MAGIC_BYTES_TO_READ);
-        fileLength = statBuf.st_size;
-        bytes = buffer;
-        isFile = true;
-    } else if (data) {
+    if (url) {
+        Boolean gotPath = FALSE;
+        char path[CFMaxPathSize];
+        gotPath = CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+        struct stat statBuf;
+#elif DEPLOYMENT_TARGET_WINDOWS
+        struct _stat statBuf;
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+        if (gotPath && stat(path, &statBuf) == 0 && (statBuf.st_mode & S_IFMT) == S_IFREG && (fd = open(path, O_RDONLY | CF_OPENFLGS, 0777)) >= 0) {
+            length = read(fd, buffer, MAGIC_BYTES_TO_READ);
+            fileLength = statBuf.st_size;
+            bytes = buffer;
+            isFile = true;
+        }
+    }
+    if (!isFile && data) {
         length = CFDataGetLength(data);
         fileLength = (off_t)length;
         bytes = CFDataGetBytePtr(data);
@@ -2267,6 +2834,7 @@ static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *
                 else if (MH_BUNDLE == mt) ext = "bundle";
 #endif /* BINARY_SUPPORT_DYLD */
                 else if (0x7b5c7274 == magic && (6 > length || 'f' != bytes[4])) ext = NULL;
+                else if (0x25504446 == magic && (6 > length || '-' != bytes[4])) ext = NULL;
                 else if (0x00010000 == magic && (6 > length || 0 != bytes[4])) ext = NULL;
                 else if (0x47494638 == magic && (6 > length || (0x3761 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))) && 0x3961 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))))))  ext = NULL;
                 else if (0x0000000c == magic && (6 > length || 0x6a50 != CFSwapInt16HostToBig(*((UInt16 *)(bytes + 4))))) ext = NULL;
@@ -2282,9 +2850,13 @@ static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *
                 else if (0x49544f4c == magic && (8 > length || 0x49544c53 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL;
                 else if (0x72746664 == magic && (8 > length || 0x00000000 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = NULL;
                 else if (0x3d796265 == magic && (12 > length || 0x67696e20 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || (0x6c696e65 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))) && 0x70617274 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8)))))) ext = NULL;
-                else if (0x25215053 == magic && 14 <= length && 0 == ustrncmp(bytes + 4, "-AdobeFont", 10)) ext = "pfa"; 
+                else if (0x63616666 == magic && (12 > length || 0 != bytes[4] || 0x64657363 != CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8))))) ext = NULL;
                 else if (0x504b0304 == magic) ext = _CFBundleGrokFileTypeForZipFile(fd, bytes, length, fileLength);
-                else if (0x464f524d == magic) {
+                else if (0x25215053 == magic) {
+                    if (11 <= length && 0 == ustrncmp(bytes + 4, "-Adobe-", 7)) ext = "ps";
+                    else if (14 <= length && 0 == ustrncmp(bytes + 4, "-AdobeFont", 10)) ext = "pfa";
+                    else ext = NULL;
+                } else if (0x464f524d == magic) {
                     // IFF
                     ext = NULL;
                     if (12 <= length) {
@@ -2327,18 +2899,27 @@ static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *
                         if (0 == ustrncmp(bytes + i, "WebMainResource", 15)) ext = "webarchive";
                     }
                     if (!ext) ext = "plist";
-                } else if (12 <= length && 0x66747970 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4)))) {
-                    // ??? list of ftyp values needs to be checked
-                    if (0x6d703432 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8)))) ext = "mp4";
-                    else if (0x4d344120 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8)))) ext = "m4a";
-                    else if (0x4d344220 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8)))) ext = "m4b";
-                    else if (0x4d345020 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8)))) ext = "m4p";
-                } else if (0x424d == shortMagic && 18 <= length && 40 == CFSwapInt32HostToLittle(*((UInt32 *)(bytes + 14)))) ext = "bmp";
-                else if (20 <= length && 0 == ustrncmp(bytes + 6, "%!PS-AdobeFont", 14)) ext = "pfb";
+                } else if (0 == shortMagic && 12 <= length && 0x66747970 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4)))) {
+                    // ??? may want more ftyp values
+                    UInt32 ftyp = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 8)));
+                    if (0x6d703431 == ftyp || 0x6d703432 == ftyp || 0x69736f6d == ftyp || 0x69736f32 == ftyp) ext = "mp4";
+                    else if (0x4d344120 == ftyp) ext = "m4a";
+                    else if (0x4d344220 == ftyp) ext = "m4b";
+                    else if (0x4d345020 == ftyp) ext = "m4p";
+                    else if (0x4d345620 == ftyp || 0x4d345648 == ftyp || 0x4d345650 == ftyp) ext = "m4v";
+                    else if (0x3367 == (ftyp >> 16)) {
+                        UInt16 remainder = (ftyp & 0xffff);
+                        if (0x6536 == remainder || 0x6537 == remainder || 0x6736 == remainder || 0x7034 == remainder || 0x7035 == remainder || 0x7036 == remainder || 0x7236 == remainder || 0x7336 == remainder || 0x7337 == remainder) ext = "3gp";
+                        else if (0x3261 == remainder) ext = "3g2";
+                    }
+                } else if (0x424d == shortMagic && 18 <= length) {
+                    UInt32 btyp = CFSwapInt32HostToLittle(*((UInt32 *)(bytes + 14)));
+                    if (40 == btyp || btyp == 12 || btyp == 64 || btyp == 108 || btyp == 124) ext = "bmp";
+                } else if (20 <= length && 0 == ustrncmp(bytes + 6, "%!PS-AdobeFont", 14)) ext = "pfb";
                 else if (40 <= length && 0x42696e48 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 34))) && 0x6578 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 38)))) ext = "hqx";
                 else if (128 <= length && 0x6d42494e == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 102)))) ext = "bin";
                 else if (128 <= length && 0 == bytes[0] && 0 < bytes[1] && bytes[1] < 64 && 0 == bytes[74] && 0 == bytes[82] && 0 == (fileLength % 128)) {
-                    unsigned df = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 83))), rf = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 87))), blocks = 1 + (df + 127) / 128 + (rf + 127) / 128;
+                    UInt32 df = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 83))), rf = CFSwapInt32HostToBig(*((UInt32 *)(bytes + 87))), blocks = 1 + (df + 127) / 128 + (rf + 127) / 128;
                     if (df < 0x00800000 && rf < 0x00800000 && 1 < blocks && (off_t)(128 * blocks) == fileLength) ext = "bin";
                 } else if (265 <= length && 0x75737461 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 257))) && (0x72202000 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 261))) || 0x7200 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 261))))) ext = "tar";
                 else if (0xfeff == shortMagic || 0xfffe == shortMagic) ext = "txt";
@@ -2366,46 +2947,56 @@ static Boolean _CFBundleGrokFileType(CFURLRef url, CFDataRef data, CFStringRef *
                 else if (0x425a == shortMagic && isdigit(bytes[2]) && isdigit(bytes[3])) ext = "bz";
                 else if (0x425a == shortMagic && 'h' == bytes[2] && isdigit(bytes[3]) && 8 <= length && (0x31415926 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))) || 0x17724538 == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 4))))) ext = "bz2";
                 else if (0x0011 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 2))) || 0x0012 == CFSwapInt16HostToBig(*((UInt16 *)(bytes + 2)))) ext = "tfm";
-                else if ('<' == bytes[0] && 14 <= length) {
-                    if (0 == ustrncasecmp(bytes + 1, "!doctype html", 13) || 0 == ustrncasecmp(bytes + 1, "head", 4) || 0 == ustrncasecmp(bytes + 1, "title", 5) || 0 == ustrncasecmp(bytes + 1, "html", 4)) {
+            }
+        }
+        if (extension && !ext) {
+            //??? what about MacOSRoman?
+            if (0xef == bytes[0] && 0xbb == bytes[1] && 0xbf == bytes[2]) {   // UTF-8 BOM
+                hasBOM = true;
+                isZero = false;
+            }
+            for (i = (hasBOM ? 3 : 0); (isPlain || isZero) && !ext && i < length && i < 512; i++) {
+                char c = bytes[i];
+                if (isPlain && '<' == c && i + 14 <= length && 0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13)) ext = "html";
+                if (isSpace && '<' == c && i + 14 <= length) {
+                    if (0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13) || 0 == ustrncasecmp(bytes + i + 1, "head", 4) || 0 == ustrncasecmp(bytes + i + 1, "title", 5) || 0 == ustrncasecmp(bytes + i + 1, "script", 6) || 0 == ustrncasecmp(bytes + i + 1, "html", 4)) {
                         ext = "html";
-                    } else if (0 == ustrncasecmp(bytes + 1, "?xml", 4)) {
-                        for (i = 4; !ext && i < 128 && i + 20 <= length; i++) {
+                    } else if (0 == ustrncasecmp(bytes + i + 1, "?xml", 4)) {
+                        for (i += 4; !ext && i < 128 && i + 20 <= length; i++) {
                             if ('<' == bytes[i]) {
                                 if (0 == ustrncasecmp(bytes + i + 1, "abiword", 7)) ext = "abw";
                                 else if (0 == ustrncasecmp(bytes + i + 1, "!doctype svg", 12)) ext = "svg";
                                 else if (0 == ustrncasecmp(bytes + i + 1, "!doctype rdf", 12)) ext = "rdf";
                                 else if (0 == ustrncasecmp(bytes + i + 1, "!doctype x3d", 12)) ext = "x3d";
                                 else if (0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13)) ext = "html";
-                                else if (0 == ustrncasecmp(bytes + i + 1, "!doctype plist", 14)) ext = "plist";
                                 else if (0 == ustrncasecmp(bytes + i + 1, "!doctype posingfont", 19)) ext = "sfont";
+                                else if (0 == ustrncasecmp(bytes + i + 1, "!doctype plist", 14)) {
+                                    for (i += 14; !ext && i < 256 && i + 16 <= length; i++) {
+                                        if (0 == ustrncmp(bytes + i, "WebMainResource", 15)) ext = "webarchive";
+                                    }
+                                    if (!ext) ext = "plist";
+                                }
                             }
                         }
                         if (!ext) ext = "xml";
                     }
                 }
-            }
-        }
-        if (extension && !ext) {
-            //??? what about MacOSRoman?
-            for (i = 0; (isPlain || isZero) && !isHTML && i < length && i < 512; i++) {
-                char c = bytes[i];
-                if (0x7f <= c || (0x20 > c && !isspace(c))) isPlain = false;
                 if (0 != c) isZero = false;
-                if (isPlain && '<' == c && i + 14 <= length && 0 == ustrncasecmp(bytes + i + 1, "!doctype html", 13)) isHTML = true;
-            }
-            if (isHTML) {
-                ext = "html";
-            } else if (isPlain) {
-                if (16 <= length && 0 == ustrncmp(bytes, "StartFontMetrics", 16)) ext = "afm";
-                else ext = "txt";
-            } else if (isZero && length >= MAGIC_BYTES_TO_READ && fileLength >= 526) {
-                if (isFile) {
-                    if (lseek(fd, 512, SEEK_SET) == 512 && read(fd, buffer, MAGIC_BYTES_TO_READ) >= 14) {
-                        if (0x001102ff == CFSwapInt32HostToBig(*((UInt32 *)(buffer + 10)))) ext = "pict";
+                if (isZero || 0x7f <= c || (0x20 > c && !isspace(c))) isPlain = false;
+                if (isZero || !isspace(c)) isSpace = false;
+            }
+            if (!ext) {
+                if (isPlain) {
+                    if (16 <= length && 0 == ustrncmp(bytes, "StartFontMetrics", 16)) ext = "afm";
+                    else ext = "txt";
+                } else if (isZero && length >= MAGIC_BYTES_TO_READ && fileLength >= 526) {
+                    if (isFile) {
+                        if (lseek(fd, 512, SEEK_SET) == 512 && read(fd, buffer, MAGIC_BYTES_TO_READ) >= 14) {
+                            if (0x001102ff == CFSwapInt32HostToBig(*((UInt32 *)(buffer + 10)))) ext = "pict";
+                        }
+                    } else {
+                        if (526 <= length && 0x001102ff == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 522)))) ext = "pict";
                     }
-                } else {
-                    if (526 <= length && 0x001102ff == CFSwapInt32HostToBig(*((UInt32 *)(bytes + 522)))) ext = "pict";
                 }
             }
         }
@@ -2449,16 +3040,18 @@ __private_extern__ CFArrayRef _CFBundleCopyArchitecturesForExecutable(CFURLRef u
     return result;
 }
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static Boolean _CFBundleGetObjCImageInfoForExecutable(CFURLRef url, uint32_t *objcVersion, uint32_t *objcFlags) {
     Boolean retval = false;
     (void)_CFBundleGrokFileType(url, NULL, NULL, NULL, NULL, NULL, &retval, objcVersion, objcFlags);
     return retval;
 }
+#endif
 
 #if defined(BINARY_SUPPORT_DYLD)
 
 __private_extern__ __CFPBinaryType _CFBundleGrokBinaryType(CFURLRef executableURL) {
-    // Attempt to grok the type of the binary by looking for DYLD magic numbers.  If one of the DYLD magic numbers is found, find out what type of Mach-o file it is.  Otherwise, look for the PEF magic numbers to see if it is CFM (if we understand CFM).
+    // Attempt to grok the type of the binary by looking for DYLD magic numbers.  If one of the DYLD magic numbers is found, find out what type of Mach-o file it is.  Otherwise, look for the PEF magic numbers to see if it is CFM.
     __CFPBinaryType result = executableURL ? __CFBundleUnreadableBinary : __CFBundleNoBinary;
     UInt32 machtype = UNKNOWN_FILETYPE;
     if (_CFBundleGrokFileType(executableURL, NULL, NULL, &machtype, NULL, NULL, NULL, NULL, NULL)) {
@@ -2472,11 +3065,9 @@ __private_extern__ __CFPBinaryType _CFBundleGrokBinaryType(CFURLRef executableUR
             case MH_DYLIB:
                 result = __CFBundleDYLDFrameworkBinary;
                 break;
-#if defined(BINARY_SUPPORT_CFM)
             case PEF_FILETYPE:
                 result = __CFBundleCFMBinary;
                 break;
-#endif /* BINARY_SUPPORT_CFM */
         }
     }
     return result;
@@ -2486,9 +3077,7 @@ __private_extern__ __CFPBinaryType _CFBundleGrokBinaryType(CFURLRef executableUR
 
 void _CFBundleSetCFMConnectionID(CFBundleRef bundle, void *connectionID) {
 #if defined(BINARY_SUPPORT_CFM)
-    if (bundle->_binaryType == __CFBundleUnknownBinary || bundle->_binaryType == __CFBundleUnreadableBinary) {
-        bundle->_binaryType = __CFBundleCFMBinary;
-    }
+    if (bundle->_binaryType == __CFBundleUnknownBinary || bundle->_binaryType == __CFBundleUnreadableBinary) bundle->_binaryType = __CFBundleCFMBinary;
 #endif /* BINARY_SUPPORT_CFM */
     bundle->_connectionCookie = connectionID;
     bundle->_isLoaded = true;
@@ -2519,28 +3108,28 @@ static CFErrorRef _CFBundleCreateErrorDebug(CFAllocatorRef allocator, CFBundleRe
         CFStringRef name = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleNameKey);
         name = name ? (CFStringRef)CFRetain(name) : _CFBundleCopyLastPathComponent(bundle);
         if (CFBundleExecutableNotFoundError == code) {
-            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because its executable could not be located."), "NSFileNoSuchFileError");
-            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable could not be located."), "NSFileNoSuchFileError");
+            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable couldn\\U2019t be located."), "NSFileNoSuchFileError");
+            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable couldn\\U2019t be located."), "NSFileNoSuchFileError");
             suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSFileNoSuchFileError");
         } else if (CFBundleExecutableNotLoadableError == code) {
-            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because its executable is not loadable."), "NSExecutableNotLoadableError");
-            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable is not loadable."), "NSExecutableNotLoadableError");
+            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable isn\\U2019t loadable."), "NSExecutableNotLoadableError");
+            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable isn\\U2019t loadable."), "NSExecutableNotLoadableError");
             suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableNotLoadableError");
         } else if (CFBundleExecutableArchitectureMismatchError == code) {
-            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because it does not contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
-            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-C"), CFSTR("Error"), bdl, CFSTR("The bundle does not contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
+            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
+            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-C"), CFSTR("Error"), bdl, CFSTR("The bundle doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
             suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-R"), CFSTR("Error"), bdl, CFSTR("Try installing a universal version of the bundle."), "NSExecutableArchitectureMismatchError");
         } else if (CFBundleExecutableRuntimeMismatchError == code) {
-            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because it is not compatible with the current application."), "NSExecutableRuntimeMismatchError");
-            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-C"), CFSTR("Error"), bdl, CFSTR("The bundle is not compatible with this application."), "NSExecutableRuntimeMismatchError");
+            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it isn\\U2019t compatible with the current application."), "NSExecutableRuntimeMismatchError");
+            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-C"), CFSTR("Error"), bdl, CFSTR("The bundle isn\\U2019t compatible with this application."), "NSExecutableRuntimeMismatchError");
             suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-R"), CFSTR("Error"), bdl, CFSTR("Try installing a newer version of the bundle."), "NSExecutableRuntimeMismatchError");
         } else if (CFBundleExecutableLoadError == code) {
-            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because it is damaged or missing necessary resources."), "NSExecutableLoadError");
+            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it is damaged or missing necessary resources."), "NSExecutableLoadError");
             reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-C"), CFSTR("Error"), bdl, CFSTR("The bundle is damaged or missing necessary resources."), "NSExecutableLoadError");
             suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableLoadError");
         } else if (CFBundleExecutableLinkError == code) {
-            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d could not be loaded."), "NSExecutableLinkError");
-            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-C"), CFSTR("Error"), bdl, CFSTR("The bundle could not be loaded."), "NSExecutableLinkError");
+            descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded."), "NSExecutableLinkError");
+            reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-C"), CFSTR("Error"), bdl, CFSTR("The bundle couldn\\U2019t be loaded."), "NSExecutableLinkError");
             suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableLinkError");
         }
         if (descFormat) {
@@ -2600,34 +3189,57 @@ Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceG
     CFErrorRef localError = NULL, *subError = (error ? &localError : NULL);
     CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
 
+    __CFSpinLock(&(bundle->_bundleLoadingLock));
     if (!executableURL) bundle->_binaryType = __CFBundleNoBinary;
     // make sure we know whether bundle is already loaded or not
 #if defined(BINARY_SUPPORT_DLFCN)
-    if (!bundle->_isLoaded && _useDlfcn) _CFBundleDlfcnCheckLoaded(bundle);
+    if (!bundle->_isLoaded) _CFBundleDlfcnCheckLoaded(bundle);
+#elif defined(BINARY_SUPPORT_DYLD)
+    if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
 #endif /* BINARY_SUPPORT_DLFCN */
 #if defined(BINARY_SUPPORT_DYLD)
-    if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
     // We might need to figure out what it is
     if (bundle->_binaryType == __CFBundleUnknownBinary) {
         bundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
-#if defined(BINARY_SUPPORT_CFM)
         if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
-#endif /* BINARY_SUPPORT_CFM */
     }
 #endif /* BINARY_SUPPORT_DYLD */
     if (executableURL) CFRelease(executableURL);
     
     if (bundle->_isLoaded) {
+        __CFSpinUnlock(&(bundle->_bundleLoadingLock));
         // Remove from the scheduled unload set if we are there.
         __CFSpinLock(&CFBundleGlobalDataLock);
+#if defined(AVOID_WEAK_COLLECTIONS)
         if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
+#else /* AVOID_WEAK_COLLECTIONS */
+        if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
+#endif /* AVOID_WEAK_COLLECTIONS */
         __CFSpinUnlock(&CFBundleGlobalDataLock);
         return true;
     }
 
     // Unload bundles scheduled for unloading
-    if (!_scheduledBundlesAreUnloading) _CFBundleUnloadScheduledBundles();
+    if (!_scheduledBundlesAreUnloading) {
+        __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+        _CFBundleUnloadScheduledBundles();
+        __CFSpinLock(&(bundle->_bundleLoadingLock));
+    }
     
+    if (bundle->_isLoaded) {
+        __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+        // Remove from the scheduled unload set if we are there.
+        __CFSpinLock(&CFBundleGlobalDataLock);
+#if defined(AVOID_WEAK_COLLECTIONS)
+        if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
+#else /* AVOID_WEAK_COLLECTIONS */
+        if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
+#endif /* AVOID_WEAK_COLLECTIONS */
+        __CFSpinUnlock(&CFBundleGlobalDataLock);
+        return true;
+    }
+    __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+
     switch (bundle->_binaryType) {
 #if defined(BINARY_SUPPORT_CFM)
         case __CFBundleCFMBinary:
@@ -2642,19 +3254,24 @@ Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceG
 #if defined(BINARY_SUPPORT_DYLD)
         case __CFBundleDYLDBundleBinary:
 #if defined(BINARY_SUPPORT_DLFCN)
-            if (_useDlfcn) result = _CFBundleDlfcnLoadBundle(bundle, forceGlobal, subError); else
-#endif /* BINARY_SUPPORT_DLFCN */
+            result = _CFBundleDlfcnLoadBundle(bundle, forceGlobal, subError);
+#else /* BINARY_SUPPORT_DLFCN */
             result = _CFBundleDYLDLoadBundle(bundle, forceGlobal, subError);
+#endif /* BINARY_SUPPORT_DLFCN */
             break;
         case __CFBundleDYLDFrameworkBinary:
 #if defined(BINARY_SUPPORT_DLFCN)
-            if (_useDlfcn) result = _CFBundleDlfcnLoadFramework(bundle, subError); else
-#endif /* BINARY_SUPPORT_DLFCN */
+            result = _CFBundleDlfcnLoadFramework(bundle, subError);
+#else /* BINARY_SUPPORT_DLFCN */
             result = _CFBundleDYLDLoadFramework(bundle, subError);
+#endif /* BINARY_SUPPORT_DLFCN */
             break;
         case __CFBundleDYLDExecutableBinary:
-            CFLog(__kCFLogBundle, CFSTR("Attempt to load executable of a type that cannot be dynamically loaded for %@"), bundle);
-            if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
+            if (error) {
+                localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
+            } else {
+                CFLog(__kCFLogBundle, CFSTR("Attempt to load executable of a type that cannot be dynamically loaded for %@"), bundle);
+            }
             break;
 #endif /* BINARY_SUPPORT_DYLD */
 #if defined(BINARY_SUPPORT_DLFCN)
@@ -2669,16 +3286,21 @@ Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceG
             break;
 #endif /* BINARY_SUPPORT_DLL */
         case __CFBundleNoBinary:
-            CFLog(__kCFLogBundle, CFSTR("Cannot find executable for %@"), bundle);
-            if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            if (error) {
+                localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            } else {
+                CFLog(__kCFLogBundle, CFSTR("Cannot find executable for %@"), bundle);
+            }
             break;     
         default:
-            CFLog(__kCFLogBundle, CFSTR("Cannot recognize type of executable for %@"), bundle);
-            if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
+            if (error) {
+                localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
+            } else {
+                CFLog(__kCFLogBundle, CFSTR("Cannot recognize type of executable for %@"), bundle);
+            }
             break;
     }
     if (result && bundle->_plugInData._isPlugIn) _CFBundlePlugInLoaded(bundle);
-
     if (!result && error) *error = localError;
     return result;
 }
@@ -2693,27 +3315,34 @@ Boolean CFBundleLoadExecutable(CFBundleRef bundle) {
 
 Boolean CFBundlePreflightExecutable(CFBundleRef bundle, CFErrorRef *error) {
     Boolean result = false;
-    CFErrorRef localError = NULL, *subError = (error ? &localError : NULL);
+    CFErrorRef localError = NULL;
+#if defined(BINARY_SUPPORT_DLFCN)
+    CFErrorRef *subError = (error ? &localError : NULL);
+#endif
     CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
 
+    __CFSpinLock(&(bundle->_bundleLoadingLock));
     if (!executableURL) bundle->_binaryType = __CFBundleNoBinary;
     // make sure we know whether bundle is already loaded or not
 #if defined(BINARY_SUPPORT_DLFCN)
-    if (!bundle->_isLoaded && _useDlfcn) _CFBundleDlfcnCheckLoaded(bundle);
+    if (!bundle->_isLoaded) _CFBundleDlfcnCheckLoaded(bundle);
+#elif defined(BINARY_SUPPORT_DYLD)
+    if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
 #endif /* BINARY_SUPPORT_DLFCN */
 #if defined(BINARY_SUPPORT_DYLD)
-    if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
     // We might need to figure out what it is
     if (bundle->_binaryType == __CFBundleUnknownBinary) {
         bundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
-#if defined(BINARY_SUPPORT_CFM)
         if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
-#endif /* BINARY_SUPPORT_CFM */
     }
 #endif /* BINARY_SUPPORT_DYLD */
     if (executableURL) CFRelease(executableURL);
     
-    if (bundle->_isLoaded) return true;
+    if (bundle->_isLoaded) {
+        __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+        return true;
+    }
+    __CFSpinUnlock(&(bundle->_bundleLoadingLock));
     
     switch (bundle->_binaryType) {
 #if defined(BINARY_SUPPORT_CFM)
@@ -2775,6 +3404,7 @@ CFArrayRef CFBundleCopyExecutableArchitectures(CFBundleRef bundle) {
     return result;
 }
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static Boolean _CFBundleGetObjCImageInfo(CFBundleRef bundle, uint32_t *objcVersion, uint32_t *objcFlags) {
     Boolean retval = false;
     uint32_t localVersion = 0, localFlags = 0;
@@ -2787,6 +3417,7 @@ static Boolean _CFBundleGetObjCImageInfo(CFBundleRef bundle, uint32_t *objcVersi
     if (objcFlags) *objcFlags = localFlags;
     return retval;
 }
+#endif
 
 void CFBundleUnloadExecutable(CFBundleRef bundle) {
     // First unload bundles scheduled for unloading (if that's not what we are already doing.)
@@ -2796,12 +3427,23 @@ void CFBundleUnloadExecutable(CFBundleRef bundle) {
     
     // Remove from the scheduled unload set if we are there.
     if (!_scheduledBundlesAreUnloading) __CFSpinLock(&CFBundleGlobalDataLock);
+#if defined(AVOID_WEAK_COLLECTIONS)
     if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
+#else /* AVOID_WEAK_COLLECTIONS */
+    if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
+#endif /* AVOID_WEAK_COLLECTIONS */
     if (!_scheduledBundlesAreUnloading) __CFSpinUnlock(&CFBundleGlobalDataLock);
     
     // Give the plugIn code a chance to realize this...
     _CFPlugInWillUnload(bundle);
 
+    __CFSpinLock(&(bundle->_bundleLoadingLock));
+    if (!bundle->_isLoaded) {
+        __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+        return;
+    }
+    __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+
     switch (bundle->_binaryType) {
 #if defined(BINARY_SUPPORT_CFM)
         case __CFBundleCFMBinary:
@@ -2811,9 +3453,10 @@ void CFBundleUnloadExecutable(CFBundleRef bundle) {
 #if defined(BINARY_SUPPORT_DYLD)
         case __CFBundleDYLDBundleBinary:
 #if defined(BINARY_SUPPORT_DLFCN)
-            if (bundle->_handleCookie) _CFBundleDlfcnUnload(bundle); else
-#endif /* BINARY_SUPPORT_DLFCN */
+            if (bundle->_handleCookie) _CFBundleDlfcnUnload(bundle);
+#else /* BINARY_SUPPORT_DLFCN */
             _CFBundleDYLDUnloadBundle(bundle);
+#endif /* BINARY_SUPPORT_DLFCN */
             break;
         case __CFBundleDYLDFrameworkBinary:
 #if defined(BINARY_SUPPORT_DLFCN)
@@ -2839,6 +3482,8 @@ void CFBundleUnloadExecutable(CFBundleRef bundle) {
     }
 }
 
+#if defined(AVOID_WEAK_COLLECTIONS)
+
 __private_extern__ void _CFBundleScheduleForUnloading(CFBundleRef bundle) {
     __CFSpinLock(&CFBundleGlobalDataLock);
     if (!_bundlesToUnload) {
@@ -2854,18 +3499,15 @@ __private_extern__ void _CFBundleScheduleForUnloading(CFBundleRef bundle) {
 
 __private_extern__ void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) {
     __CFSpinLock(&CFBundleGlobalDataLock);
-    if (_bundlesToUnload) {
-        CFSetRemoveValue(_bundlesToUnload, bundle);
-    }
+    if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
     __CFSpinUnlock(&CFBundleGlobalDataLock);
 }
 
 __private_extern__ void _CFBundleUnloadScheduledBundles(void) {
     __CFSpinLock(&CFBundleGlobalDataLock);
     if (_bundlesToUnload) {
-        CFIndex c = CFSetGetCount(_bundlesToUnload);
+        CFIndex i, c = CFSetGetCount(_bundlesToUnload);
         if (c > 0) {
-            CFIndex i;
             CFBundleRef *unloadThese = (CFBundleRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(CFBundleRef) * c, 0);
             CFSetGetValues(_bundlesToUnload, (const void **)unloadThese);
             _scheduledBundlesAreUnloading = true;
@@ -2880,6 +3522,43 @@ __private_extern__ void _CFBundleUnloadScheduledBundles(void) {
     __CFSpinUnlock(&CFBundleGlobalDataLock);
 }
 
+#else /* AVOID_WEAK_COLLECTIONS */
+
+__private_extern__ void _CFBundleScheduleForUnloading(CFBundleRef bundle) {
+    __CFSpinLock(&CFBundleGlobalDataLock);
+    if (!_bundlesToUnload) _bundlesToUnload = [[__CFHashTable alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory capacity:0];
+    [_bundlesToUnload addObject:(id)bundle];
+    __CFSpinUnlock(&CFBundleGlobalDataLock);
+}
+
+__private_extern__ void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) {
+    __CFSpinLock(&CFBundleGlobalDataLock);
+    if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
+    __CFSpinUnlock(&CFBundleGlobalDataLock);
+}
+
+__private_extern__ void _CFBundleUnloadScheduledBundles(void) {
+    __CFSpinLock(&CFBundleGlobalDataLock);
+    if (_bundlesToUnload && [_bundlesToUnload count] > 0) {
+        CFIndex i, c;
+        CFMutableArrayRef unloadThese = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+        for (id value in _bundlesToUnload) CFArrayAppendValue(unloadThese, value);
+        c = CFArrayGetCount(unloadThese);
+        if (c > 0) {
+            _scheduledBundlesAreUnloading = true;
+            for (i = 0; i < c; i++) {
+                // This will cause them to be removed from the set.  (Which is why we copied all the values out of the set up front.)
+                CFBundleUnloadExecutable((CFBundleRef)CFArrayGetValueAtIndex(unloadThese, i));
+            }
+            _scheduledBundlesAreUnloading = false;
+        }
+        CFRelease(unloadThese);
+    }
+    __CFSpinUnlock(&CFBundleGlobalDataLock);
+}
+
+#endif /* AVOID_WEAK_COLLECTIONS */
+
 void *CFBundleGetFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName) {
     void *tvp = NULL;
     // Load if necessary
@@ -2899,8 +3578,9 @@ void *CFBundleGetFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName
         case __CFBundleDYLDExecutableBinary:
 #if defined(BINARY_SUPPORT_DLFCN)
             if (bundle->_handleCookie) return _CFBundleDlfcnGetSymbolByName(bundle, funcName);
-#endif /* BINARY_SUPPORT_DLFCN */
+#else /* BINARY_SUPPORT_DLFCN */
             return _CFBundleDYLDGetSymbolByName(bundle, funcName);
+#endif /* BINARY_SUPPORT_DLFCN */
             break;
 #endif /* BINARY_SUPPORT_DYLD */
 #if defined(BINARY_SUPPORT_DLL)
@@ -2946,9 +3626,10 @@ void *_CFBundleGetCFMFunctionPointerForName(CFBundleRef bundle, CFStringRef func
         case __CFBundleDYLDFrameworkBinary:
         case __CFBundleDYLDExecutableBinary:
 #if defined(BINARY_SUPPORT_DLFCN)
-            if (bundle->_handleCookie) fp = _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, funcName, true); else
-#endif /* BINARY_SUPPORT_DLFCN */
+            if (bundle->_handleCookie) fp = _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, funcName, true);
+#else /* BINARY_SUPPORT_DLFCN */
             fp = _CFBundleDYLDGetSymbolByNameWithSearch(bundle, funcName, true);
+#endif /* BINARY_SUPPORT_DLFCN */
             break;
 #endif /* BINARY_SUPPORT_DYLD */
         default:
@@ -2978,9 +3659,7 @@ void CFBundleGetFunctionPointersForNames(CFBundleRef bundle, CFArrayRef function
     if (!ftbl) return;
 
     c = CFArrayGetCount(functionNames);
-    for (i = 0; i < c; i++) {
-        ftbl[i] = CFBundleGetFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i));
-    }
+    for (i = 0; i < c; i++) ftbl[i] = CFBundleGetFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i));
 }
 
 void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle, CFArrayRef functionNames, void *ftbl[]) {
@@ -2989,17 +3668,13 @@ void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle, CFArrayRef func
     if (!ftbl) return;
 
     c = CFArrayGetCount(functionNames);
-    for (i = 0; i < c; i++) {
-        ftbl[i] = _CFBundleGetCFMFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i));
-    }
+    for (i = 0; i < c; i++) ftbl[i] = _CFBundleGetCFMFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i));
 }
 
 void *CFBundleGetDataPointerForName(CFBundleRef bundle, CFStringRef symbolName) {
     void *dp = NULL;
     // Load if necessary
-    if (!bundle->_isLoaded) {
-        if (!CFBundleLoadExecutable(bundle)) return NULL;
-    }
+    if (!bundle->_isLoaded && !CFBundleLoadExecutable(bundle)) return NULL;
     
     switch (bundle->_binaryType) {
 #if defined(BINARY_SUPPORT_CFM)
@@ -3012,9 +3687,10 @@ void *CFBundleGetDataPointerForName(CFBundleRef bundle, CFStringRef symbolName)
         case __CFBundleDYLDFrameworkBinary:
         case __CFBundleDYLDExecutableBinary:
 #if defined(BINARY_SUPPORT_DLFCN)
-            if (bundle->_handleCookie) dp = _CFBundleDlfcnGetSymbolByName(bundle, symbolName); else
-#endif /* BINARY_SUPPORT_DLFCN */
+            if (bundle->_handleCookie) dp = _CFBundleDlfcnGetSymbolByName(bundle, symbolName);
+#else /* BINARY_SUPPORT_DLFCN */
             dp = _CFBundleDYLDGetSymbolByName(bundle, symbolName);
+#endif /* BINARY_SUPPORT_DLFCN */
             break;
 #endif /* BINARY_SUPPORT_DYLD */
 #if defined(BINARY_SUPPORT_DLL)
@@ -3037,9 +3713,7 @@ void CFBundleGetDataPointersForNames(CFBundleRef bundle, CFArrayRef symbolNames,
     if (!stbl) return;
 
     c = CFArrayGetCount(symbolNames);
-    for (i = 0; i < c; i++) {
-        stbl[i] = CFBundleGetDataPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(symbolNames, i));
-    }
+    for (i = 0; i < c; i++) stbl[i] = CFBundleGetDataPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(symbolNames, i));
 }
 
 __private_extern__ _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle) {
@@ -3047,11 +3721,7 @@ __private_extern__ _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle
 }
 
 CFPlugInRef CFBundleGetPlugIn(CFBundleRef bundle) {
-    if (bundle->_plugInData._isPlugIn) {
-        return (CFPlugInRef)bundle;
-    } else {
-        return NULL;
-    }
+    return (bundle->_plugInData._isPlugIn) ? (CFPlugInRef)bundle : NULL;
 }
 
 __private_extern__ _CFPlugInData *__CFBundleGetPlugInData(CFBundleRef bundle) {
@@ -3062,10 +3732,7 @@ __private_extern__ Boolean _CFBundleCouldBeBundle(CFURLRef url) {
     Boolean result = false;
     Boolean exists;
     SInt32 mode;
-
-    if (_CFGetFileProperties(kCFAllocatorSystemDefault, url, &exists, &mode, NULL, NULL, NULL, NULL) == 0) {
-        result = (exists && ((mode & S_IFMT) == S_IFDIR) && ((mode & 0444) != 0));
-    }
+    if (_CFGetFileProperties(kCFAllocatorSystemDefault, url, &exists, &mode, NULL, NULL, NULL, NULL) == 0) result = (exists && (mode & S_IFMT) == S_IFDIR && (mode & 0444) != 0);
     return result;
 }
 
@@ -3073,6 +3740,20 @@ __private_extern__ Boolean _CFBundleCouldBeBundle(CFURLRef url) {
 
 __private_extern__ CFURLRef _CFBundleCopyFrameworkURLForExecutablePath(CFAllocatorRef alloc, CFStringRef executablePath) {
     // MF:!!! Implement me.  We need to be able to find the bundle from the exe, dealing with old vs. new as well as the Executables dir business on Windows.
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif 0 && DEPLOYMENT_TARGET_WINDOWS_SYNC
+    UniChar executablesToFrameworksPathBuff[] = {'.', '.', '\\', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
+    UniChar executablesToPrivateFrameworksPathBuff[] = {'.', '.', '\\', 'P', 'r', 'i', 'v', 'a', 't', 'e', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
+    UniChar executablesToSystemFrameworksPathBuff[MAX_PATH+1] = { 0 };
+    SHGetFolderPathAndSubDirW(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0 /* SHGFP_TYPE_CURRENT */, L"Apple\\Mobile Device Support\\Frameworks", executablesToSystemFrameworksPathBuff);
+    UniChar frameworksExtension[] = {'f', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k'};
+#elif DEPLOYMENT_TARGET_WINDOWS
+    UniChar executablesToFrameworksPathBuff[] = {'.', '.', '\\', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
+    UniChar executablesToPrivateFrameworksPathBuff[] = {'.', '.', '\\', 'P', 'r', 'i', 'v', 'a', 't', 'e', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
+    UniChar frameworksExtension[] = {'f', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k'};
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
     UniChar pathBuff[CFMaxPathSize];
     UniChar nameBuff[CFMaxPathSize];
     CFIndex length, nameStart, nameLength, savedLength;
@@ -3093,6 +3774,67 @@ __private_extern__ CFURLRef _CFBundleCopyFrameworkURLForExecutablePath(CFAllocat
     length = _CFLengthAfterDeletingLastPathComponent(pathBuff, length);
     savedLength = length;
 
+#if DEPLOYMENT_TARGET_WINDOWS
+    // * (Windows-only) First check the "Executables" directory parallel to the "Frameworks" directory case.
+    if (_CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, executablesToFrameworksPathBuff, LENGTH_OF(executablesToFrameworksPathBuff)) && _CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, nameBuff, nameLength) && _CFAppendPathExtension(pathBuff, &length, CFMaxPathSize, frameworksExtension, LENGTH_OF(frameworksExtension))) {
+        CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
+        bundleURL = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, true);
+        if (!_CFBundleCouldBeBundle(bundleURL)) {
+            CFRelease(bundleURL);
+            bundleURL = NULL;
+        }
+    }
+    // * (Windows-only) Next check the "Executables" directory parallel to the "PrivateFrameworks" directory case.
+    if (!bundleURL) {
+        length = savedLength;
+        if (_CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, executablesToPrivateFrameworksPathBuff, LENGTH_OF(executablesToPrivateFrameworksPathBuff)) && _CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, nameBuff, nameLength) && _CFAppendPathExtension(pathBuff, &length, CFMaxPathSize, frameworksExtension, LENGTH_OF(frameworksExtension))) {
+            CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
+            bundleURL = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, true);
+            if (!_CFBundleCouldBeBundle(bundleURL)) {
+                CFRelease(bundleURL);
+                bundleURL = NULL;
+            }
+        }
+    }
+            
+#elif 0 && DEPLOYMENT_TARGET_WINDOWS_SYNC
+    // * (Windows-only) First check the "Executables" directory parallel to the "Frameworks" directory case.
+    if (_CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, executablesToFrameworksPathBuff, LENGTH_OF(executablesToFrameworksPathBuff)) && _CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, nameBuff, nameLength) && _CFAppendPathExtension(pathBuff, &length, CFMaxPathSize, frameworksExtension, LENGTH_OF(frameworksExtension))) {
+        CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
+        bundleURL = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, true);
+        if (!_CFBundleCouldBeBundle(bundleURL)) {
+            CFRelease(bundleURL);
+            bundleURL = NULL;
+        }
+    }
+    // * (Windows-only) Next check the "Executables" directory parallel to the "PrivateFrameworks" directory case.
+    if (!bundleURL) {
+        length = savedLength;
+        if (_CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, executablesToPrivateFrameworksPathBuff, LENGTH_OF(executablesToPrivateFrameworksPathBuff)) && _CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, nameBuff, nameLength) && _CFAppendPathExtension(pathBuff, &length, CFMaxPathSize, frameworksExtension, LENGTH_OF(frameworksExtension))) {
+            CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
+            bundleURL = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, true);
+            if (!_CFBundleCouldBeBundle(bundleURL)) {
+                CFRelease(bundleURL);
+                bundleURL = NULL;
+            }
+        }
+    }
+    // * (Windows-only) Next check the \Program Files\Apple\Mobile Device Support\Frameworks directory
+    if (!bundleURL) {
+        length = 0;
+        if (_CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, executablesToSystemFrameworksPathBuff, wcslen(executablesToSystemFrameworksPathBuff)) && _CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, nameBuff, nameLength) && _CFAppendPathExtension(pathBuff, &length, CFMaxPathSize, frameworksExtension, LENGTH_OF(frameworksExtension))) {
+            CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
+            bundleURL = CFURLCreateWithFileSystemPath(alloc, cheapStr, PLATFORM_PATH_STYLE, true);
+            if (!_CFBundleCouldBeBundle(bundleURL)) {
+                CFRelease(bundleURL);
+                bundleURL = NULL;
+            }
+        }
+    }
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
     // * Finally check the executable inside the framework case.
     if (!bundleURL) {
         // MF:!!! This should ensure the framework name is the same as the library name!
@@ -3103,9 +3845,7 @@ __private_extern__ CFURLRef _CFBundleCopyFrameworkURLForExecutablePath(CFAllocat
 
         while (length > 0) {
             curStart = _CFStartOfLastPathComponent(pathBuff, length);
-            if (curStart >= length) {
-                break;
-            }
+            if (curStart >= length) break;
             CFStringSetExternalCharactersNoCopy(cheapStr, &(pathBuff[curStart]), length - curStart, CFMaxPathSize - curStart);
             if (CFEqual(cheapStr, _CFBundleSupportFilesDirectoryName1) || CFEqual(cheapStr, _CFBundleSupportFilesDirectoryName2)) {
                 length = _CFLengthAfterDeletingLastPathComponent(pathBuff, length);
@@ -3128,10 +3868,8 @@ __private_extern__ CFURLRef _CFBundleCopyFrameworkURLForExecutablePath(CFAllocat
             length = _CFLengthAfterDeletingLastPathComponent(pathBuff, length);
         }
     }
-
     CFStringSetExternalCharactersNoCopy(cheapStr, NULL, 0, 0);
     CFRelease(cheapStr);
-
     return bundleURL;
 }
 
@@ -3140,37 +3878,47 @@ static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath) {
     // If an image path corresponds to a bundle, we see if there is already a bundle instance.  If there is and it is NOT in the _dynamicBundles array, it is added to the staticBundles.  Do not add the main bundle to the list here.
     CFBundleRef bundle;
     CFURLRef curURL = _CFBundleCopyFrameworkURLForExecutablePath(kCFAllocatorSystemDefault, imagePath);
-    Boolean doFinalProcessing = false;
+    Boolean createdBundle = false;
 
     if (curURL) {
-        bundle = _CFBundleFindByURL(curURL, true);
+        bundle = _CFBundleCopyBundleForURL(curURL, true);
         if (!bundle) {
+            // Ensure bundle exists by creating it if necessary
+            // NB doFinalProcessing must be false here, see below
             bundle = _CFBundleCreate(kCFAllocatorSystemDefault, curURL, true, false);
-            doFinalProcessing = true;
-        }
-        if (bundle && !bundle->_isLoaded) {
-            // make sure that these bundles listed as loaded, and mark them frameworks (we probably can't see anything else here, and we cannot unload them)
-#if defined(BINARY_SUPPORT_DLFCN)
-            if (!bundle->_isLoaded && _useDlfcn) _CFBundleDlfcnCheckLoaded(bundle);
-#endif /* BINARY_SUPPORT_DLFCN */
-#if defined(BINARY_SUPPORT_DYLD)
-            if (bundle->_binaryType == __CFBundleUnknownBinary) bundle->_binaryType = __CFBundleDYLDFrameworkBinary;
-            if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
-            if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
-#endif /* BINARY_SUPPORT_DYLD */
-#if LOG_BUNDLE_LOAD
-            if (!bundle->_isLoaded) printf("ensure bundle %p set loaded fallback, handle %p image %p conn %p\n", bundle, bundle->_handleCookie, bundle->_imageCookie, bundle->_connectionCookie);
-#endif /* LOG_BUNDLE_LOAD */
-            bundle->_isLoaded = true;
+            createdBundle = true;
         }
-        // Perform delayed final processing steps.
-        // This must be done after _isLoaded has been set.
-        if (bundle && doFinalProcessing) {
-            _CFBundleCheckWorkarounds(bundle);
-            if (_CFBundleNeedsInitPlugIn(bundle)) {
-                __CFSpinUnlock(&CFBundleGlobalDataLock);
-                _CFBundleInitPlugIn(bundle);
-                __CFSpinLock(&CFBundleGlobalDataLock);
+        if (bundle) {
+            __CFSpinLock(&(bundle->_bundleLoadingLock));
+            if (!bundle->_isLoaded) {
+                // make sure that these bundles listed as loaded, and mark them frameworks (we probably can't see anything else here, and we cannot unload them)
+    #if defined(BINARY_SUPPORT_DLFCN)
+                if (!bundle->_isLoaded) _CFBundleDlfcnCheckLoaded(bundle);
+    #elif defined(BINARY_SUPPORT_DYLD)
+                if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
+    #endif /* BINARY_SUPPORT_DLFCN */
+    #if defined(BINARY_SUPPORT_DYLD)
+                if (bundle->_binaryType == __CFBundleUnknownBinary) bundle->_binaryType = __CFBundleDYLDFrameworkBinary;
+                if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
+    #endif /* BINARY_SUPPORT_DYLD */
+    #if LOG_BUNDLE_LOAD
+                if (!bundle->_isLoaded) printf("ensure bundle %p set loaded fallback, handle %p image %p conn %p\n", bundle, bundle->_handleCookie, bundle->_imageCookie, bundle->_connectionCookie);
+    #endif /* LOG_BUNDLE_LOAD */
+                bundle->_isLoaded = true;
+            }
+            __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+            if (createdBundle) {
+                // Perform delayed final processing steps.
+                // This must be done after _isLoaded has been set, for security reasons (3624341).
+                _CFBundleCheckWorkarounds(bundle);
+                if (_CFBundleNeedsInitPlugIn(bundle)) {
+                    __CFSpinUnlock(&CFBundleGlobalDataLock);
+                    _CFBundleInitPlugIn(bundle);
+                    __CFSpinLock(&CFBundleGlobalDataLock);
+                }
+            } else {
+                // Release the bundle if we did not create it here
+                CFRelease(bundle);
             }
         }
         CFRelease(curURL);
@@ -3181,10 +3929,7 @@ static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths) {
     // This finds the bundles for the given paths.
     // If an image path corresponds to a bundle, we see if there is already a bundle instance.  If there is and it is NOT in the _dynamicBundles array, it is added to the staticBundles.  Do not add the main bundle to the list here (even if it appears in imagePaths).
     CFIndex i, imagePathCount = CFArrayGetCount(imagePaths);
-
-    for (i = 0; i < imagePathCount; i++) {
-        _CFBundleEnsureBundleExistsForImagePath((CFStringRef)CFArrayGetValueAtIndex(imagePaths, i));
-    }
+    for (i = 0; i < imagePathCount; i++) _CFBundleEnsureBundleExistsForImagePath((CFStringRef)CFArrayGetValueAtIndex(imagePaths, i));
 }
 
 static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint) {
@@ -3203,7 +3948,6 @@ static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint
 static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void) {
     // This method returns all the statically linked bundles.  This includes the main bundle as well as any frameworks that the process was linked against at launch time.  It does not include frameworks or opther bundles that were loaded dynamically.
     CFArrayRef imagePaths = NULL;
-
     // Tickle the main bundle into existence
     (void)_CFBundleGetMainBundleAlreadyLocked();
 
@@ -3226,13 +3970,32 @@ static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void) {
 
 CFArrayRef CFBundleGetAllBundles(void) {
     // To answer this properly, we have to have created the static bundles!
+#if !defined(AVOID_WEAK_COLLECTIONS)
+    static CFMutableArrayRef externalAllBundles = NULL;
+#endif /* AVOID_WEAK_COLLECTIONS */
+    CFArrayRef bundles;
     __CFSpinLock(&CFBundleGlobalDataLock);
     _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
+#if defined(AVOID_WEAK_COLLECTIONS)
+    bundles = _allBundles;
+#else /* AVOID_WEAK_COLLECTIONS */
+    if (!externalAllBundles) {
+        CFArrayCallBacks nonRetainingArrayCallbacks = kCFTypeArrayCallBacks;
+        nonRetainingArrayCallbacks.retain = NULL;
+        nonRetainingArrayCallbacks.release = NULL;
+        externalAllBundles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &nonRetainingArrayCallbacks);
+    }
+    CFArrayRemoveAllValues(externalAllBundles);
+    for (id value in _allBundles) CFArrayAppendValue(externalAllBundles, value);
+    bundles = externalAllBundles;
+#endif /* AVOID_WEAK_COLLECTIONS */
     __CFSpinUnlock(&CFBundleGlobalDataLock);
-    return _allBundles;
+    return bundles;
 }
 
-uint8_t _CFBundleLayoutVersion(CFBundleRef bundle) {return bundle->_version;}
+uint8_t _CFBundleLayoutVersion(CFBundleRef bundle) {
+    return bundle->_version;
+}
 
 CF_EXPORT CFURLRef _CFBundleCopyInfoPlistURL(CFBundleRef bundle) {
     CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
@@ -3241,7 +4004,9 @@ CF_EXPORT CFURLRef _CFBundleCopyInfoPlistURL(CFBundleRef bundle) {
     return (url ? (CFURLRef)CFRetain(url) : NULL);
 }
 
-CF_EXPORT CFURLRef _CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle) {return CFBundleCopyPrivateFrameworksURL(bundle);}
+CF_EXPORT CFURLRef _CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle) {
+    return CFBundleCopyPrivateFrameworksURL(bundle);
+}
 
 CF_EXPORT CFURLRef CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle) {
     CFURLRef result = NULL;
@@ -3256,7 +4021,9 @@ CF_EXPORT CFURLRef CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle) {
     return result;
 }
 
-CF_EXPORT CFURLRef _CFBundleCopySharedFrameworksURL(CFBundleRef bundle) {return CFBundleCopySharedFrameworksURL(bundle);}
+CF_EXPORT CFURLRef _CFBundleCopySharedFrameworksURL(CFBundleRef bundle) {
+    return CFBundleCopySharedFrameworksURL(bundle);
+}
 
 CF_EXPORT CFURLRef CFBundleCopySharedFrameworksURL(CFBundleRef bundle) {
     CFURLRef result = NULL;
@@ -3271,7 +4038,9 @@ CF_EXPORT CFURLRef CFBundleCopySharedFrameworksURL(CFBundleRef bundle) {
     return result;
 }
 
-CF_EXPORT CFURLRef _CFBundleCopySharedSupportURL(CFBundleRef bundle) {return CFBundleCopySharedSupportURL(bundle);}
+CF_EXPORT CFURLRef _CFBundleCopySharedSupportURL(CFBundleRef bundle) {
+    return CFBundleCopySharedSupportURL(bundle);
+}
 
 CF_EXPORT CFURLRef CFBundleCopySharedSupportURL(CFBundleRef bundle) {
     CFURLRef result = NULL;
@@ -3286,7 +4055,9 @@ CF_EXPORT CFURLRef CFBundleCopySharedSupportURL(CFBundleRef bundle) {
     return result;
 }
 
-__private_extern__ CFURLRef _CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) {return CFBundleCopyBuiltInPlugInsURL(bundle);}
+__private_extern__ CFURLRef _CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) {
+    return CFBundleCopyBuiltInPlugInsURL(bundle);
+}
 
 CF_EXPORT CFURLRef CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) {
     CFURLRef result = NULL, alternateResult = NULL;
@@ -3321,6 +4092,143 @@ CF_EXPORT CFURLRef CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) {
 
 #if defined(BINARY_SUPPORT_DYLD)
 
+__private_extern__ CFArrayRef _CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint) {
+    uint32_t i, numImages = _dyld_image_count();
+    CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+    CFRange range = CFRangeMake(0, CFStringGetLength(hint)), altRange = CFRangeMake(0, 0), testRange = CFRangeMake(0, 0);
+    const char *processPath = _CFProcessPath();
+    const void *mhp = (const void *)_NSGetMachExecuteHeader();
+    
+    if (range.length > 14) {
+        // handle some common variations on framework bundle identifiers
+        if (CFStringFindWithOptions(hint, CFSTR(".framework"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) {
+            // identifier has .framework appended
+            altRange.length = testRange.location;
+        } else if (CFStringFindWithOptions(hint, CFSTR("framework"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) {
+            // identifier has Framework appended
+            altRange.length = testRange.location;
+        } else if (CFStringFindWithOptions(hint, CFSTR("fw"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) {
+            // identifier has FW appended
+            altRange.length = testRange.location;
+        }
+    }
+    for (i = 0; i < numImages; i++) {
+        const char *curName = _dyld_get_image_name(i), *lastComponent = NULL;
+        if (curName && (!processPath || 0 != strcmp(curName, processPath)) && mhp != (void *)_dyld_get_image_header(i)) lastComponent = strrchr(curName, '/');
+        if (lastComponent) {
+            CFStringRef str = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, lastComponent + 1);
+            if (str) {
+                if (CFStringFindWithOptions(hint, str, range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL) || (altRange.length > 0 && CFStringFindWithOptions(hint, str, altRange, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL))) {
+                    CFStringRef curStr = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, curName);
+                    if (curStr) {
+                        CFArrayAppendValue(result, curStr);
+                        CFRelease(curStr);
+                    }
+                }
+                CFRelease(str);
+            }
+        }
+    }
+    return result;
+}
+
+static char *_cleanedPathForPath(const char *curName) {
+    char *thePath = strdup(curName);
+    if (thePath) {
+        // We are going to process the buffer replacing all "/./" and "//" with "/"
+        CFIndex srcIndex = 0, dstIndex = 0;
+        CFIndex len = strlen(thePath);
+        for (srcIndex=0; srcIndex<len; srcIndex++) {
+            thePath[dstIndex] = thePath[srcIndex];
+            dstIndex++;
+            while (srcIndex < len-1 && thePath[srcIndex] == '/' && (thePath[srcIndex+1] == '/' || (thePath[srcIndex+1] == '.' && srcIndex < len-2 && thePath[srcIndex+2] == '/'))) srcIndex += (thePath[srcIndex+1] == '/' ? 1 : 2);
+        }
+        thePath[dstIndex] = 0;
+    }
+    return thePath;
+}
+
+__private_extern__ CFArrayRef _CFBundleDYLDCopyLoadedImagePathsIfChanged(void) {
+    // This returns an array of the paths of all the dyld images in the process.  These paths may not be absolute, they may point at things that are not bundles, they may be staticly linked bundles or dynamically loaded bundles, they may be NULL.
+    uint32_t i, numImages = _dyld_image_count();
+    CFMutableArrayRef result = NULL;
+    static uint32_t _cachedDYLDImageCount = -1;
+
+    if (numImages != _cachedDYLDImageCount) {
+        const char *curName;
+        char *cleanedCurName = NULL;
+        CFStringRef curStr;
+        const char *processPath = _CFProcessPath();
+        const void *mhp = (const void *)_NSGetMachExecuteHeader();
+
+        result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+
+        for (i = 0; i < numImages; i++) {
+            curName = _dyld_get_image_name(i);
+            if (curName && i == 0) cleanedCurName = _cleanedPathForPath(curName);
+            if (curName && (!processPath || 0 != strcmp(curName, processPath)) && (!processPath || !cleanedCurName || 0 != strcmp(cleanedCurName, processPath)) && mhp != (void *)_dyld_get_image_header(i)) {
+                curStr = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, curName);
+                if (curStr) {
+                    CFArrayAppendValue(result, curStr);
+                    CFRelease(curStr);
+                }
+            }
+            if (cleanedCurName) {
+                free(cleanedCurName);
+                cleanedCurName = NULL;
+            }
+        }
+        _cachedDYLDImageCount = numImages;
+    }
+    return result;
+}
+
+static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p) {
+    CFStringRef result = NULL;
+#if defined(USE_DYLD_PRIV)
+    const char *name = dyld_image_path_containing_address(p);
+    if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name);
+#else /* USE_DYLD_PRIV */
+    if (!result) {
+        uint32_t i, j, n = _dyld_image_count();
+        Boolean foundit = false;
+        const char *name;
+#if __LP64__
+#define MACH_HEADER_TYPE struct mach_header_64
+#define MACH_SEGMENT_CMD_TYPE struct segment_command_64
+#define MACH_SEGMENT_FLAVOR LC_SEGMENT_64
+#else
+#define MACH_HEADER_TYPE struct mach_header
+#define MACH_SEGMENT_CMD_TYPE struct segment_command
+#define MACH_SEGMENT_FLAVOR LC_SEGMENT
+#endif
+        for (i = 0; !foundit && i < n; i++) {
+            const MACH_HEADER_TYPE *mh = (const MACH_HEADER_TYPE *)_dyld_get_image_header(i);
+            uintptr_t addr = (uintptr_t)p - _dyld_get_image_vmaddr_slide(i);
+            if (mh) {
+                struct load_command *lc = (struct load_command *)((char *)mh + sizeof(MACH_HEADER_TYPE));
+                for (j = 0; !foundit && j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) {
+                    if (MACH_SEGMENT_FLAVOR == lc->cmd && ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr <= addr && addr < ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr + ((MACH_SEGMENT_CMD_TYPE *)lc)->vmsize) {
+                        foundit = true;
+                        name = _dyld_get_image_name(i);
+                        if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name);
+                    }
+                }
+            }
+        }
+#undef MACH_HEADER_TYPE
+#undef MACH_SEGMENT_CMD_TYPE
+#undef MACH_SEGMENT_FLAVOR
+    }
+#endif /* USE_DYLD_PRIV */
+#if LOG_BUNDLE_LOAD
+    printf("dyld image path for pointer %p is %p\n", p, result);
+#endif /* LOG_BUNDLE_LOAD */
+    return result;
+}
+
+#if !defined(BINARY_SUPPORT_DLFCN) 
+
 static const void *__CFBundleDYLDFindImage(char *buff) {
     const void *header = NULL;
     uint32_t i, numImages = _dyld_image_count(), numMatches = 0;
@@ -3408,21 +4316,25 @@ __private_extern__ Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean f
                     bundle->_isLoaded = true;
                 } else {
                     NSLinkEditError(&c, &errorNumber, &fileName, &errorString);
-                    CFLog(__kCFLogBundle, CFSTR("Error loading %s:  error code %d, error number %d (%s)"), fileName, c, errorNumber, errorString);
                     if (error) {
 #if defined(BINARY_SUPPORT_DLFCN)
                         _CFBundleDlfcnPreflight(bundle, subError);
 #endif /* BINARY_SUPPORT_DLFCN */
                         if (!localError) {
-                            CFStringRef debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%s)"), c, errorNumber, errorString);
+                            CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString);
                             localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
-                            CFRelease(debugString);
+                            if (tempString) CFRelease(tempString);
+                            if (debugString) CFRelease(debugString);
                         }
+                    } else {
+                        CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName);
+                        CFLog(__kCFLogBundle, CFSTR("Error loading %@:  error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString);
+                        if (tempString) CFRelease(tempString);
+                        if (executableString) CFRelease(executableString);
                     }
                     (void)NSDestroyObjectFileImage(image);
                 }
             } else {
-                CFLog(__kCFLogBundle, CFSTR("dyld returns %d when trying to load %@"), retCode, executableURL);
                 if (error) {
                     if (retCode == NSObjectFileImageArch) {
                         localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableArchitectureMismatchError);
@@ -3447,11 +4359,16 @@ __private_extern__ Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean f
                             CFRelease(debugString);
                         }
                     }
+                } else {
+                    CFLog(__kCFLogBundle, CFSTR("dyld returns %d when trying to load %@"), retCode, executableURL);
                 }
             }
         } else {
-            CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
-            if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            if (error) {
+                localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            } else {
+                CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
+            }
         }
         if (executableURL) CFRelease(executableURL);
     }
@@ -3481,21 +4398,29 @@ __private_extern__ Boolean _CFBundleDYLDLoadFramework(CFBundleRef bundle, CFErro
                 bundle->_isLoaded = true;
             } else {
                 NSLinkEditError(&c, &errorNumber, &fileName, &errorString);
-                CFLog(__kCFLogBundle, CFSTR("Error loading %s:  error code %d, error number %d (%s)"), fileName, c, errorNumber, errorString);
                 if (error) {
 #if defined(BINARY_SUPPORT_DLFCN)
                     _CFBundleDlfcnPreflight(bundle, subError);
 #endif /* BINARY_SUPPORT_DLFCN */
                     if (!localError) {
-                        CFStringRef debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%s)"), c, errorNumber, errorString);
+                        CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString);
                         localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
-                        CFRelease(debugString);
+                        if (tempString) CFRelease(tempString);
+                        if (debugString) CFRelease(debugString);
                     }
+                } else {
+                    CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName);
+                    CFLog(__kCFLogBundle, CFSTR("Error loading %@:  error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString);
+                    if (tempString) CFRelease(tempString);
+                    if (executableString) CFRelease(executableString);
                 }
             }
         } else {
-            CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
-            if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            if (error) {
+                localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            } else {
+                CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
+            }
         }
         if (executableURL) CFRelease(executableURL);
     }
@@ -3519,7 +4444,9 @@ __private_extern__ void _CFBundleDYLDUnloadBundle(CFBundleRef bundle) {
     }
 }
 
-__private_extern__ void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) {return _CFBundleDYLDGetSymbolByNameWithSearch(bundle, symbolName, false);}
+__private_extern__ void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) {
+    return _CFBundleDYLDGetSymbolByNameWithSearch(bundle, symbolName, false);
+}
 
 static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch) {
     void *result = NULL;
@@ -3541,15 +4468,15 @@ static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFString
                 if (!CFStringGetCString(executableName, hintBuff, 1024, kCFStringEncodingUTF8)) hintBuff[0] = '\0';
                 CFRelease(executableName);
             }
-           // Nowdays, NSIsSymbolNameDefinedWithHint() and NSLookupAndBindSymbolWithHint()
-           // are identical, except the first just returns a bool, so checking with the
-           // Is function first just causes a redundant lookup.
-           // This returns NULL on failure.
+            // Nowdays, NSIsSymbolNameDefinedWithHint() and NSLookupAndBindSymbolWithHint()
+            // are identical, except the first just returns a bool, so checking with the
+            // Is function first just causes a redundant lookup.
+            // This returns NULL on failure.
             symbol = NSLookupAndBindSymbolWithHint(buff, hintBuff);
         }
         if (symbol) result = NSAddressOfSymbol(symbol);
 #if defined(DEBUG)
-        if (!result) CFLog(__kCFLogBundle, CFSTR("dyld cannot find symbol %s in %@"), buff, bundle);
+        if (!result) CFLog(__kCFLogBundle, CFSTR("dyld cannot find symbol %@ in %@"), symbolName, bundle);
 #endif /* DEBUG */
 #if LOG_BUNDLE_LOAD
         printf("bundle %p handle %p module %p image %p dyld returns symbol %p for %s\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie, result, buff + 1);
@@ -3558,122 +4485,7 @@ static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFString
     return result;
 }
 
-static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p) {
-    CFStringRef result = NULL;
-    if (!result) {
-        uint32_t i, j, n = _dyld_image_count();
-        Boolean foundit = false;
-        const char *name;
-#if __LP64__
-#define MACH_HEADER_TYPE struct mach_header_64
-#define MACH_SEGMENT_CMD_TYPE struct segment_command_64
-#define MACH_SEGMENT_FLAVOR LC_SEGMENT_64
-#else
-#define MACH_HEADER_TYPE struct mach_header
-#define MACH_SEGMENT_CMD_TYPE struct segment_command
-#define MACH_SEGMENT_FLAVOR LC_SEGMENT
-#endif
-        for (i = 0; !foundit && i < n; i++) {
-            const MACH_HEADER_TYPE *mh = (const MACH_HEADER_TYPE *)_dyld_get_image_header(i);
-            uintptr_t addr = (uintptr_t)p - _dyld_get_image_vmaddr_slide(i);
-            if (mh) {
-                struct load_command *lc = (struct load_command *)((char *)mh + sizeof(MACH_HEADER_TYPE));
-                for (j = 0; !foundit && j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) {
-                    if (MACH_SEGMENT_FLAVOR == lc->cmd && ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr <= addr && addr < ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr + ((MACH_SEGMENT_CMD_TYPE *)lc)->vmsize) {
-                        foundit = true;
-                        name = _dyld_get_image_name(i);
-                        if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name);
-                    }
-                }
-            }
-        }
-#undef MACH_HEADER_TYPE
-#undef MACH_SEGMENT_CMD_TYPE
-#undef MACH_SEGMENT_FLAVOR
-    }
-#if LOG_BUNDLE_LOAD
-    printf("dyld image path for pointer %p is %p\n", p, result);
-#endif /* LOG_BUNDLE_LOAD */
-    return result;
-}
-
-__private_extern__ CFArrayRef _CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint) {
-    uint32_t i, numImages = _dyld_image_count();
-    CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
-    CFRange range = CFRangeMake(0, CFStringGetLength(hint));
-    const char *processPath = _CFProcessPath();
-    
-    for (i = 0; i < numImages; i++) {
-        const char *curName = _dyld_get_image_name(i), *lastComponent = NULL;
-        if (curName && (!processPath || 0 != strcmp(curName, processPath))) lastComponent = strrchr(curName, '/');
-        if (lastComponent) {
-            CFStringRef str = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, lastComponent + 1);
-            if (str) {
-                if (CFStringFindWithOptions(hint, str, range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL)) {
-                    CFStringRef curStr = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, curName);
-                    if (curStr) {
-                        CFArrayAppendValue(result, curStr);
-                        CFRelease(curStr);
-                    }
-                }
-                CFRelease(str);
-            }
-        }
-    }
-    return result;
-}
-
-static char *_cleanedPathForPath(const char *curName) {
-    char *thePath = strdup(curName);
-    if (thePath) {
-        // We are going to process the buffer replacing all "/./" and "//" with "/"
-        CFIndex srcIndex = 0, dstIndex = 0;
-        CFIndex len = strlen(thePath);
-        for (srcIndex=0; srcIndex<len; srcIndex++) {
-            thePath[dstIndex] = thePath[srcIndex];
-            dstIndex++;
-            while (srcIndex < len-1 && thePath[srcIndex] == '/' && (thePath[srcIndex+1] == '/' || (thePath[srcIndex+1] == '.' && srcIndex < len-2 && thePath[srcIndex+2] == '/'))) srcIndex += (thePath[srcIndex+1] == '/' ? 1 : 2);
-        }
-        thePath[dstIndex] = 0;
-    }
-    return thePath;
-}
-
-__private_extern__ CFArrayRef _CFBundleDYLDCopyLoadedImagePathsIfChanged(void) {
-    // This returns an array of the paths of all the dyld images in the process.  These paths may not be absolute, they may point at things that are not bundles, they may be staticly linked bundles or dynamically loaded bundles, they may be NULL.
-    static uint32_t _cachedDYLDImageCount = -1;
-
-    uint32_t i, numImages = _dyld_image_count();
-    CFMutableArrayRef result = NULL;
-
-    if (numImages != _cachedDYLDImageCount) {
-        const char *curName;
-        char *cleanedCurName = NULL;
-        CFStringRef curStr;
-        const char *processPath = _CFProcessPath();
-
-        result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
-
-        for (i = 0; i < numImages; i++) {
-            curName = _dyld_get_image_name(i);
-            if (curName && i == 0) cleanedCurName = _cleanedPathForPath(curName);
-            if (curName && (!processPath || 0 != strcmp(curName, processPath)) && (!processPath || !cleanedCurName || 0 != strcmp(cleanedCurName, processPath))) {
-                curStr = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, curName);
-                if (curStr) {
-                    CFArrayAppendValue(result, curStr);
-                    CFRelease(curStr);
-                }
-            }
-            if (cleanedCurName) {
-                free(cleanedCurName);
-                cleanedCurName = NULL;
-            }
-        }
-        _cachedDYLDImageCount = numImages;
-    }
-    return result;
-}
-
+#endif /* !BINARY_SUPPORT_DLFCN */
 #endif /* BINARY_SUPPORT_DYLD */
 
 #if defined(BINARY_SUPPORT_DLFCN)
@@ -3705,24 +4517,7 @@ __private_extern__ Boolean _CFBundleDlfcnCheckLoaded(CFBundleRef bundle) {
     return bundle->_isLoaded;
 }
 
-static SInt32 _CFBundleCurrentArchitecture(void) {
-    SInt32 arch = 0;
-#if defined(__ppc__)
-    arch = kCFBundleExecutableArchitecturePPC;
-#elif defined(__ppc64__)
-    arch = kCFBundleExecutableArchitecturePPC64;
-#elif defined(__i386__)
-    arch = kCFBundleExecutableArchitectureI386;
-#elif defined(__x86_64__)
-    arch = kCFBundleExecutableArchitectureX86_64;
-#elif defined(BINARY_SUPPORT_DYLD)
-    const NXArchInfo *archInfo = NXGetLocalArchInfo();
-    if (archInfo) arch = archInfo->cputype;
-#endif
-    return arch;
-}
-
-extern Boolean _CFBundleDlfcnPreflight(CFBundleRef bundle, CFErrorRef *error) {
+CF_EXPORT Boolean _CFBundleDlfcnPreflight(CFBundleRef bundle, CFErrorRef *error) {
     Boolean retval = true;
     CFErrorRef localError = NULL;
     if (!bundle->_isLoaded) {
@@ -3781,27 +4576,47 @@ __private_extern__ Boolean _CFBundleDlfcnLoadBundle(CFBundleRef bundle, Boolean
         char buff[CFMaxPathSize];
         if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
             int mode = forceGlobal ? (RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST) : (RTLD_NOW | RTLD_LOCAL | RTLD_FIRST);
-            bundle->_handleCookie = dlopen(buff, mode);
+            void *cookie = dlopen(buff, mode);
+#if LOG_BUNDLE_LOAD
+            printf("dlfcn load bundle %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, cookie);
+#endif /* LOG_BUNDLE_LOAD */
+            if (cookie && cookie == bundle->_handleCookie) {
+                // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose
 #if LOG_BUNDLE_LOAD
-            printf("dlfcn load bundle %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, bundle->_handleCookie);
+                printf("dlfcn load bundle %p closing existing reference to handle %p\n", bundle, cookie);
 #endif /* LOG_BUNDLE_LOAD */
+                dlclose(bundle->_handleCookie);
+            }
+            bundle->_handleCookie = cookie;
             if (bundle->_handleCookie) {
                 bundle->_isLoaded = true;
             } else {
-                CFStringRef debugString = NULL;
                 const char *errorString = dlerror();
-                if (errorString) {
-                    CFLog(__kCFLogBundle, CFSTR("Error loading %s:  %s"), buff, errorString);
-                    debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString);
+                if (error) {
+                    _CFBundleDlfcnPreflight(bundle, subError);
+                    if (!localError) {
+                        CFStringRef debugString = errorString ? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString) : NULL;
+                        localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
+                        if (debugString) CFRelease(debugString);
+                    }
                 } else {
-                    CFLog(__kCFLogBundle, CFSTR("Error loading %s"), buff);
+                    CFStringRef executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff);
+                    if (errorString) {
+                        CFStringRef debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString);
+                        CFLog(__kCFLogBundle, CFSTR("Error loading %@:  %@"), executableString, debugString);
+                        if (debugString) CFRelease(debugString);
+                    } else {
+                        CFLog(__kCFLogBundle, CFSTR("Error loading %@"), executableString);
+                    }
+                    if (executableString) CFRelease(executableString);
                 }
-                if (error && _CFBundleDlfcnPreflight(bundle, subError)) localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
-                if (debugString) CFRelease(debugString);
             }
         } else {
-            CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
-            if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            if (error) {
+                localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            } else {
+                CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
+            }
         }
         if (executableURL) CFRelease(executableURL);
     }
@@ -3816,27 +4631,47 @@ __private_extern__ Boolean _CFBundleDlfcnLoadFramework(CFBundleRef bundle, CFErr
         char buff[CFMaxPathSize];
         if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
             int mode = RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST;
-            bundle->_handleCookie = dlopen(buff, mode);
+            void *cookie = dlopen(buff, mode);
+#if LOG_BUNDLE_LOAD
+            printf("dlfcn load framework %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, cookie);
+#endif /* LOG_BUNDLE_LOAD */
+            if (cookie && cookie == bundle->_handleCookie) {
+                // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose
 #if LOG_BUNDLE_LOAD
-            printf("dlfcn load framework %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, bundle->_handleCookie);
+                printf("dlfcn load framework %p closing existing reference to handle %p\n", bundle, cookie);
 #endif /* LOG_BUNDLE_LOAD */
+                dlclose(bundle->_handleCookie);
+            }
+            bundle->_handleCookie = cookie;
             if (bundle->_handleCookie) {
                 bundle->_isLoaded = true;
             } else {
-                CFStringRef debugString = NULL;
                 const char *errorString = dlerror();
-                if (errorString) {
-                    CFLog(__kCFLogBundle, CFSTR("Error loading %s:  %s"), buff, errorString);
-                    debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString);
+                if (error) {
+                    _CFBundleDlfcnPreflight(bundle, subError);
+                    if (!localError) {
+                        CFStringRef debugString = errorString ? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString) : NULL;
+                        localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
+                        if (debugString) CFRelease(debugString);
+                    }
                 } else {
-                    CFLog(__kCFLogBundle, CFSTR("Error loading %s"), buff);
+                    CFStringRef executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff);
+                    if (errorString) {
+                        CFStringRef debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString);
+                        CFLog(__kCFLogBundle, CFSTR("Error loading %@:  %@"), executableString, debugString);
+                        if (debugString) CFRelease(debugString);
+                    } else {
+                        CFLog(__kCFLogBundle, CFSTR("Error loading %@"), executableString);
+                    }
+                    if (executableString) CFRelease(executableString);
                 }
-                if (error && _CFBundleDlfcnPreflight(bundle, subError)) localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
-                if (debugString) CFRelease(debugString);
             }
         } else {
-            CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
-            if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            if (error) {
+                localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            } else {
+                CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
+            }
         }
         if (executableURL) CFRelease(executableURL);
     }
@@ -3859,7 +4694,9 @@ __private_extern__ void _CFBundleDlfcnUnload(CFBundleRef bundle) {
     }
 }
 
-__private_extern__ void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) {return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, symbolName, false);}
+__private_extern__ void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) {
+    return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, symbolName, false);
+}
 
 static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch) {
     void *result = NULL;
@@ -3869,7 +4706,7 @@ static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStrin
         result = dlsym(bundle->_handleCookie, buff);
         if (!result && globalSearch) result = dlsym(RTLD_DEFAULT, buff);
 #if defined(DEBUG)
-        if (!result) CFLog(__kCFLogBundle, CFSTR("dlsym cannot find symbol %s in %@"), buff, bundle);
+        if (!result) CFLog(__kCFLogBundle, CFSTR("dlsym cannot find symbol %@ in %@"), symbolName, bundle);
 #endif /* DEBUG */
 #if LOG_BUNDLE_LOAD
         printf("bundle %p handle %p module %p image %p dlsym returns symbol %p for %s\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie, result, buff);
@@ -3878,6 +4715,8 @@ static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStrin
     return result;
 }
 
+#if !defined(BINARY_SUPPORT_DYLD)
+
 static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p) {
     CFStringRef result = NULL;
     Dl_info info;
@@ -3888,6 +4727,7 @@ static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p) {
     return result;
 }
 
+#endif /* !BINARY_SUPPORT_DYLD */
 #endif /* BINARY_SUPPORT_DLFCN */
 
 
@@ -3897,18 +4737,25 @@ __private_extern__ Boolean _CFBundleDLLLoad(CFBundleRef bundle, CFErrorRef *erro
     CFErrorRef localError = NULL;
     if (!bundle->_isLoaded) {
         CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
-        TCHAR buff[CFMaxPathSize];
+        wchar_t buff[CFMaxPathSize];
 
-        if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
-            bundle->_hModule = LoadLibrary(buff);
+        if (executableURL && _CFURLGetWideFileSystemRepresentation(executableURL, true, (wchar_t *)buff, CFMaxPathSize)) {
+            bundle->_hModule = LoadLibraryW(buff);
             if (bundle->_hModule) {
                 bundle->_isLoaded = true;
             } else {
-                if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError);
+                if (error) {
+                    localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError);
+                } else {
+                    CFLog(__kCFLogBundle, CFSTR("Failed to load bundle %@"), bundle);
+                }
             }
         } else {
-            CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
-            if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            if (error) {
+                localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
+            } else {
+                CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
+            }
         }
         if (executableURL) CFRelease(executableURL);
     }
@@ -3935,7 +4782,7 @@ __private_extern__ void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle, CFStrin
 
 /* Workarounds to be applied in the presence of certain bundles can go here. This is called on every bundle creation.
 */
-extern void _CFStringSetCompatibility(CFOptionFlags);
+CF_EXPORT void _CFStringSetCompatibility(CFOptionFlags);
 
 static void _CFBundleCheckWorkarounds(CFBundleRef bundle) {
 }
index b3b35191083bf87a1596ea1250beea80567c6f2e..c8347392df50f13d08812d38394c7eaa5f8035dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBundle.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFBUNDLE__)
@@ -80,7 +80,8 @@ CFBundleRef CFBundleGetBundleWithIdentifier(CFStringRef bundleID);
 
 CF_EXPORT
 CFArrayRef CFBundleGetAllBundles(void);
-    /* This is potentially expensive.  Use with care. */
+    /* This is potentially expensive, and not thread-safe.  Use with care. */
+    /* Best used for debuggging or other diagnostic purposes. */
 
 /* ===================== Creating Bundles ===================== */
 
@@ -165,7 +166,7 @@ CF_EXPORT
 CFArrayRef CFBundleCopyResourceURLsOfType(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName);
 
 CF_EXPORT
-CFStringRef CFBundleCopyLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName);
+CFStringRef CFBundleCopyLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName) CF_FORMAT_ARGUMENT(2);
 
 #define CFCopyLocalizedString(key, comment) \
             CFBundleCopyLocalizedString(CFBundleGetMainBundle(), (key), (key), NULL)
@@ -259,14 +260,14 @@ CFArrayRef CFBundleCopyExecutableArchitecturesForURL(CFURLRef url) AVAILABLE_MAC
 CF_EXPORT
 CFURLRef CFBundleCopyExecutableURL(CFBundleRef bundle);
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
 enum {
     kCFBundleExecutableArchitectureI386     = 0x00000007,
     kCFBundleExecutableArchitecturePPC      = 0x00000012,
     kCFBundleExecutableArchitectureX86_64   = 0x01000007,
     kCFBundleExecutableArchitecturePPC64    = 0x01000012
 };
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 */
+#endif /* MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED */
 
 CF_EXPORT
 CFArrayRef CFBundleCopyExecutableArchitectures(CFBundleRef bundle) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
index acac0a4a35c8fc4e9817635ceaf7ce48de64e3be..7f076b2721315dc6141bcfabf41caecae83b35be 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBundlePriv.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFBUNDLEPRIV__)
@@ -108,6 +108,14 @@ const CFStringRef _kCFBundleOldTypeExtensions2Key;
 CF_EXPORT
 const CFStringRef _kCFBundleOldTypeOSTypesKey;
 
+/* For platform specification */
+CF_EXPORT
+const CFStringRef _kCFBundleSupportedPlatformsKey;
+
+/* For Code Signing */
+CF_EXPORT
+const CFStringRef _kCFBundleResourceSpecificationKey;
+
 
 /* Functions for examining directories that may "look like" bundles */
 
@@ -135,6 +143,22 @@ CFURLRef _CFBundleCopyMainBundleExecutableURL(Boolean *looksLikeBundle);
 CF_EXPORT
 CFBundleRef _CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL);
 
+CF_EXPORT
+CFArrayRef _CFBundleGetSupportedPlatforms(CFBundleRef bundle);
+
+CF_EXPORT
+CFStringRef _CFBundleGetCurrentPlatform(void);
+
+
+/* For Code Signing */
+
+CF_EXPORT
+CFBundleRef _CFBundleCreateIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url);
+
+CF_EXPORT
+CFBundleRef _CFBundleCreateWithExecutableURLIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url);
+
+
 /* Functions for examining the structure of a bundle */
 
 CF_EXPORT
index ff70bce3d78edff7fd2fbeb372bf5a1c5c413731..54db8158e8b7ff33851eb4810e315ac4c9226a08 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBundle_BinaryTypes.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFBUNDLE_BINARYTYPES__)
 CF_EXTERN_C_BEGIN
 
 
-#if DEPLOYMENT_TARGET_MACOSX || 0
-#if !defined(DISABLE_DYLD_USAGE)
+#if DEPLOYMENT_TARGET_MACOSX
+#define BINARY_SUPPORT_DYLD 1
+#define BINARY_SUPPORT_DLFCN 1
+#define USE_DYLD_PRIV 1
+#elif DEPLOYMENT_TARGET_EMBEDDED
 #define BINARY_SUPPORT_DYLD 1
-#endif
-#if !defined(DISABLE_DLFCN_USAGE)
 #define BINARY_SUPPORT_DLFCN 1
+#if !defined(TARGET_IPHONE_SIMULATOR)
+#define USE_DYLD_PRIV 1
 #endif
-#elif 0 || 0
+#elif DEPLOYMENT_TARGET_WINDOWS
 #define BINARY_SUPPORT_DLL 1
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
index c6213b9d0eb584c4231c544323c9810d1216f0d8..668ed6108e41fc14e4129c75d4865389135153cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFBundle_Internal.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFBUNDLE_INTERNAL__)
@@ -40,9 +40,9 @@ CF_EXTERN_C_BEGIN
 #define __kCFLogBundle       3
 #define __kCFLogPlugIn       3
 
-#if DEPLOYMENT_TARGET_MACOSX || 0
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define PLATFORM_PATH_STYLE kCFURLPOSIXPathStyle
-#elif 0 || 0
+#elif DEPLOYMENT_TARGET_WINDOWS
 #define PLATFORM_PATH_STYLE kCFURLWindowsPathStyle
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
@@ -112,14 +112,15 @@ extern void _CFBundleUnloadScheduledBundles(void);
 #if defined(BINARY_SUPPORT_DYLD)
 // DYLD API
 extern __CFPBinaryType _CFBundleGrokBinaryType(CFURLRef executableURL);
+extern CFArrayRef _CFBundleDYLDCopyLoadedImagePathsIfChanged(void);
+extern CFArrayRef _CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint);
+#if !defined(BINARY_SUPPORT_DLFCN)
 extern Boolean _CFBundleDYLDCheckLoaded(CFBundleRef bundle);
 extern Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error);
 extern Boolean _CFBundleDYLDLoadFramework(CFBundleRef bundle, CFErrorRef *error);
 extern void _CFBundleDYLDUnloadBundle(CFBundleRef bundle);
 extern void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName);
-
-extern CFArrayRef _CFBundleDYLDCopyLoadedImagePathsIfChanged(void);
-extern CFArrayRef _CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint);
+#endif /* !BINARY_SUPPORT_DLFCN */
 #endif /* BINARY_SUPPORT_DYLD */
 
 #if defined(BINARY_SUPPORT_DLFCN)
@@ -221,7 +222,7 @@ extern void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactory *factory);
 
 #define _CFBundleLocalizedResourceForkFileName CFSTR("Localized")
 
-#if 0 || 0
+#if DEPLOYMENT_TARGET_WINDOWS
 #define _CFBundleWindowsResourceDirectoryExtension CFSTR("resources")
 #endif
 
index fc9ddae6e587ac221a6a57b37c6d6e05eb1ef6ba..ef084a6276d160d6ec421ef3c9cd95929693ca09 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
-/*     CFBundle_Resources.c
-       Copyright (c) 1999-2007 Apple Inc.  All rights reserved.
-       Responsibility: Doug Davidson
+/*      CFBundle_Resources.c
+        Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
+        Responsibility: Doug Davidson
 */
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define READ_DIRECTORIES 1
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define READ_DIRECTORIES 0
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 #define READ_DIRECTORIES_CACHE_CAPACITY 128
 #include <CoreFoundation/CFPropertyList.h>
 #include <CoreFoundation/CFByteOrder.h>
 #include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CFLocale.h>
+#include <CoreFoundation/CFPreferences.h>
 #include <string.h>
 #include "CFInternal.h"
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <ctype.h>
 
 #if DEPLOYMENT_TARGET_MACOSX
-#include <CoreFoundation/CFPreferences.h>
 #include <unistd.h>
+#elif DEPLOYMENT_TARGET_EMBEDDED
+#include <unistd.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 #if READ_DIRECTORIES
 
 // All new-style bundles will have these extensions.
 CF_INLINE CFStringRef _CFGetPlatformName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     return _CFBundleMacOSXPlatformName;
+#elif DEPLOYMENT_TARGET_WINDOWS
+    return _CFBundleWindowsPlatformName;
 #elif DEPLOYMENT_TARGET_SOLARIS
     return _CFBundleSolarisPlatformName;
 #elif DEPLOYMENT_TARGET_HPUX
@@ -73,8 +85,12 @@ CF_INLINE CFStringRef _CFGetPlatformName(void) {
 }
 
 CF_INLINE CFStringRef _CFGetAlternatePlatformName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     return _CFBundleAlternateMacOSXPlatformName;
+#elif DEPLOYMENT_TARGET_WINDOWS
+    return CFSTR("");
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 }
 
@@ -206,7 +222,6 @@ static CFArrayRef _CFBundleCopyDirectoryContentsAtPath(CFStringRef path, _CFBund
                             if (!foundIt) tryToOpen = false;
                         }
                         __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
-                        
                         CFRelease(name);
                     }
                     CFRelease(dirName);
@@ -372,7 +387,10 @@ static void _CFSearchBundleDirectory(CFAllocatorRef alloc, CFMutableArrayRef res
     // cheapStr is available for our use for whatever we want.
     // URLs for found resources get added to result.
     CFIndex savedPathLen;
-    Boolean appendSucceeded = true, platformGenericFound = false, platformSpecificFound = false, platformGenericIsDir = false, platformSpecificIsDir = false, platformGenericIsUnknown = false, platformSpecificIsUnknown = false;
+    Boolean appendSucceeded = true, platformGenericFound = false, platformSpecificFound = false, platformGenericIsDir = false, platformSpecificIsDir = false;
+#if READ_DIRECTORIES
+    Boolean platformGenericIsUnknown = false, platformSpecificIsUnknown = false; 
+#endif
     CFStringRef platformGenericStr = NULL;
 
 #if READ_DIRECTORIES
@@ -595,64 +613,71 @@ CFArrayRef _CFFindBundleResources(CFBundleRef bundle, CFURLRef bundleURL, CFStri
     CFAllocatorRef alloc = (bundle ? CFGetAllocator(bundle) : (CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()));
     CFMutableArrayRef result;
     UniChar *workingUniChars, *nameUniChars, *subDirUniChars;
-    CFIndex nameLen = (resName ? CFStringGetLength(resName) : 0);
+    CFIndex nameLen = 0;
     CFIndex subDirLen = (subDirName ? CFStringGetLength(subDirName) : 0);
     CFIndex workingLen, savedWorkingLen;
     CFURLRef absoluteURL;
     CFStringRef bundlePath;
     CFMutableStringRef cheapStr, tmpString;
+    char buff[CFMaxPathSize];
 
     result = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
+    if (resName) {  
+        CFStringRef newResName = NULL;
+        if (CFStringGetFileSystemRepresentation(resName, buff, CFMaxPathSize)) newResName = CFStringCreateWithFileSystemRepresentation(alloc, buff);
+        resName = newResName ? newResName : (CFStringRef)CFRetain(resName);
+        nameLen = CFStringGetLength(resName);
+    }
+
     // Init the one-time-only unichar buffers.
     _CFEnsureStaticBuffersInited();
 
     // Build UniChar buffers for some of the string pieces we need.
     // One malloc will do.
     nameUniChars = (UniChar *)CFAllocatorAllocate(alloc, sizeof(UniChar) * (nameLen + subDirLen + CFMaxPathSize), 0);
-    subDirUniChars = nameUniChars + nameLen;
-    workingUniChars = subDirUniChars + subDirLen;
-
-    if (nameLen > 0) CFStringGetCharacters(resName, CFRangeMake(0, nameLen), nameUniChars);
-    if (subDirLen > 0) CFStringGetCharacters(subDirName, CFRangeMake(0, subDirLen), subDirUniChars);
-    // Build a UniChar buffer with the absolute path to the bundle's resources directory.
-    // If no URL was passed, we get it from the bundle.
-    bundleURL = (bundleURL ? (CFURLRef)CFRetain(bundleURL) : CFBundleCopyBundleURL(bundle));
-    absoluteURL = CFURLCopyAbsoluteURL(bundleURL);
-    bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
-    CFRelease(absoluteURL);
-    if ((workingLen = CFStringGetLength(bundlePath)) > 0) CFStringGetCharacters(bundlePath, CFRangeMake(0, workingLen), workingUniChars);
-    CFRelease(bundlePath);
-    CFRelease(bundleURL);
-    savedWorkingLen = workingLen;
-    if (1 == version) {
-        _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars1, _AppSupportLen1);
-    } else if (2 == version) {
-        _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars2, _AppSupportLen2);
-    }
-    if (0 == version || 1 == version || 2 == version) {
-        _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _ResourcesUniChars, _ResourcesLen);
-    }
+    if (nameUniChars) {
+        subDirUniChars = nameUniChars + nameLen;
+        workingUniChars = subDirUniChars + subDirLen;
+
+        if (nameLen > 0) CFStringGetCharacters(resName, CFRangeMake(0, nameLen), nameUniChars);
+        if (subDirLen > 0) CFStringGetCharacters(subDirName, CFRangeMake(0, subDirLen), subDirUniChars);
+        // Build a UniChar buffer with the absolute path to the bundle's resources directory.
+        // If no URL was passed, we get it from the bundle.
+        bundleURL = (bundleURL ? (CFURLRef)CFRetain(bundleURL) : CFBundleCopyBundleURL(bundle));
+        absoluteURL = CFURLCopyAbsoluteURL(bundleURL);
+        bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
+        if ((workingLen = CFStringGetLength(bundlePath)) > 0) CFStringGetCharacters(bundlePath, CFRangeMake(0, workingLen), workingUniChars);
+        savedWorkingLen = workingLen;
+        if (1 == version) {
+            _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars1, _AppSupportLen1);
+        } else if (2 == version) {
+            _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars2, _AppSupportLen2);
+        }
+        if (0 == version || 1 == version || 2 == version) _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _ResourcesUniChars, _ResourcesLen);
 
-    // both of these used for temp string operations, for slightly
-    // different purposes, where each type is appropriate
-    cheapStr = CFStringCreateMutable(alloc, 0);
-    _CFStrSetDesiredCapacity(cheapStr, CFMaxPathSize);
-    tmpString = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull);
+        // both of these used for temp string operations, for slightly different purposes, where each type is appropriate
+        cheapStr = CFStringCreateMutable(alloc, 0);
+        _CFStrSetDesiredCapacity(cheapStr, CFMaxPathSize);
+        tmpString = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull);
 
-    _CFFindBundleResourcesInResourcesDir(alloc, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, version, cheapStr, tmpString, result);
-    
-    // drd: This unfortunate hack is still necessary because of installer packages
-    if (0 == version && CFArrayGetCount(result) == 0) {
-        // Try looking directly in the bundle path
-        workingLen = savedWorkingLen;
         _CFFindBundleResourcesInResourcesDir(alloc, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, version, cheapStr, tmpString, result);
-    }
+        
+        // drd: This unfortunate hack is still necessary because of installer packages and Spotlight importers
+        if (CFArrayGetCount(result) == 0 && (0 == version || (2 == version && bundlePath && CFEqual(CFSTR("/Library/Spotlight"), bundlePath)))) {
+            // Try looking directly in the bundle path
+            workingLen = savedWorkingLen;
+            _CFFindBundleResourcesInResourcesDir(alloc, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, version, cheapStr, tmpString, result);
+        }
 
-    CFRelease(cheapStr);
-    CFRelease(tmpString);
-    CFAllocatorDeallocate(alloc, nameUniChars);
+        CFRelease(absoluteURL);
+        CFRelease(bundlePath);
+        CFRelease(bundleURL);
+        CFRelease(cheapStr);
+        CFRelease(tmpString);
+        CFAllocatorDeallocate(alloc, nameUniChars);
+    }
+    if (resName) CFRelease(resName);
     if (!bundle) CFRelease(alloc);
-
     return result;
 }
 
@@ -660,11 +685,8 @@ CF_EXPORT CFURLRef CFBundleCopyResourceURL(CFBundleRef bundle, CFStringRef resou
     CFURLRef result = NULL;
     CFArrayRef languages = _CFBundleGetLanguageSearchList(bundle), types = NULL, array;
     if (resourceType) types = CFArrayCreate(CFGetAllocator(bundle), (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-    
     array = _CFFindBundleResources(bundle, NULL, subDirName, languages, resourceName, types, 1, _CFBundleLayoutVersion(bundle));
-    
     if (types) CFRelease(types);
-    
     if (array) {
         if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0));
         CFRelease(array);
@@ -675,16 +697,16 @@ CF_EXPORT CFURLRef CFBundleCopyResourceURL(CFBundleRef bundle, CFStringRef resou
 CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfType(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName) {
     CFArrayRef languages = _CFBundleGetLanguageSearchList(bundle), types = NULL, array;
     if (resourceType) types = CFArrayCreate(CFGetAllocator(bundle), (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-
     // MF:!!! Better "limit" than 1,000,000?
     array = _CFFindBundleResources(bundle, NULL, subDirName, languages, NULL, types, 1000000, _CFBundleLayoutVersion(bundle));
-    
     if (types) CFRelease(types);
     
     return array;
 }
 
-CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {return CFBundleCopyResourceURLForLocalization(bundle, resourceName, resourceType, subDirName, language);}
+CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {
+    return CFBundleCopyResourceURLForLocalization(bundle, resourceName, resourceType, subDirName, language);
+}
 
 CF_EXPORT CFURLRef CFBundleCopyResourceURLForLocalization(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef localizationName) {
     CFURLRef result = NULL;
@@ -692,44 +714,48 @@ CF_EXPORT CFURLRef CFBundleCopyResourceURLForLocalization(CFBundleRef bundle, CF
 
     if (localizationName) languages = CFArrayCreate(CFGetAllocator(bundle), (const void **)&localizationName, 1, &kCFTypeArrayCallBacks);
     if (resourceType) types = CFArrayCreate(CFGetAllocator(bundle), (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-    
     array = _CFFindBundleResources(bundle, NULL, subDirName, languages, resourceName, types, 1, _CFBundleLayoutVersion(bundle));
     if (array) {
         if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0));
         CFRelease(array);
     }
-
     if (types) CFRelease(types);
     if (languages) CFRelease(languages);
-    
     return result;
 }
 
-CF_EXPORT CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {return CFBundleCopyResourceURLsOfTypeForLocalization(bundle, resourceType, subDirName, language);}
+CF_EXPORT CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {
+    return CFBundleCopyResourceURLsOfTypeForLocalization(bundle, resourceType, subDirName, language);
+}
 
 CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfTypeForLocalization(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef localizationName) {
     CFArrayRef languages = NULL, types = NULL, array;
 
     if (localizationName) languages = CFArrayCreate(CFGetAllocator(bundle), (const void **)&localizationName, 1, &kCFTypeArrayCallBacks);
     if (resourceType) types = CFArrayCreate(CFGetAllocator(bundle), (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-    
     // MF:!!! Better "limit" than 1,000,000?
     array = _CFFindBundleResources(bundle, NULL, subDirName, languages, NULL, types, 1000000, _CFBundleLayoutVersion(bundle));
-
     if (types) CFRelease(types);
     if (languages) CFRelease(languages);
-
     return array;
 }
 
 CF_EXPORT CFStringRef CFBundleCopyLocalizedString(CFBundleRef bundle, CFStringRef key, CFStringRef value, CFStringRef tableName) {
     CFStringRef result = NULL;
     CFDictionaryRef stringTable = NULL;
+    static CFSpinLock_t CFBundleLocalizedStringLock = CFSpinLockInit;
 
     if (!key) return (value ? (CFStringRef)CFRetain(value) : (CFStringRef)CFRetain(CFSTR("")));
 
     if (!tableName || CFEqual(tableName, CFSTR(""))) tableName = _CFBundleDefaultStringTableName;
-    if (__CFBundleGetResourceData(bundle)->_stringTableCache) stringTable = (CFDictionaryRef)CFDictionaryGetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName);
+
+    __CFSpinLock(&CFBundleLocalizedStringLock);
+    if (__CFBundleGetResourceData(bundle)->_stringTableCache) {
+        stringTable = (CFDictionaryRef)CFDictionaryGetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName);
+        if (stringTable) CFRetain(stringTable);
+    }
+    __CFSpinUnlock(&CFBundleLocalizedStringLock);
+
     if (!stringTable) {
         // Go load the table.
         CFURLRef tableURL = CFBundleCopyResourceURL(bundle, tableName, _CFBundleStringTableType, NULL);
@@ -756,9 +782,13 @@ CF_EXPORT CFStringRef CFBundleCopyLocalizedString(CFBundleRef bundle, CFStringRe
             CFRelease(tableURL);
         }
         if (!stringTable) stringTable = CFDictionaryCreate(CFGetAllocator(bundle), NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-        if (!__CFBundleGetResourceData(bundle)->_stringTableCache) __CFBundleGetResourceData(bundle)->_stringTableCache = CFDictionaryCreateMutable(CFGetAllocator(bundle), 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-        CFDictionarySetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName, stringTable);
-        CFRelease(stringTable);
+
+        if (!CFStringHasSuffix(tableName, CFSTR(".nocache")) || !_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) {
+            __CFSpinLock(&CFBundleLocalizedStringLock);
+            if (!__CFBundleGetResourceData(bundle)->_stringTableCache) __CFBundleGetResourceData(bundle)->_stringTableCache = CFDictionaryCreateMutable(CFGetAllocator(bundle), 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+            CFDictionarySetValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName, stringTable);
+            __CFSpinUnlock(&CFBundleLocalizedStringLock);
+        }
     }
 
     result = (CFStringRef)CFDictionaryGetValue(stringTable, key);
@@ -783,8 +813,7 @@ CF_EXPORT CFStringRef CFBundleCopyLocalizedString(CFBundleRef bundle, CFStringRe
     } else {
         CFRetain(result);
     }
-    if (CFStringHasSuffix(tableName, CFSTR(".nocache")) && __CFBundleGetResourceData(bundle)->_stringTableCache && _CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) CFDictionaryRemoveValue(__CFBundleGetResourceData(bundle)->_stringTableCache, tableName);
-    
+    CFRelease(stringTable);
     return result;
 }
 
@@ -801,12 +830,9 @@ CF_EXPORT CFURLRef CFBundleCopyResourceURLInDirectory(CFURLRef bundleURL, CFStri
         uint8_t version = 0;
         CFArrayRef languages = _CFBundleCopyLanguageSearchListInDirectory(kCFAllocatorSystemDefault, newURL, &version), types = NULL, array;
         if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-        
         array = _CFFindBundleResources(NULL, newURL, subDirName, languages, resourceName, types, 1, version);
-
         if (types) CFRelease(types);
         if (languages) CFRelease(languages);
-
         if (array) {
             if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0));
             CFRelease(array);
@@ -829,10 +855,8 @@ CF_EXPORT CFArrayRef CFBundleCopyResourceURLsOfTypeInDirectory(CFURLRef bundleUR
         uint8_t version = 0;
         CFArrayRef languages = _CFBundleCopyLanguageSearchListInDirectory(kCFAllocatorSystemDefault, newURL, &version), types = NULL;
         if (resourceType) types = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&resourceType, 1, &kCFTypeArrayCallBacks);
-
         // MF:!!! Better "limit" than 1,000,000?
         array = _CFFindBundleResources(NULL, newURL, subDirName, languages, NULL, types, 1000000, version);
-
         if (types) CFRelease(types);
         if (languages) CFRelease(languages);
     }
@@ -857,8 +881,8 @@ const char * __CFBundleLocaleAbbreviationsArray =
     "ur_IN\0"      "vi_VN\0"      "fr_BE\0"      "uz_UZ\0"      "en_SG\0"      "nn_NO\0"      "af_ZA\0"      "eo\0\0\0\0"
     "mr_IN\0"      "bo\0\0\0\0"   "ne_NP\0"      "kl\0\0\0\0"   "en_IE\0";
 
-#define NUM_LOCALE_ABBREVIATIONS       109
-#define LOCALE_ABBREVIATION_LENGTH     6
+#define NUM_LOCALE_ABBREVIATIONS        109
+#define LOCALE_ABBREVIATION_LENGTH      6
 
 static const char * const __CFBundleLanguageNamesArray[] = {
     "English",      "French",       "German",       "Italian",      "Dutch",        "Swedish",      "Spanish",      "Danish",
@@ -882,8 +906,8 @@ static const char * const __CFBundleLanguageNamesArray[] = {
     "Scottish",     "Manx",         "Irish",        "Tongan",       "Greek",        "Greenlandic",  "Azerbaijani",  "Nynorsk"
 };
 
-#define NUM_LANGUAGE_NAMES     152
-#define LANGUAGE_NAME_LENGTH   13
+#define NUM_LANGUAGE_NAMES      152
+#define LANGUAGE_NAME_LENGTH    13
 
 // string, with groups of 3 characters being 1 element in the array of abbreviations
 const char * __CFBundleLanguageAbbreviationsArray =
@@ -907,8 +931,8 @@ const char * __CFBundleLanguageAbbreviationsArray =
     "ug\0"   "dz\0"   "jv\0"   "su\0"   "gl\0"   "af\0"   "br\0"   "iu\0"
     "gd\0"   "gv\0"   "ga\0"   "to\0"   "el\0"   "kl\0"   "az\0"   "nn\0";
 
-#define NUM_LANGUAGE_ABBREVIATIONS     152
-#define LANGUAGE_ABBREVIATION_LENGTH   3
+#define NUM_LANGUAGE_ABBREVIATIONS      152
+#define LANGUAGE_ABBREVIATION_LENGTH    3
 
 #if defined(__CONSTANT_CFSTRINGS__)
 
@@ -1026,7 +1050,7 @@ CF_INLINE CFStringRef _CFBundleCopyLanguageNameForLocalization(CFStringRef local
 
 static SInt32 _CFBundleGetLanguageCodeForRegionCode(SInt32 regionCode) {
     SInt32 result = -1, i;
-    if (52 == regionCode) {    // hack for mixed-up Chinese language codes
+    if (52 == regionCode) {     // hack for mixed-up Chinese language codes
         result = 33;
     } else if (0 <= regionCode && regionCode < NUM_LOCALE_ABBREVIATIONS) {
         const char *localeAbbreviation = __CFBundleLocaleAbbreviationsArray + regionCode * LOCALE_ABBREVIATION_LENGTH;
@@ -1041,7 +1065,7 @@ static SInt32 _CFBundleGetLanguageCodeForRegionCode(SInt32 regionCode) {
 
 static SInt32 _CFBundleGetRegionCodeForLanguageCode(SInt32 languageCode) {
     SInt32 result = -1, i;
-    if (19 == languageCode) {  // hack for mixed-up Chinese language codes
+    if (19 == languageCode) {   // hack for mixed-up Chinese language codes
         result = 53;
     } else if (0 <= languageCode && languageCode < NUM_LANGUAGE_ABBREVIATIONS) {
         const char *languageAbbreviation = __CFBundleLanguageAbbreviationsArray + languageCode * LANGUAGE_ABBREVIATION_LENGTH;
@@ -1060,7 +1084,7 @@ static SInt32 _CFBundleGetRegionCodeForLocalization(CFStringRef localizationName
     SInt32 result = -1, i;
     char buff[LOCALE_ABBREVIATION_LENGTH];
     CFIndex length = CFStringGetLength(localizationName);
-    if ((length >= LANGUAGE_ABBREVIATION_LENGTH - 1) && (length <= LOCALE_ABBREVIATION_LENGTH - 1) && CFStringGetCString(localizationName, buff, LOCALE_ABBREVIATION_LENGTH, kCFStringEncodingASCII)) {
+    if (length >= LANGUAGE_ABBREVIATION_LENGTH - 1 && length <= LOCALE_ABBREVIATION_LENGTH - 1 && CFStringGetCString(localizationName, buff, LOCALE_ABBREVIATION_LENGTH, kCFStringEncodingASCII)) {
         buff[LOCALE_ABBREVIATION_LENGTH - 1] = '\0';
         for (i = 0; -1 == result && i < NUM_LOCALE_ABBREVIATIONS * LOCALE_ABBREVIATION_LENGTH; i += LOCALE_ABBREVIATION_LENGTH) {
             if (0 == strcmp(buff, __CFBundleLocaleAbbreviationsArray + i)) result = i / LOCALE_ABBREVIATION_LENGTH;
@@ -1101,6 +1125,19 @@ Boolean CFBundleGetLocalizationInfoForLocalization(CFStringRef localizationName,
         if (!languages) languages = _CFBundleCopyUserLanguages(false);
         if (languages && CFArrayGetCount(languages) > 0) localizationName = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);
     }
+    if (localizationName) {
+        LangCode langCode = -1;
+        RegionCode regCode = -1;
+        ScriptCode scrCode = 0;
+        CFStringEncoding enc = kCFStringEncodingMacRoman;
+        retval = CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(localizationName, &langCode, &regCode, &scrCode, &enc);
+        if (retval) {
+            language = langCode;
+            region = regCode;
+            script = scrCode;
+            encoding = enc;
+        }
+    }  
     if (!retval) {
         if (localizationName) {
             language = _CFBundleGetLanguageCodeForLocalization(localizationName);
@@ -1127,15 +1164,11 @@ Boolean CFBundleGetLocalizationInfoForLocalization(CFStringRef localizationName,
 
 CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SInt32 regionCode, SInt32 scriptCode, CFStringEncoding stringEncoding) {
     CFStringRef localizationName = NULL;
-    if (!localizationName) {
-        localizationName = _CFBundleCopyLocaleAbbreviationForRegionCode(regionCode);
-    }
-    if (!localizationName && 0 <= languageCode && languageCode < SHRT_MAX) {
-        localizationName = CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(kCFAllocatorSystemDefault, (LangCode)languageCode, (RegionCode)-1);
-    }
-    if (!localizationName) {
-        localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(languageCode);
-    }
+    if (!localizationName) localizationName = _CFBundleCopyLocaleAbbreviationForRegionCode(regionCode);
+#if DEPLOYMENT_TARGET_MACOSX
+    if (!localizationName && 0 <= languageCode && languageCode < SHRT_MAX) localizationName = CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(kCFAllocatorSystemDefault, (LangCode)languageCode, (RegionCode)-1);
+#endif
+    if (!localizationName) localizationName = _CFBundleCopyLanguageAbbreviationForLanguageCode(languageCode);
     if (!localizationName) {
         SInt32 language = -1, scriptLanguage = -1, encodingLanguage = -1;
         unsigned int i;
@@ -1157,9 +1190,58 @@ CFStringRef CFBundleCopyLocalizationForLocalizationInfo(SInt32 languageCode, SIn
 
 extern void *__CFAppleLanguages;
 
+#if DEPLOYMENT_TARGET_WINDOWS
+
+extern CFStringRef copyLocaleLanguageName(void);
+extern CFStringRef copyLocaleCountryName(void);
+
+static CFArrayRef copyWindowsLanguagePrefsArray() {
+    CFArrayRef result;
+    CFStringRef locales[4];
+    CFStringRef languageName = copyLocaleLanguageName(), countryName = copyLocaleCountryName();
+    if (!languageName) languageName = CFSTR("en");
+    if (!countryName) countryName = CFSTR("");
+    CFIndex i, localesCount = 0;
+    if (CFStringGetLength(countryName) > 0) locales[localesCount++] = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@_%@"), languageName, countryName);
+    if (CFStringGetLength(languageName) != 0) {
+        // special-case for zh since we don't have a generic zh localization
+        if (CFStringCompare(languageName, CFSTR("zh"), kCFCompareCaseInsensitive) != 0) {
+            locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, languageName);//languageName;
+        } else {
+            CFStringRef moreSpecificLanguageName;
+
+            // See http://intrigue-build.apple.com/changeset/14948 for the details on the change.  Copied below is the snippet of the code change.
+            // According to http://www.microsoft.com/globaldev/reference/win2k/setup/lcid.mspx, the locales that use 
+            // 126          // simplified chinese are CN (PRC) and SG (Singapore).  The rest use traditional chinese. 
+            // 127          languageName = (countryName == TEXT("CN") || countryName == TEXT("SG")) ? TEXT("zh_CN") : TEXT("zh_TW"); 
+
+            // Compare for CN or SG
+            if (CFStringCompare(countryName, CFSTR("CN"), kCFCompareCaseInsensitive) == 0 || CFStringCompare(countryName, CFSTR("SG"), kCFCompareCaseInsensitive) == 0) {
+                moreSpecificLanguageName = CFSTR("zh_CN");
+            } else {
+                moreSpecificLanguageName = CFSTR("zh_TW");
+            }
+            locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, moreSpecificLanguageName);
+        }
+        // Don't need this now
+        if (languageName) CFRelease(languageName);
+        if (countryName) CFRelease(countryName);
+    }
+    if (localesCount == 0) locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, CFSTR("en"));
+    result = CFArrayCreate(kCFAllocatorDefault, (const void **)locales, localesCount, &kCFTypeArrayCallBacks);
+    for (i = 0; i < localesCount; i++) CFRelease(locales[i]);
+    return result;
+}
+
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+    
+static CFArrayRef _CFBundleUserLanguages = NULL;
+
 __private_extern__ CFArrayRef _CFBundleCopyUserLanguages(Boolean useBackstops) {
     CFArrayRef result = NULL;
-    static CFArrayRef userLanguages = NULL;
     static Boolean didit = false;
     CFArrayRef preferencesArray = NULL;
     // This is a temporary solution, until the argument domain is moved down into CFPreferences
@@ -1171,27 +1253,27 @@ __private_extern__ CFArrayRef _CFBundleCopyUserLanguages(Boolean useBackstops) {
             if (length > 0) {
                 data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (const UInt8 *)__CFAppleLanguages, length, kCFAllocatorNull);
                 if (data) {
-                    userLanguages = (CFArrayRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListImmutable, NULL);
+                    _CFBundleUserLanguages = (CFArrayRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListImmutable, NULL);
                     CFRelease(data);
                 }
             }
         }
-        if (!userLanguages && preferencesArray) userLanguages = (CFArrayRef)CFRetain(preferencesArray);
+        if (!_CFBundleUserLanguages && preferencesArray) _CFBundleUserLanguages = (CFArrayRef)CFRetain(preferencesArray);
         Boolean useEnglishAsBackstop = true;
         // could perhaps read out of LANG environment variable
-        if (useEnglishAsBackstop && !userLanguages) {
+        if (useEnglishAsBackstop && !_CFBundleUserLanguages) {
             CFStringRef english = CFSTR("en");
-            userLanguages = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&english, 1, &kCFTypeArrayCallBacks);
+            _CFBundleUserLanguages = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&english, 1, &kCFTypeArrayCallBacks);
         }
-        if (userLanguages && CFGetTypeID(userLanguages) != CFArrayGetTypeID()) {
-            CFRelease(userLanguages);
-            userLanguages = NULL;
+        if (_CFBundleUserLanguages && CFGetTypeID(_CFBundleUserLanguages) != CFArrayGetTypeID()) {
+            CFRelease(_CFBundleUserLanguages);
+            _CFBundleUserLanguages = NULL;
         }
         didit = true;
     }
     __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
     if (preferencesArray) CFRelease(preferencesArray);
-    if (!result && userLanguages) result = (CFArrayRef)CFRetain(userLanguages);
+    if (!result && _CFBundleUserLanguages) result = (CFArrayRef)CFRetain(_CFBundleUserLanguages);
     return result;
 }
 
@@ -1211,6 +1293,11 @@ CF_EXPORT void _CFBundleGetLanguageAndRegionCodes(SInt32 *languageCode, SInt32 *
         Boolean retval = false;
         LangCode langCode = -1;
         RegionCode regCode = -1;
+        retval = CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(localizationName, &langCode, &regCode, NULL, NULL);
+        if (retval) {
+            language = langCode;
+            region = regCode;
+        }
         if (!retval) {
             language = _CFBundleGetLanguageCodeForLocalization(localizationName);
             region = _CFBundleGetRegionCodeForLocalization(localizationName);
@@ -1227,12 +1314,12 @@ CF_EXPORT void _CFBundleGetLanguageAndRegionCodes(SInt32 *languageCode, SInt32 *
 }
 
 
-static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc, UniChar *pathUniChars, CFIndex pathLen, uint8_t version, CFDictionaryRef infoDict, CFStringRef curLangStr, CFMutableArrayRef lprojNames) {
+static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc, UniChar *pathUniChars, CFIndex pathLen, uint8_t version, CFDictionaryRef infoDict, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage) {
     CFIndex curLangLen = CFStringGetLength(curLangStr), savedPathLen;
     UniChar curLangUniChars[255];
-    CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL;
+    CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL;
     CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL, predefinedCanonicalLanguageIdentifiers = NULL;
-    Boolean foundOne = false;
+    Boolean foundOne = false, specifiesScript = false;
     CFArrayRef predefinedLocalizations = NULL;
     CFRange predefinedLocalizationsRange;
     CFMutableStringRef cheapStr, tmpString;
@@ -1369,7 +1456,7 @@ static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc
             }
         }
     }
-    if (!altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) {
+    if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) {
         curLangLen = CFStringGetLength(languageAbbreviation);
         if (curLangLen > 255) curLangLen = 255;
         CFStringGetCharacters(languageAbbreviation, CFRangeMake(0, curLangLen), curLangUniChars);
@@ -1389,7 +1476,7 @@ static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc
             }
         }
     }
-    if (!altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) {
+    if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) {
         curLangLen = CFStringGetLength(languageName);
         if (curLangLen > 255) curLangLen = 255;
         CFStringGetCharacters(languageName, CFRangeMake(0, curLangLen), curLangUniChars);
@@ -1415,12 +1502,12 @@ static Boolean _CFBundleTryOnePreferredLprojNameInDirectory(CFAllocatorRef alloc
     if (canonicalLanguageIdentifier) CFRelease(canonicalLanguageIdentifier);
     if (canonicalLanguageIdentifiers) CFRelease(canonicalLanguageIdentifiers);
     if (predefinedCanonicalLanguageIdentifiers) CFRelease(predefinedCanonicalLanguageIdentifiers);
+    if (canonicalLanguageAbbreviation) CFRelease(canonicalLanguageAbbreviation);
     CFRelease(cheapStr);
     CFRelease(tmpString);
 #if READ_DIRECTORIES
     CFRelease(contents);
 #endif /* READ_DIRECTORIES */
-
     return foundOne;
 }
 
@@ -1446,20 +1533,36 @@ static Boolean CFBundleAllowMixedLocalizations(void) {
     return allowMixed;
 }
 
+static Boolean _CFBundleLocalizationsHaveCommonPrefix(CFStringRef loc1, CFStringRef loc2) {
+    Boolean result = false;
+    CFIndex length1 = CFStringGetLength(loc1), length2 = CFStringGetLength(loc2), idx;
+    if (length1 > 3 && length2 > 3) {
+        for (idx = 0; idx < length1 && idx < length2; idx++) {
+            UniChar c1 = CFStringGetCharacterAtIndex(loc1, idx), c2 = CFStringGetCharacterAtIndex(loc2, idx);
+            if (idx >= 2 && (c1 == '-' || c1 == '_') && (c2 == '-' || c2 == '_')) {
+                result = true;
+                break;
+            } else if (c1 != c2) {
+                break;
+            }
+        }
+    }
+    return result;
+}
+
 __private_extern__ void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRef alloc, CFURLRef bundleURL, uint8_t version, CFDictionaryRef infoDict, CFMutableArrayRef lprojNames, CFStringRef devLang) {
     // This function will add zero, one or two elements to the lprojNames array.
     // It examines the users preferred language list and the lproj directories inside the bundle directory.  It picks the lproj directory that is highest on the users list.
     // The users list can contain region names (like "en_US" for US English).  In this case, if the region lproj exists, it will be added, and, if the region's associated language lproj exists that will be added.
     CFURLRef resourcesURL = _CFBundleCopyResourcesDirectoryURLInDirectory(alloc, bundleURL, version);
     CFURLRef absoluteURL;
-    CFIndex idx;
+    CFIndex idx, startIdx;
     CFIndex count;
     CFStringRef resourcesPath;
     UniChar pathUniChars[CFMaxPathSize];
     CFIndex pathLen;
-    CFStringRef curLangStr;
+    CFStringRef curLangStr, nextLangStr;
     Boolean foundOne = false;
-
     CFArrayRef userLanguages;
     
     // Init the one-time-only unichar buffers.
@@ -1480,15 +1583,17 @@ __private_extern__ void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRe
         CFBundleRef mainBundle = CFBundleGetMainBundle();
         if (mainBundle) {
             CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle);
-            if (!CFEqual(bundleURL, mainBundleURL)) {
-                // If there is a main bundle, and it isn't this one, try to use the language it prefers.
-                CFArrayRef mainBundleLangs = _CFBundleGetLanguageSearchList(mainBundle);
-                if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) {
-                    curLangStr = (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0);
-                    foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames);
+            if (mainBundleURL) {
+                if (!CFEqual(bundleURL, mainBundleURL)) {
+                    // If there is a main bundle, and it isn't this one, try to use the language it prefers.
+                    CFArrayRef mainBundleLangs = _CFBundleGetLanguageSearchList(mainBundle);
+                    if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) {
+                        curLangStr = (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0);
+                        foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true);
+                    }
                 }
+                CFRelease(mainBundleURL);
             }
-            CFRelease(mainBundleURL);
         }
     }
 
@@ -1496,21 +1601,35 @@ __private_extern__ void _CFBundleAddPreferredLprojNamesInDirectory(CFAllocatorRe
         // If we didn't find the main bundle's preferred language, look at the users' prefs again and find the best one.
         userLanguages = _CFBundleCopyUserLanguages(true);
         count = (userLanguages ? CFArrayGetCount(userLanguages) : 0);
-        for (idx = 0; !foundOne && idx < count; idx++) {
+        for (idx = 0, startIdx = -1; !foundOne && idx < count; idx++) {
             curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, idx);
-            foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames);
+            nextLangStr = (idx + 1 < count) ? (CFStringRef)CFArrayGetValueAtIndex(userLanguages, idx + 1) : NULL;
+            if (nextLangStr && _CFBundleLocalizationsHaveCommonPrefix(curLangStr, nextLangStr)) {
+                foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, false);
+                if (startIdx < 0) startIdx = idx;
+            } else if (startIdx >= 0 && startIdx <= idx) {
+                foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, false);
+                for (; !foundOne && startIdx <= idx; startIdx++) {
+                    curLangStr = (CFStringRef)CFArrayGetValueAtIndex(userLanguages, startIdx);
+                    foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true);
+                }
+                startIdx = -1;
+            } else {
+                foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, curLangStr, lprojNames, true);
+                startIdx = -1;
+            }
         }
         // use development region and U.S. English as backstops
-        if (!foundOne && devLang) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, devLang, lprojNames);
-        if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, CFSTR("en_US"), lprojNames);
+        if (!foundOne && devLang) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, devLang, lprojNames, true);
+        if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInDirectory(alloc, pathUniChars, pathLen, version, infoDict, CFSTR("en_US"), lprojNames, true);
         if (userLanguages) CFRelease(userLanguages);
     }
 }
 
-static Boolean _CFBundleTryOnePreferredLprojNameInArray(CFArrayRef array, CFStringRef curLangStr, CFMutableArrayRef lprojNames) {
-    Boolean foundOne = false;
+static Boolean _CFBundleTryOnePreferredLprojNameInArray(CFArrayRef array, CFStringRef curLangStr, CFMutableArrayRef lprojNames, Boolean fallBackToLanguage) {
+    Boolean foundOne = false, specifiesScript = false;
     CFRange range = CFRangeMake(0, CFArrayGetCount(array));
-    CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL;
+    CFStringRef altLangStr = NULL, modifiedLangStr = NULL, languageAbbreviation = NULL, languageName = NULL, canonicalLanguageIdentifier = NULL, canonicalLanguageAbbreviation = NULL;
     CFMutableDictionaryRef canonicalLanguageIdentifiers = NULL;
 
     if (range.length == 0) return foundOne;
@@ -1541,13 +1660,13 @@ static Boolean _CFBundleTryOnePreferredLprojNameInArray(CFArrayRef array, CFStri
             foundOne = true;
         }
     }
-    if (!altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) {
+    if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageAbbreviation = _CFBundleCopyLanguageAbbreviationForLocalization(curLangStr)) && !CFEqual(curLangStr, languageAbbreviation)) {
         if (CFArrayContainsValue(array, range, languageAbbreviation)) {
             if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageAbbreviation)) CFArrayAppendValue(lprojNames, languageAbbreviation);
             foundOne = true;
         }
     }
-    if (!altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) {
+    if (!specifiesScript && (foundOne || fallBackToLanguage) && !altLangStr && (languageName = _CFBundleCopyLanguageNameForLocalization(curLangStr)) && !CFEqual(curLangStr, languageName)) {
         if (CFArrayContainsValue(array, range, languageName)) {
             if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageName)) CFArrayAppendValue(lprojNames, languageName);
             foundOne = true;
@@ -1558,42 +1677,53 @@ static Boolean _CFBundleTryOnePreferredLprojNameInArray(CFArrayRef array, CFStri
     if (languageName) CFRelease(languageName);
     if (canonicalLanguageIdentifier) CFRelease(canonicalLanguageIdentifier);
     if (canonicalLanguageIdentifiers) CFRelease(canonicalLanguageIdentifiers);
-
+    if (canonicalLanguageAbbreviation) CFRelease(canonicalLanguageAbbreviation);
     return foundOne;
 }
 
 static CFArrayRef _CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, CFArrayRef prefArray, Boolean considerMain) {
     CFMutableArrayRef lprojNames = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
     Boolean foundOne = false, releasePrefArray = false;
-    CFIndex idx, count;
+    CFIndex idx, count, startIdx;
     
     if (considerMain && !CFBundleAllowMixedLocalizations()) {
         CFBundleRef mainBundle = CFBundleGetMainBundle();
         if (mainBundle) {
             // If there is a main bundle, try to use the language it prefers.
             CFArrayRef mainBundleLangs = _CFBundleGetLanguageSearchList(mainBundle);
-            if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) {
-                foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0), lprojNames);
-            }
+            if (mainBundleLangs && (CFArrayGetCount(mainBundleLangs) > 0)) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(mainBundleLangs, 0), lprojNames, true);
         }
     }
+    
     if (!foundOne) {
+        CFStringRef curLangStr, nextLangStr;
         if (!prefArray) {
             prefArray = _CFBundleCopyUserLanguages(true);
             if (prefArray) releasePrefArray = true;
         }
         count = (prefArray ? CFArrayGetCount(prefArray) : 0);
-        for (idx = 0; !foundOne && idx < count; idx++) {
-            foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(prefArray, idx), lprojNames);
+        for (idx = 0, startIdx = -1; !foundOne && idx < count; idx++) {
+            curLangStr = (CFStringRef)CFArrayGetValueAtIndex(prefArray, idx);
+            nextLangStr = (idx + 1 < count) ? (CFStringRef)CFArrayGetValueAtIndex(prefArray, idx + 1) : NULL;
+            if (nextLangStr && _CFBundleLocalizationsHaveCommonPrefix(curLangStr, nextLangStr)) {
+                foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, false);
+                if (startIdx < 0) startIdx = idx;
+            } else if (startIdx >= 0 && startIdx <= idx) {
+                foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, false);
+                for (; !foundOne && startIdx <= idx; startIdx++) {
+                    curLangStr = (CFStringRef)CFArrayGetValueAtIndex(prefArray, startIdx);
+                    foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, true);
+                }
+                startIdx = -1;
+            } else {
+                foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, curLangStr, lprojNames, true);
+                startIdx = -1;
+            }
         }
         // use U.S. English as backstop
-        if (!foundOne) {
-            foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, CFSTR("en_US"), lprojNames);
-        }
+        if (!foundOne) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, CFSTR("en_US"), lprojNames, true);
         // use random entry as backstop
-        if (!foundOne && CFArrayGetCount(lprojNames) > 0) {
-            foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(locArray, 0), lprojNames);
-        }
+        if (!foundOne && CFArrayGetCount(locArray) > 0) foundOne = _CFBundleTryOnePreferredLprojNameInArray(locArray, (CFStringRef)CFArrayGetValueAtIndex(locArray, 0), lprojNames, true);
     }
     if (CFArrayGetCount(lprojNames) == 0) {
         // Total backstop behavior to avoid having an empty array. 
@@ -1605,9 +1735,13 @@ static CFArrayRef _CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray,
     return lprojNames;
 }
 
-CF_EXPORT CFArrayRef CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, CFArrayRef prefArray) {return _CFBundleCopyLocalizationsForPreferences(locArray, prefArray, false);}
+CF_EXPORT CFArrayRef CFBundleCopyLocalizationsForPreferences(CFArrayRef locArray, CFArrayRef prefArray) {
+    return _CFBundleCopyLocalizationsForPreferences(locArray, prefArray, false);
+}
 
-CF_EXPORT CFArrayRef CFBundleCopyPreferredLocalizationsFromArray(CFArrayRef locArray) {return _CFBundleCopyLocalizationsForPreferences(locArray, NULL, true);}
+CF_EXPORT CFArrayRef CFBundleCopyPreferredLocalizationsFromArray(CFArrayRef locArray) {
+    return _CFBundleCopyLocalizationsForPreferences(locArray, NULL, true);
+}
 
 __private_extern__ CFArrayRef _CFBundleCopyLanguageSearchListInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) {
     CFMutableArrayRef langs = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
@@ -1641,10 +1775,8 @@ CF_EXPORT Boolean _CFBundleURLLooksLikeBundle(CFURLRef url) {
 
 // Note that subDirName is expected to be the string for a URL
 CF_INLINE Boolean _CFBundleURLHasSubDir(CFURLRef url, CFStringRef subDirName) {
-    CFURLRef dirURL;
     Boolean isDir = false, result = false;
-
-    dirURL = CFURLCreateWithString(kCFAllocatorSystemDefault, subDirName, url);
+    CFURLRef dirURL = CFURLCreateWithString(kCFAllocatorSystemDefault, subDirName, url);
     if (dirURL) {
         if (_CFIsResourceAtURL(dirURL, &isDir) && isDir) result = true;
         CFRelease(dirURL);
@@ -1680,7 +1812,8 @@ __private_extern__ Boolean _CFBundleURLLooksLikeBundleVersion(CFURLRef url, uint
     CFRelease(absoluteURL);
 #endif /* READ_DIRECTORIES */
     if (localVersion == 3) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX
         if (CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework/"))) {
             if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
             else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase2)) localVersion = 2;
@@ -1690,10 +1823,22 @@ __private_extern__ Boolean _CFBundleURLLooksLikeBundleVersion(CFURLRef url, uint
             else if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
             else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase1)) localVersion = 1;
         }
+#elif DEPLOYMENT_TARGET_WINDOWS
+        if (CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework\\"))) {
+            if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
+            else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase2)) localVersion = 2;
+            else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase1)) localVersion = 1;
+        } else {
+            if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase2)) localVersion = 2;
+            else if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
+            else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase1)) localVersion = 1;
+        }
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     }
     if (version) *version = localVersion;
-    return !(localVersion == 3);
+    return (localVersion != 3);
 }
 
 __private_extern__ CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectory(CFAllocatorRef alloc, CFURLRef url, uint8_t *version) {
@@ -1753,35 +1898,18 @@ __private_extern__ CFDictionaryRef _CFBundleCopyInfoDictionaryInDirectoryWithVer
             infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension2;
             infoURLFromBase = _CFBundleInfoURLFromBase2;
         } else if (3 == version) {
-#if DEPLOYMENT_TARGET_MACOSX
-            CFStringRef posixPath = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+            CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
             // this test is necessary to exclude the case where a bundle is spuriously created from the innards of another bundle
-            if (posixPath) {
-                if (!(CFStringHasSuffix(posixPath, _CFBundleSupportFilesDirectoryName1) || CFStringHasSuffix(posixPath, _CFBundleSupportFilesDirectoryName2) || CFStringHasSuffix(posixPath, _CFBundleResourcesDirectoryName))) {
+            if (path) {
+                if (!(CFStringHasSuffix(path, _CFBundleSupportFilesDirectoryName1) || CFStringHasSuffix(path, _CFBundleSupportFilesDirectoryName2) || CFStringHasSuffix(path, _CFBundleResourcesDirectoryName))) {
 #if READ_DIRECTORIES
                     directoryURL = CFRetain(url);
 #endif /* READ_DIRECTORIES */    
                     infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension3;
                     infoURLFromBase = _CFBundleInfoURLFromBase3;
                 }
-                CFRelease(posixPath);
+                CFRelease(path);
             }
-#elif 0
-            CFStringRef windowsPath = CFURLCopyFileSystemPath(url, kCFURLWindowsPathStyle);
-            // this test is necessary to exclude the case where a bundle is spuriously created from the innards of another bundle
-            if (windowsPath) {
-                if (!(CFStringHasSuffix(windowsPath, _CFBundleSupportFilesDirectoryName1) || CFStringHasSuffix(windowsPath, _CFBundleSupportFilesDirectoryName2) || CFStringHasSuffix(windowsPath, _CFBundleResourcesDirectoryName))) {
-#if READ_DIRECTORIES
-                    directoryURL = CFRetain(url);
-#endif /* READ_DIRECTORIES */    
-                    infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension3;
-                    infoURLFromBase = _CFBundleInfoURLFromBase3;
-                }
-                CFRelease(windowsPath);
-            }
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
         }
 #if READ_DIRECTORIES
         if (directoryURL) {
@@ -1933,19 +2061,19 @@ static Boolean _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(CFAllocatorR
                 CFStringGetCharacters(urlStr, CFRangeMake(0, strLen), buff);
                 CFRelease(urlStr);
                 startOfExtension = _CFStartOfPathExtension(buff, strLen);
-                if (((strLen - startOfExtension == 4) || (strLen - startOfExtension == 5)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'a') && (buff[startOfExtension+2] == (UniChar)'p') && (buff[startOfExtension+3] == (UniChar)'p') && ((strLen - startOfExtension == 4) || (buff[startOfExtension+4] == (UniChar)'/'))) {
+                if ((strLen - startOfExtension == 4 || strLen - startOfExtension == 5) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'a' && buff[startOfExtension+2] == (UniChar)'p' && buff[startOfExtension+3] == (UniChar)'p' && (strLen - startOfExtension == 4 || buff[startOfExtension+4] == (UniChar)'/')) {
                     // This is an app
                     *packageType = 0x4150504c;  // 'APPL'
-                } else if (((strLen - startOfExtension == 6) || (strLen - startOfExtension == 7)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'d') && (buff[startOfExtension+2] == (UniChar)'e') && (buff[startOfExtension+3] == (UniChar)'b') && (buff[startOfExtension+4] == (UniChar)'u') && (buff[startOfExtension+5] == (UniChar)'g') && ((strLen - startOfExtension == 6) || (buff[startOfExtension+6] == (UniChar)'/'))) {
+                } else if ((strLen - startOfExtension == 6 || strLen - startOfExtension == 7) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'d' && buff[startOfExtension+2] == (UniChar)'e' && buff[startOfExtension+3] == (UniChar)'b' && buff[startOfExtension+4] == (UniChar)'u' && buff[startOfExtension+5] == (UniChar)'g' && (strLen - startOfExtension == 6 || buff[startOfExtension+6] == (UniChar)'/')) {
                     // This is an app (debug version)
                     *packageType = 0x4150504c;  // 'APPL'
-                } else if (((strLen - startOfExtension == 8) || (strLen - startOfExtension == 9)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'p') && (buff[startOfExtension+2] == (UniChar)'r') && (buff[startOfExtension+3] == (UniChar)'o') && (buff[startOfExtension+4] == (UniChar)'f') && (buff[startOfExtension+5] == (UniChar)'i') && (buff[startOfExtension+6] == (UniChar)'l') && (buff[startOfExtension+7] == (UniChar)'e') && ((strLen - startOfExtension == 8) || (buff[startOfExtension+8] == (UniChar)'/'))) {
+                } else if ((strLen - startOfExtension == 8 || strLen - startOfExtension == 9) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'p' && buff[startOfExtension+2] == (UniChar)'r' && buff[startOfExtension+3] == (UniChar)'o' && buff[startOfExtension+4] == (UniChar)'f' && buff[startOfExtension+5] == (UniChar)'i' && buff[startOfExtension+6] == (UniChar)'l' && buff[startOfExtension+7] == (UniChar)'e' && (strLen - startOfExtension == 8 || buff[startOfExtension+8] == (UniChar)'/')) {
                     // This is an app (profile version)
                     *packageType = 0x4150504c;  // 'APPL'
-                } else if (((strLen - startOfExtension == 8) || (strLen - startOfExtension == 9)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'s') && (buff[startOfExtension+2] == (UniChar)'e') && (buff[startOfExtension+3] == (UniChar)'r') && (buff[startOfExtension+4] == (UniChar)'v') && (buff[startOfExtension+5] == (UniChar)'i') && (buff[startOfExtension+6] == (UniChar)'c') && (buff[startOfExtension+7] == (UniChar)'e') && ((strLen - startOfExtension == 8) || (buff[startOfExtension+8] == (UniChar)'/'))) {
+                } else if ((strLen - startOfExtension == 8 || strLen - startOfExtension == 9) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'s' && buff[startOfExtension+2] == (UniChar)'e' && buff[startOfExtension+3] == (UniChar)'r' && buff[startOfExtension+4] == (UniChar)'v' && buff[startOfExtension+5] == (UniChar)'i' && buff[startOfExtension+6] == (UniChar)'c' && buff[startOfExtension+7] == (UniChar)'e' && (strLen - startOfExtension == 8 || buff[startOfExtension+8] == (UniChar)'/')) {
                     // This is a service
                     *packageType = 0x4150504c;  // 'APPL'
-                } else if (((strLen - startOfExtension == 10) || (strLen - startOfExtension == 11)) && (buff[startOfExtension] == (UniChar)'.') && (buff[startOfExtension+1] == (UniChar)'f') && (buff[startOfExtension+2] == (UniChar)'r') && (buff[startOfExtension+3] == (UniChar)'a') && (buff[startOfExtension+4] == (UniChar)'m') && (buff[startOfExtension+5] == (UniChar)'e') && (buff[startOfExtension+6] == (UniChar)'w') && (buff[startOfExtension+7] == (UniChar)'o') && (buff[startOfExtension+8] == (UniChar)'r') && (buff[startOfExtension+9] == (UniChar)'k') && ((strLen - startOfExtension == 10) || (buff[startOfExtension+10] == (UniChar)'/'))) {
+                } else if ((strLen - startOfExtension == 10 || strLen - startOfExtension == 11) && buff[startOfExtension] == (UniChar)'.' && buff[startOfExtension+1] == (UniChar)'f' && buff[startOfExtension+2] == (UniChar)'r' && buff[startOfExtension+3] == (UniChar)'a' && buff[startOfExtension+4] == (UniChar)'m' && buff[startOfExtension+5] == (UniChar)'e' && buff[startOfExtension+6] == (UniChar)'w' && buff[startOfExtension+7] == (UniChar)'o' && buff[startOfExtension+8] == (UniChar)'r' && buff[startOfExtension+9] == (UniChar)'k' && (strLen - startOfExtension == 10 || buff[startOfExtension+10] == (UniChar)'/')) {
                     // This is a framework
                     *packageType = 0x464d574b;  // 'FMWK'
                 } else {
@@ -1959,7 +2087,9 @@ static Boolean _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(CFAllocatorR
     return retVal;
 }
 
-CF_EXPORT Boolean _CFBundleGetPackageInfoInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) {return _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(alloc, url, NULL, packageType, packageCreator);}
+CF_EXPORT Boolean _CFBundleGetPackageInfoInDirectory(CFAllocatorRef alloc, CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) {
+    return _CFBundleGetPackageInfoInDirectoryWithInfoDictionary(alloc, url, NULL, packageType, packageCreator);
+}
 
 CF_EXPORT void CFBundleGetPackageInfo(CFBundleRef bundle, UInt32 *packageType, UInt32 *packageCreator) {
     CFURLRef bundleURL = CFBundleCopyBundleURL(bundle);
@@ -1970,11 +2100,96 @@ CF_EXPORT void CFBundleGetPackageInfo(CFBundleRef bundle, UInt32 *packageType, U
     if (bundleURL) CFRelease(bundleURL);
 }
 
-CF_EXPORT Boolean CFBundleGetPackageInfoInDirectory(CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) {return _CFBundleGetPackageInfoInDirectory(kCFAllocatorSystemDefault, url, packageType, packageCreator);}
+CF_EXPORT Boolean CFBundleGetPackageInfoInDirectory(CFURLRef url, UInt32 *packageType, UInt32 *packageCreator) {
+    return _CFBundleGetPackageInfoInDirectory(kCFAllocatorSystemDefault, url, packageType, packageCreator);
+}
 
-__private_extern__ CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(void) {
+static void _CFBundleCheckSupportedPlatform(CFMutableArrayRef mutableArray, UniChar *buff, CFIndex startLen, CFStringRef platformName, CFStringRef platformIdentifier) {
+    CFIndex buffLen = startLen, platformLen = CFStringGetLength(platformName), extLen = CFStringGetLength(_CFBundleInfoExtension);
+    CFMutableStringRef str;
+    Boolean isDir;
+    if (buffLen + platformLen + extLen < CFMaxPathSize) {
+        CFStringGetCharacters(platformName, CFRangeMake(0, platformLen), buff + buffLen);
+        buffLen += platformLen;
+        buff[buffLen++] = (UniChar)'.';
+        CFStringGetCharacters(_CFBundleInfoExtension, CFRangeMake(0, extLen), buff + buffLen);
+        buffLen += extLen;
+        str = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+        CFStringAppendCharacters(str, buff, buffLen);
+        if (_CFIsResourceAtPath(str, &isDir) && !isDir && CFArrayGetFirstIndexOfValue(mutableArray, CFRangeMake(0, CFArrayGetCount(mutableArray)), platformIdentifier) < 0) CFArrayAppendValue(mutableArray, platformIdentifier);
+        CFRelease(str);
+    }
+}
+
+CF_EXPORT CFArrayRef _CFBundleGetSupportedPlatforms(CFBundleRef bundle) {
+    CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
+    CFArrayRef platformArray = infoDict ? (CFArrayRef)CFDictionaryGetValue(infoDict, _kCFBundleSupportedPlatformsKey) : NULL;
+    if (platformArray && CFGetTypeID(platformArray) != CFArrayGetTypeID()) {
+        platformArray = NULL;
+        CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, _kCFBundleSupportedPlatformsKey);
+    }
+    if (!platformArray) {
+        CFURLRef infoPlistURL = infoDict ? (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleInfoPlistURLKey) : NULL, absoluteURL;
+        CFStringRef infoPlistPath;
+        UniChar buff[CFMaxPathSize];
+        CFIndex buffLen, infoLen = CFStringGetLength(_CFBundleInfoURLFromBaseNoExtension3), startLen, extLen = CFStringGetLength(_CFBundleInfoExtension);
+        if (infoPlistURL) {
+            CFMutableArrayRef mutableArray = CFArrayCreateMutable(CFGetAllocator(bundle), 0, &kCFTypeArrayCallBacks);
+            absoluteURL = CFURLCopyAbsoluteURL(infoPlistURL);
+            infoPlistPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
+            CFRelease(absoluteURL);
+            buffLen = CFStringGetLength(infoPlistPath);
+            if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
+            CFStringGetCharacters(infoPlistPath, CFRangeMake(0, buffLen), buff);
+            CFRelease(infoPlistPath);
+            if (buffLen > 0) {
+                buffLen = _CFStartOfLastPathComponent(buff, buffLen);
+                if (buffLen > 0 && buffLen + infoLen + extLen < CFMaxPathSize) {
+                    CFStringGetCharacters(_CFBundleInfoURLFromBaseNoExtension3, CFRangeMake(0, infoLen), buff + buffLen);
+                    buffLen += infoLen;
+                    buff[buffLen++] = (UniChar)'-';
+                    startLen = buffLen;
+                    _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("macos"), CFSTR("MacOS"));
+                    _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("macosx"), CFSTR("MacOS"));
+                    _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("iphoneos"), CFSTR("iPhoneOS"));
+                    _CFBundleCheckSupportedPlatform(mutableArray, buff, startLen, CFSTR("windows"), CFSTR("Windows"));
+                }
+            }
+            if (CFArrayGetCount(mutableArray) > 0) {
+                platformArray = (CFArrayRef)mutableArray;
+                CFDictionarySetValue((CFMutableDictionaryRef)infoDict, _kCFBundleSupportedPlatformsKey, platformArray);
+            }
+            CFRelease(mutableArray);
+        }
+    }
+    return platformArray;
+}
+
+CF_EXPORT CFStringRef _CFBundleGetCurrentPlatform(void) {
 #if DEPLOYMENT_TARGET_MACOSX
     return CFSTR("MacOS");
+#elif DEPLOYMENT_TARGET_EMBEDDED
+    return CFSTR("iPhoneOS");
+#elif DEPLOYMENT_TARGET_WINDOWS
+    return CFSTR("Windows");
+#elif DEPLOYMENT_TARGET_SOLARIS
+    return CFSTR("Solaris");
+#elif DEPLOYMENT_TARGET_HPUX
+    return CFSTR("HPUX");
+#elif DEPLOYMENT_TARGET_LINUX
+    return CFSTR("Linux");
+#elif DEPLOYMENT_TARGET_FREEBSD
+    return CFSTR("FreeBSD");
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+}
+
+__private_extern__ CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    return CFSTR("MacOS");
+#elif DEPLOYMENT_TARGET_WINDOWS
+    return CFSTR("Windows");
 #elif DEPLOYMENT_TARGET_SOLARIS
     return CFSTR("Solaris");
 #elif DEPLOYMENT_TARGET_HPUX
@@ -1989,8 +2204,10 @@ __private_extern__ CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(v
 }
 
 __private_extern__ CFStringRef _CFBundleGetAlternatePlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     return CFSTR("Mac OS X");
+#elif DEPLOYMENT_TARGET_WINDOWS
+    return CFSTR("WinNT");
 #elif DEPLOYMENT_TARGET_SOLARIS
     return CFSTR("Solaris");
 #elif DEPLOYMENT_TARGET_HPUX
@@ -2005,8 +2222,10 @@ __private_extern__ CFStringRef _CFBundleGetAlternatePlatformExecutablesSubdirect
 }
 
 __private_extern__ CFStringRef _CFBundleGetOtherPlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     return CFSTR("MacOSClassic");
+#elif DEPLOYMENT_TARGET_WINDOWS
+    return CFSTR("Other");
 #elif DEPLOYMENT_TARGET_HPUX
     return CFSTR("Other");
 #elif DEPLOYMENT_TARGET_SOLARIS
@@ -2021,8 +2240,10 @@ __private_extern__ CFStringRef _CFBundleGetOtherPlatformExecutablesSubdirectoryN
 }
 
 __private_extern__ CFStringRef _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     return CFSTR("Mac OS 8");
+#elif DEPLOYMENT_TARGET_WINDOWS
+    return CFSTR("Other");
 #elif DEPLOYMENT_TARGET_HPUX
     return CFSTR("Other");
 #elif DEPLOYMENT_TARGET_SOLARIS
@@ -2036,7 +2257,9 @@ __private_extern__ CFStringRef _CFBundleGetOtherAlternatePlatformExecutablesSubd
 #endif
 }
 
-__private_extern__ CFArrayRef _CFBundleCopyBundleRegionsArray(CFBundleRef bundle) {return CFBundleCopyBundleLocalizations(bundle);}
+__private_extern__ CFArrayRef _CFBundleCopyBundleRegionsArray(CFBundleRef bundle) {
+    return CFBundleCopyBundleLocalizations(bundle);
+}
 
 CF_EXPORT CFArrayRef CFBundleCopyBundleLocalizations(CFBundleRef bundle) {
     CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
@@ -2122,7 +2345,6 @@ CF_EXPORT CFArrayRef CFBundleCopyBundleLocalizations(CFBundleRef bundle) {
         }
     }
     if (resourcesURL) CFRelease(resourcesURL);
-
     return result;
 }
 
index a56cb161a4dabf55847fb672047732273c5c5fb4..89045b319b91ff35b688de790a9880eb9d3be249 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFByteOrder.h
-       Copyright (c) 1995-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1995-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFBYTEORDER__)
 #define __COREFOUNDATION_CFBYTEORDER__ 1
 
 #include <CoreFoundation/CFBase.h>
-#if defined(__MACH__) && !defined(CF_USE_OSBYTEORDER_H)
+#if ((TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) && !defined(CF_USE_OSBYTEORDER_H)
 #include <libkern/OSByteOrder.h>
 #define CF_USE_OSBYTEORDER_H 1
 #endif
index b7ee551217d1248de55d4e9801d36b98173eb4c2..33b58b6e8c8555b0d33e90a841630e7a0ade1863 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -25,6 +25,8 @@
        Responsibility: Christopher Kane
 */
 
+
+
 #include <CoreFoundation/CFCalendar.h>
 #include <CoreFoundation/CFRuntime.h>
 #include "CFInternal.h"
@@ -1044,6 +1046,7 @@ Boolean CFCalendarGetTimeRangeOfUnit(CFCalendarRef calendar, CFCalendarUnit unit
            return true;
        }
     }
+
     return false;
 }
 
index b8673064374447ca15d4030fdf3ae67fe518b87a..c6179fb28f4f8e636e561319f276d3680aa611bb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFCalendar.h
-       Copyright (c) 2004-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2004-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFCALENDAR__)
@@ -79,16 +79,19 @@ void CFCalendarSetMinimumDaysInFirstWeek(CFCalendarRef calendar, CFIndex mwd) AV
 
 
 enum {
-       kCFCalendarUnitEra = (1 << 1),
-       kCFCalendarUnitYear = (1 << 2),
-       kCFCalendarUnitMonth = (1 << 3),
-       kCFCalendarUnitDay = (1 << 4),
-       kCFCalendarUnitHour = (1 << 5),
-       kCFCalendarUnitMinute = (1 << 6),
-       kCFCalendarUnitSecond = (1 << 7),
-       kCFCalendarUnitWeek = (1 << 8),
-       kCFCalendarUnitWeekday = (1 << 9),
-       kCFCalendarUnitWeekdayOrdinal = (1 << 10)
+       kCFCalendarUnitEra = (1UL << 1),
+       kCFCalendarUnitYear = (1UL << 2),
+       kCFCalendarUnitMonth = (1UL << 3),
+       kCFCalendarUnitDay = (1UL << 4),
+       kCFCalendarUnitHour = (1UL << 5),
+       kCFCalendarUnitMinute = (1UL << 6),
+       kCFCalendarUnitSecond = (1UL << 7),
+       kCFCalendarUnitWeek = (1UL << 8),
+       kCFCalendarUnitWeekday = (1UL << 9),
+       kCFCalendarUnitWeekdayOrdinal = (1UL << 10),
+#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED
+       kCFCalendarUnitQuarter = (1UL << 11),
+#endif
 };
 typedef CFOptionFlags CFCalendarUnit;
 
@@ -115,7 +118,7 @@ Boolean CFCalendarDecomposeAbsoluteTime(CFCalendarRef calendar, CFAbsoluteTime a
 
 
 enum {
-    kCFCalendarComponentsWrap = (1 << 0)  // option for adding
+    kCFCalendarComponentsWrap = (1UL << 0)  // option for adding
 };
 
 CF_EXPORT
index 49c0c658d3faa33d23941284e63d5b96b144ab4b..0daf28af64af35dfa3c4cef1a626df281def6a01 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFCharacterSet.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Aki Inoue
 */
 
@@ -31,7 +31,7 @@
 #include <CoreFoundation/CFData.h>
 #include <CoreFoundation/CFString.h>
 #include "CFInternal.h"
-#include "CFUniChar.h"
+#include <CoreFoundation/CFUniChar.h>
 #include "CFUniCharPriv.h"
 #include <stdlib.h>
 #include <string.h>
@@ -499,7 +499,7 @@ static void __CFCheckForExpandedSet(CFCharacterSetRef cset) {
     static bool warnedOnce = false;
 
     if (0 > __CFNumberOfPlanesForLogging) {
-        const char *envVar = getenv("CFCharacterSetCheckForExpandedSet");
+        const char *envVar = __CFgetenv("CFCharacterSetCheckForExpandedSet");
         long value = (envVar ? strtol_l(envVar, NULL, 0, NULL) : 0);
         __CFNumberOfPlanesForLogging = (int8_t)(((value > 0) && (value <= 16)) ? value : 0);
     }
@@ -834,6 +834,40 @@ CF_INLINE CFMutableCharacterSetRef __CFCSetGenericCreate(CFAllocatorRef allocato
     return cset;
 }
 
+static void __CFApplySurrogatesInString(CFMutableCharacterSetRef cset, CFStringRef string, void (*applyer)(CFMutableCharacterSetRef, CFRange)) {
+    CFStringInlineBuffer buffer;
+    CFIndex index, length = CFStringGetLength(string);
+    CFRange range = CFRangeMake(0, 0);
+    UTF32Char character;
+
+    CFStringInitInlineBuffer(string, &buffer, CFRangeMake(0, length));
+
+    for (index = 0;index < length;index++) {
+       character = __CFStringGetCharacterFromInlineBufferQuick(&buffer, index);
+
+       if (CFStringIsSurrogateHighCharacter(character) && ((index + 1) < length)) {
+           UTF16Char other = __CFStringGetCharacterFromInlineBufferQuick(&buffer, index + 1);
+
+           if (CFStringIsSurrogateLowCharacter(other)) {
+               character = CFStringGetLongCharacterForSurrogatePair(character, other);
+
+               if ((range.length + range.location) == character) {
+                   ++range.length;
+               } else {
+                   if (range.length > 0) applyer(cset, range);
+                   range.location = character;
+                   range.length = 1;
+               }
+           }
+
+           ++index; // skip the low surrogate
+       }
+    }
+
+    if (range.length > 0) applyer(cset, range);
+}
+
+
 /* Bsearch theChar for __kCFCharSetClassString
 */
 CF_INLINE Boolean __CFCSetBsearchUniChar(const UniChar *theTable, CFIndex length, UniChar theChar) {
@@ -852,27 +886,6 @@ CF_INLINE Boolean __CFCSetBsearchUniChar(const UniChar *theTable, CFIndex length
     return false;
 }
 
-/* Predefined cset names
- Need to add entry here for new builtin types
-*/
-CONST_STRING_DECL(__kCFCSetNameControl, "<CFCharacterSet Predefined Control Set>")
-CONST_STRING_DECL(__kCFCSetNameWhitespace, "<CFCharacterSet Predefined Whitespace Set>")
-CONST_STRING_DECL(__kCFCSetNameWhitespaceAndNewline, "<CFCharacterSet Predefined WhitespaceAndNewline Set>")
-CONST_STRING_DECL(__kCFCSetNameDecimalDigit, "<CFCharacterSet Predefined DecimalDigit Set>")
-CONST_STRING_DECL(__kCFCSetNameLetter, "<CFCharacterSet Predefined Letter Set>")
-CONST_STRING_DECL(__kCFCSetNameLowercaseLetter, "<CFCharacterSet Predefined LowercaseLetter Set>")
-CONST_STRING_DECL(__kCFCSetNameUppercaseLetter, "<CFCharacterSet Predefined UppercaseLetter Set>")
-CONST_STRING_DECL(__kCFCSetNameNonBase, "<CFCharacterSet Predefined NonBase Set>")
-CONST_STRING_DECL(__kCFCSetNameDecomposable, "<CFCharacterSet Predefined Decomposable Set>")
-CONST_STRING_DECL(__kCFCSetNameAlphaNumeric, "<CFCharacterSet Predefined AlphaNumeric Set>")
-CONST_STRING_DECL(__kCFCSetNamePunctuation, "<CFCharacterSet Predefined Punctuation Set>")
-CONST_STRING_DECL(__kCFCSetNameIllegal, "<CFCharacterSet Predefined Illegal Set>")
-CONST_STRING_DECL(__kCFCSetNameCapitalizedLetter, "<CFCharacterSet Predefined CapitalizedLetter Set>")
-CONST_STRING_DECL(__kCFCSetNameSymbol, "<CFCharacterSet Predefined Symbol Set>")
-CONST_STRING_DECL(__kCFCSetNameNewline, "<CFCharacterSet Predefined Newline Set>")
-
-CONST_STRING_DECL(__kCFCSetNameStringTypeFormat, "<CFCharacterSet Items(")
-
 /* Array of instantiated builtin set. Note builtin set ID starts with 1 so the array index is ID - 1
 */
 static CFCharacterSetRef *__CFBuiltinSets = NULL;
@@ -1198,36 +1211,39 @@ static CFStringRef  __CFCharacterSetCopyDescription(CFTypeRef cf) {
     switch (__CFCSetClassType((CFCharacterSetRef)cf)) {
         case __kCFCharSetClassBuiltin:
             switch (__CFCSetBuiltinType((CFCharacterSetRef)cf)) {
-                case kCFCharacterSetControl: return (CFStringRef)CFRetain(__kCFCSetNameControl);
-                case kCFCharacterSetWhitespace : return (CFStringRef)CFRetain(__kCFCSetNameWhitespace);
-                case kCFCharacterSetWhitespaceAndNewline: return (CFStringRef)CFRetain(__kCFCSetNameWhitespaceAndNewline);
-                case kCFCharacterSetDecimalDigit: return (CFStringRef)CFRetain(__kCFCSetNameDecimalDigit);
-                case kCFCharacterSetLetter: return (CFStringRef)CFRetain(__kCFCSetNameLetter);
-                case kCFCharacterSetLowercaseLetter: return (CFStringRef)CFRetain(__kCFCSetNameLowercaseLetter);
-                case kCFCharacterSetUppercaseLetter: return (CFStringRef)CFRetain(__kCFCSetNameUppercaseLetter);
-                case kCFCharacterSetNonBase: return (CFStringRef)CFRetain(__kCFCSetNameNonBase);
-                case kCFCharacterSetDecomposable: return (CFStringRef)CFRetain(__kCFCSetNameDecomposable);
-                case kCFCharacterSetAlphaNumeric: return (CFStringRef)CFRetain(__kCFCSetNameAlphaNumeric);
-                case kCFCharacterSetPunctuation: return (CFStringRef)CFRetain(__kCFCSetNamePunctuation);
-                case kCFCharacterSetIllegal: return (CFStringRef)CFRetain(__kCFCSetNameIllegal);
-                case kCFCharacterSetCapitalizedLetter: return (CFStringRef)CFRetain(__kCFCSetNameCapitalizedLetter);
-                case kCFCharacterSetSymbol: return (CFStringRef)CFRetain(__kCFCSetNameSymbol);
-                case kCFCharacterSetNewline: return (CFStringRef)CFRetain(__kCFCSetNameNewline);
+                case kCFCharacterSetControl: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined Control Set>"));
+                case kCFCharacterSetWhitespace : return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined Whitespace Set>"));
+                case kCFCharacterSetWhitespaceAndNewline: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined WhitespaceAndNewline Set>"));
+                case kCFCharacterSetDecimalDigit: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined DecimalDigit Set>"));
+                case kCFCharacterSetLetter: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined Letter Set>"));
+                case kCFCharacterSetLowercaseLetter: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined LowercaseLetter Set>"));
+                case kCFCharacterSetUppercaseLetter: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined UppercaseLetter Set>"));
+                case kCFCharacterSetNonBase: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined NonBase Set>"));
+                case kCFCharacterSetDecomposable: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined Decomposable Set>"));
+                case kCFCharacterSetAlphaNumeric: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined AlphaNumeric Set>"));
+                case kCFCharacterSetPunctuation: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined Punctuation Set>"));
+                case kCFCharacterSetIllegal: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined Illegal Set>"));
+                case kCFCharacterSetCapitalizedLetter: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined CapitalizedLetter Set>"));
+                case kCFCharacterSetSymbol: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined Symbol Set>"));
+                case kCFCharacterSetNewline: return (CFStringRef)CFRetain(CFSTR("<CFCharacterSet Predefined Newline Set>"));
             }
             break;
 
         case __kCFCharSetClassRange:
             return CFStringCreateWithFormat(CFGetAllocator((CFCharacterSetRef)cf), NULL, CFSTR("<CFCharacterSet Range(%d, %d)>"), __CFCSetRangeFirstChar((CFCharacterSetRef)cf), __CFCSetRangeLength((CFCharacterSetRef)cf));
 
-        case __kCFCharSetClassString:
+        case __kCFCharSetClassString: {
+            CFStringRef format = CFSTR("<CFCharacterSet Items(");
+
             length = __CFCSetStringLength((CFCharacterSetRef)cf);
-            string = CFStringCreateMutable(CFGetAllocator(cf), CFStringGetLength(__kCFCSetNameStringTypeFormat) + 7 * length + 2); // length of__kCFCSetNameStringTypeFormat + "U+XXXX "(7) * length + ")>"(2)
-            CFStringAppend(string, __kCFCSetNameStringTypeFormat);
+            string = CFStringCreateMutable(CFGetAllocator(cf), CFStringGetLength(format) + 7 * length + 2); // length of format + "U+XXXX "(7) * length + ")>"(2)
+            CFStringAppend(string, format);
             for (idx = 0;idx < length;idx++) {
                 CFStringAppendFormat(string, NULL, CFSTR("%sU+%04X"), (idx > 0 ? " " : ""), (UInt32)((__CFCSetStringBuffer((CFCharacterSetRef)cf))[idx]));
             }
             CFStringAppend(string, CFSTR(")>"));
             return string;
+        }
 
         case __kCFCharSetClassBitmap:
         case __kCFCharSetClassCompactBitmap:
@@ -1271,7 +1287,7 @@ static const CFRuntimeClass __CFCharacterSetClass = {
 static bool __CFCheckForExapendedSet = false;
 
 __private_extern__ void __CFCharacterSetInitialize(void) {
-    const char *checkForExpandedSet = getenv("__CF_DEBUG_EXPANDED_SET");
+    const char *checkForExpandedSet = __CFgetenv("__CF_DEBUG_EXPANDED_SET");
 
     __kCFCharacterSetTypeID = _CFRuntimeRegisterClass(&__CFCharacterSetClass);
 
@@ -1348,15 +1364,32 @@ CFCharacterSetRef CFCharacterSetCreateWithCharactersInString(CFAllocatorRef allo
         __CFCSetPutStringLength(cset, length);
         CFStringGetCharacters(theString, CFRangeMake(0, length), __CFCSetStringBuffer(cset));
         qsort(__CFCSetStringBuffer(cset), length, sizeof(UniChar), chcompar);
-        if (!length) __CFCSetPutHasHashValue(cset, true); // _hashValue is 0
-        return cset;
-    } else {
-        CFMutableCharacterSetRef mcset = CFCharacterSetCreateMutable(allocator);
-        CFCharacterSetAddCharactersInString(mcset, theString);
-        __CFCSetMakeCompact(mcset);
-        __CFCSetPutIsMutable(mcset, false);
-        return mcset;
+
+        if (0 == length) {
+           __CFCSetPutHasHashValue(cset, true); // _hashValue is 0
+       } else if (length > 1) { // Check for surrogate
+           const UTF16Char *characters = __CFCSetStringBuffer(cset);
+           const UTF16Char *charactersLimit = characters + length;
+
+           if ((*characters < 0xDC00UL) && (*(charactersLimit - 1) > 0xDBFFUL)) { // might have surrogate chars
+               while (characters < charactersLimit) {
+                   if (CFStringIsSurrogateHighCharacter(*characters) || CFStringIsSurrogateLowCharacter(*characters)) {
+                       CFRelease(cset);
+                       cset = NULL;
+                       break;
+                   }
+                   ++characters;
+               }
+           }           
+       }
+       if (NULL != cset) return cset;
     }
+
+    CFMutableCharacterSetRef mcset = CFCharacterSetCreateMutable(allocator);
+    CFCharacterSetAddCharactersInString(mcset, theString);
+    __CFCSetMakeCompact(mcset);
+    __CFCSetPutIsMutable(mcset, false);
+    return mcset;
 }
 
 CFCharacterSetRef CFCharacterSetCreateWithBitmapRepresentation(CFAllocatorRef allocator, CFDataRef theData) {
@@ -1470,7 +1503,7 @@ CFMutableCharacterSetRef CFCharacterSetCreateMutable(CFAllocatorRef allocator) {
     return cset;
 }
 
-CFMutableCharacterSetRef __CFCharacterSetCreateCopy(CFAllocatorRef alloc, CFCharacterSetRef theSet, bool isMutable) {
+static CFMutableCharacterSetRef __CFCharacterSetCreateCopy(CFAllocatorRef alloc, CFCharacterSetRef theSet, bool isMutable) {
     CFMutableCharacterSetRef cset;
 
     CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFMutableCharacterSetRef , theSet, "mutableCopy");
@@ -1551,7 +1584,6 @@ CFMutableCharacterSetRef __CFCharacterSetCreateCopy(CFAllocatorRef alloc, CFChar
         }
         __CFCSetAnnexSetIsInverted(cset, __CFCSetAnnexIsInverted(theSet));
     } else if (__CFCSetAnnexIsInverted(theSet)) {
-        __CFCSetAllocateAnnexForPlane(cset, 0); // We need to alloc annex to invert
         __CFCSetAnnexSetIsInverted(cset, true);
     }
     
@@ -1734,8 +1766,8 @@ Boolean CFCharacterSetIsSupersetOfSet(CFCharacterSetRef theSet, CFCharacterSetRe
                 uint8_t theOtherSetBuffer[__kCFBitmapSize];
 
                 // We mask plane 1 to plane 16
-                if (isTheSetAnnexInverted) theSetAnnexMask = (~theSetAnnexMask) & (0xFFFF < 1);
-                if (isTheOtherSetAnnexInverted) theOtherSetAnnexMask = (~theOtherSetAnnexMask) & (0xFFFF < 1);
+                if (isTheSetAnnexInverted) theSetAnnexMask = (~theSetAnnexMask) & (0xFFFF << 1);
+                if (isTheOtherSetAnnexInverted) theOtherSetAnnexMask = (~theOtherSetAnnexMask) & (0xFFFF << 1);
 
                 __CFCSetGetBitmap(theSet, theSetBuffer);
                 __CFCSetGetBitmap(theOtherSet, theOtherSetBuffer);
@@ -2146,8 +2178,9 @@ void CFCharacterSetRemoveCharactersInRange(CFMutableCharacterSetRef theSet, CFRa
 }
 
 void CFCharacterSetAddCharactersInString(CFMutableCharacterSetRef theSet,  CFStringRef theString) {
-    const UniChar *buffer;
+    UniChar *buffer;
     CFIndex length;
+    BOOL hasSurrogate = NO;
 
     CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "addCharactersInString:", theString);
 
@@ -2159,42 +2192,79 @@ void CFCharacterSetAddCharactersInString(CFMutableCharacterSetRef theSet,  CFStr
         CFIndex newLength = length + (__CFCSetIsEmpty(theSet) ? 0 : (__CFCSetIsString(theSet) ? __CFCSetStringLength(theSet) : __kCFStringCharSetMax));
 
         if (newLength < __kCFStringCharSetMax) {
-            if (__CFCSetIsEmpty(theSet)) {
-                __CFCSetPutClassType(theSet, __kCFCharSetClassString);
-                __CFCSetPutStringLength(theSet, 0); // Make sure to reset this
-            }
-            
-            if (!__CFCSetStringBuffer(theSet))
-                               __CFCSetPutStringBuffer(theSet, (UniChar *)CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), 0));
-            buffer = __CFCSetStringBuffer(theSet) + __CFCSetStringLength(theSet);
+           buffer = __CFCSetStringBuffer(theSet);
+
+           if (NULL == buffer) {
+               buffer = (UniChar *)CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), 0);
+           } else {
+               buffer += __CFCSetStringLength(theSet);
+           }
 
-            __CFCSetPutClassType(theSet, __kCFCharSetClassString);
-            __CFCSetPutStringLength(theSet, newLength);
             CFStringGetCharacters(theString, CFRangeMake(0, length), (UniChar*)buffer);
-            qsort(__CFCSetStringBuffer(theSet), newLength, sizeof(UniChar), chcompar);
+
+           if (length > 1) {
+               UTF16Char *characters = buffer;
+               const UTF16Char *charactersLimit = characters + length;
+               
+               while (characters < charactersLimit) {
+                   if (CFStringIsSurrogateHighCharacter(*characters) || CFStringIsSurrogateLowCharacter(*characters)) {
+                       memmove(characters, characters + 1, (charactersLimit - (characters + 1)) * sizeof(*characters));
+                       --charactersLimit;
+                       hasSurrogate = YES;
+                   } else {
+                       ++characters;
+                   }
+               }
+
+               newLength -= (length - (charactersLimit - buffer));
+           }
+
+           if (0 == newLength) {
+               if (NULL == __CFCSetStringBuffer(theSet)) CFAllocatorDeallocate(CFGetAllocator(theSet), buffer);
+           } else {
+               if (NULL == __CFCSetStringBuffer(theSet)) {
+                   __CFCSetPutClassType(theSet, __kCFCharSetClassString);
+                   __CFCSetPutStringBuffer(theSet, buffer);
+               }
+               __CFCSetPutStringLength(theSet, newLength);
+               qsort(__CFCSetStringBuffer(theSet), newLength, sizeof(UniChar), chcompar);
+           }
             __CFCSetPutHasHashValue(theSet, false);
+
+           if (hasSurrogate) __CFApplySurrogatesInString(theSet, theString, &CFCharacterSetAddCharactersInRange);
+
             return;
         }
     }
 
     // OK, I have to be a bitmap
     __CFCSetMakeBitmap(theSet);
-    if ((buffer = CFStringGetCharactersPtr(theString))) {
-        while (length--) __CFCSetBitmapAddCharacter(__CFCSetBitmapBits(theSet), *buffer++);
-    } else {
-        CFStringInlineBuffer inlineBuffer;
-        CFIndex idx;
+    CFStringInlineBuffer inlineBuffer;
+    CFIndex idx;
+    
+    CFStringInitInlineBuffer(theString, &inlineBuffer, CFRangeMake(0, length));
+
+    for (idx = 0;idx < length;idx++) {
+       UTF16Char character = __CFStringGetCharacterFromInlineBufferQuick(&inlineBuffer, idx);
 
-        CFStringInitInlineBuffer(theString, &inlineBuffer, CFRangeMake(0, length));
-        for (idx = 0;idx < length;idx++) __CFCSetBitmapAddCharacter(__CFCSetBitmapBits(theSet), __CFStringGetCharacterFromInlineBufferQuick(&inlineBuffer, idx));
+       if (CFStringIsSurrogateHighCharacter(character) || CFStringIsSurrogateLowCharacter(character)) {
+           hasSurrogate = YES;
+       } else {
+           __CFCSetBitmapAddCharacter(__CFCSetBitmapBits(theSet), character);
+       }
     }
+
     __CFCSetPutHasHashValue(theSet, false);
+
     if (__CFCheckForExapendedSet) __CFCheckForExpandedSet(theSet);
+
+    if (hasSurrogate) __CFApplySurrogatesInString(theSet, theString, &CFCharacterSetAddCharactersInRange);
 }
 
 void CFCharacterSetRemoveCharactersInString(CFMutableCharacterSetRef theSet, CFStringRef theString) {
-    const UniChar *buffer;
+    UniChar *buffer;
     CFIndex length;
+    BOOL hasSurrogate = NO;
 
     CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "removeCharactersInString:", theString);
 
@@ -2204,39 +2274,69 @@ void CFCharacterSetRemoveCharactersInString(CFMutableCharacterSetRef theSet, CFS
 
     if (__CFCSetIsInverted(theSet)) {
         CFIndex newLength = length + (__CFCSetIsEmpty(theSet) ? 0 : (__CFCSetIsString(theSet) ? __CFCSetStringLength(theSet) : __kCFStringCharSetMax));
-
+       
         if (newLength < __kCFStringCharSetMax) {
-            if (__CFCSetIsEmpty(theSet)) {
-                __CFCSetPutClassType(theSet, __kCFCharSetClassString);
-                __CFCSetPutStringLength(theSet, 0); // Make sure to reset this
-            }
-
-            if (!__CFCSetStringBuffer(theSet))
-                               __CFCSetPutStringBuffer(theSet, (UniChar *)CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), 0));
-            buffer = __CFCSetStringBuffer(theSet) + __CFCSetStringLength(theSet);
-
-            __CFCSetPutClassType(theSet, __kCFCharSetClassString);
+           buffer = __CFCSetStringBuffer(theSet);
+           
+           if (NULL == buffer) {
+               buffer = (UniChar *)CFAllocatorAllocate(CFGetAllocator(theSet), __kCFStringCharSetMax * sizeof(UniChar), 0);
+           } else {
+               buffer += __CFCSetStringLength(theSet);
+           }
+           
+            CFStringGetCharacters(theString, CFRangeMake(0, length), (UniChar*)buffer);
+           
+           if (length > 1) {
+               UTF16Char *characters = buffer;
+               const UTF16Char *charactersLimit = characters + length;
+               
+               while (characters < charactersLimit) {
+                   if (CFStringIsSurrogateHighCharacter(*characters) || CFStringIsSurrogateLowCharacter(*characters)) {
+                       memmove(characters, characters + 1, charactersLimit - (characters + 1));
+                       --charactersLimit;
+                       hasSurrogate = YES;
+                   }
+                   ++characters;
+               }
+               
+               newLength -= (length - (charactersLimit - buffer));
+           }
+           
+           if (NULL == __CFCSetStringBuffer(theSet)) {
+               __CFCSetPutClassType(theSet, __kCFCharSetClassString);
+               __CFCSetPutStringBuffer(theSet, buffer);
+           }
             __CFCSetPutStringLength(theSet, newLength);
-            CFStringGetCharacters(theString, CFRangeMake(0, length), (UniChar *)buffer);
             qsort(__CFCSetStringBuffer(theSet), newLength, sizeof(UniChar), chcompar);
             __CFCSetPutHasHashValue(theSet, false);
+           
+           if (hasSurrogate) __CFApplySurrogatesInString(theSet, theString, &CFCharacterSetRemoveCharactersInRange);
+           
             return;
         }
     }
 
     // OK, I have to be a bitmap
     __CFCSetMakeBitmap(theSet);
-    if ((buffer = CFStringGetCharactersPtr(theString))) {
-        while (length--) __CFCSetBitmapRemoveCharacter(__CFCSetBitmapBits(theSet), *buffer++);
-    } else {
-        CFStringInlineBuffer inlineBuffer;
-        CFIndex idx;
-
-        CFStringInitInlineBuffer(theString, &inlineBuffer, CFRangeMake(0, length));
-        for (idx = 0;idx < length;idx++) __CFCSetBitmapRemoveCharacter(__CFCSetBitmapBits(theSet), __CFStringGetCharacterFromInlineBufferQuick(&inlineBuffer, idx));
+    CFStringInlineBuffer inlineBuffer;
+    CFIndex idx;
+    
+    CFStringInitInlineBuffer(theString, &inlineBuffer, CFRangeMake(0, length));
+    
+    for (idx = 0;idx < length;idx++) {
+       UTF16Char character = __CFStringGetCharacterFromInlineBufferQuick(&inlineBuffer, idx);
+       
+       if (CFStringIsSurrogateHighCharacter(character) || CFStringIsSurrogateLowCharacter(character)) {
+           hasSurrogate = YES;
+       } else {
+           __CFCSetBitmapRemoveCharacter(__CFCSetBitmapBits(theSet), character);
+       }
     }
+    
     __CFCSetPutHasHashValue(theSet, false);
     if (__CFCheckForExapendedSet) __CFCheckForExpandedSet(theSet);
+
+    if (hasSurrogate) __CFApplySurrogatesInString(theSet, theString, &CFCharacterSetRemoveCharactersInRange);
 }
 
 void CFCharacterSetUnion(CFMutableCharacterSetRef theSet, CFCharacterSetRef theOtherSet) {
@@ -2269,6 +2369,8 @@ void CFCharacterSetUnion(CFMutableCharacterSetRef theSet, CFCharacterSetRef theO
         } else if (__CFCSetIsBuiltin(theOtherSet) && __CFCSetIsEmpty(theSet)) { // theSet can be builtin set
             __CFCSetPutClassType(theSet, __kCFCharSetClassBuiltin);
             __CFCSetPutBuiltinType(theSet, __CFCSetBuiltinType(theOtherSet));
+           if (__CFCSetIsInverted(theOtherSet)) __CFCSetPutIsInverted(theSet, true);
+           if (__CFCSetAnnexIsInverted(theOtherSet)) __CFCSetAnnexSetIsInverted(theSet, true);
             __CFCSetPutHasHashValue(theSet, false);
         } else {
             if (__CFCSetIsRange(theOtherSet)) {
@@ -2314,6 +2416,9 @@ void CFCharacterSetUnion(CFMutableCharacterSetRef theSet, CFCharacterSetRef theO
                         CFCharacterSetUnion((CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSet(theSet, idx), otherSetPlane);
                     }
                 }
+           } else if (__CFCSetAnnexIsInverted(theOtherSet)) {
+               if (__CFCSetHasNonBMPPlane(theSet)) __CFCSetDeallocateAnnexPlane(theSet);
+               __CFCSetAnnexSetIsInverted(theSet, true);
             } else if (__CFCSetIsBuiltin(theOtherSet)) {
                 CFMutableCharacterSetRef annexPlane;
                 uint8_t bitmapBuffer[__kCFBitmapSize];
@@ -2469,12 +2574,11 @@ void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef
                     }
                 }
                 if (!__CFCSetHasNonBMPPlane(theSet)) __CFCSetDeallocateAnnexPlane(theSet);
-            } else if (__CFCSetIsBuiltin(theOtherSet)) {
+            } else if (__CFCSetIsBuiltin(theOtherSet) && !__CFCSetAnnexIsInverted(theOtherSet)) {
                 CFMutableCharacterSetRef annexPlane;
                 uint8_t bitmapBuffer[__kCFBitmapSize];
                 uint8_t result;
                 int planeIndex;
-                Boolean isOtherAnnexPlaneInverted = __CFCSetAnnexIsInverted(theOtherSet);
                 UInt32 *bitmap1;
                 UInt32 *bitmap2;
                 CFIndex length;
@@ -2482,7 +2586,7 @@ void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef
                 for (planeIndex = 1;planeIndex <= MAX_ANNEX_PLANE;planeIndex++) {
                     annexPlane = (CFMutableCharacterSetRef)__CFCSetGetAnnexPlaneCharacterSetNoAlloc(theSet, planeIndex);
                     if (annexPlane) {
-                        result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(theOtherSet), planeIndex, bitmapBuffer, (isOtherAnnexPlaneInverted != 0));
+                        result = CFUniCharGetBitmapForPlane(__CFCSetBuiltinType(theOtherSet), planeIndex, bitmapBuffer, false);
                         if (result == kCFUniCharBitmapEmpty) {
                             __CFCSetPutCharacterSetToAnnexPlane(theSet, NULL, planeIndex);
                         } else if (result == kCFUniCharBitmapFilled) {
@@ -2520,7 +2624,7 @@ void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef
                 }
                 if (!__CFCSetHasNonBMPPlane(theSet)) __CFCSetDeallocateAnnexPlane(theSet);
                 CFRelease(tempOtherSet);
-            } else if (__CFCSetHasNonBMPPlane(theSet)) {
+            } else if ((__CFCSetHasNonBMPPlane(theSet) || __CFCSetAnnexIsInverted(theSet)) && !__CFCSetAnnexIsInverted(theOtherSet)) {
                 __CFCSetDeallocateAnnexPlane(theSet);
             }
         }
@@ -2618,6 +2722,8 @@ void CFCharacterSetFast(CFMutableCharacterSetRef theSet) {
 /* Keyed-coding support
 */
 CFCharacterSetKeyedCodingType _CFCharacterSetGetKeyedCodingType(CFCharacterSetRef cset) {
+    if (CF_IS_OBJC(__kCFCharacterSetTypeID, cset)) return kCFCharacterSetKeyedCodingTypeBitmap;
+
     switch (__CFCSetClassType(cset)) {
         case __kCFCharSetClassBuiltin: return ((__CFCSetBuiltinType(cset) < kCFCharacterSetSymbol) ? kCFCharacterSetKeyedCodingTypeBuiltin : kCFCharacterSetKeyedCodingTypeBuiltinAndBitmap);
         case __kCFCharSetClassRange: return kCFCharacterSetKeyedCodingTypeRange;
index 5b38c503a0ec0aceb2e0b41896ec781b7c6421a8..fe4adbe2dd80bb5e6c5325fa47b5a676ae2379c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFCharacterSet.h
-       Copyright (c) 1999-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
 */
 
 /*!
index b0874f9ea3e1d477ba24a7c60b08eea9d01c7154..f2c9794335515e5afdb5f54c155f82cd1237005d 100644 (file)
Binary files a/CFCharacterSetBitmaps.bitmap and b/CFCharacterSetBitmaps.bitmap differ
index bb36baed0a8040c0c625afd2fa7e3a84c4f95185..ea4a79669f66314447dc6c3f9e502f501404f745 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFCharacterSetPriv.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFCHARACTERSETPRIV__)
index e71ca102274d7f154bd7d3ec91425b5f9e553a48..50a1e4b24ea770e7fe60637214b06bd7bec996c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFConcreteStreams.c
-       Copyright 2000-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc. All rights reserved.
        Responsibility: Becky Willrich
 */
 
-#define _DARWIN_UNLIMITED_SELECT 1
-
 #include "CFStreamInternal.h"
 #include "CFInternal.h"
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include <CoreFoundation/CFNumber.h>
 #include <sys/types.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <string.h>
 #include <stdio.h>
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <sys/time.h>
 #include <unistd.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 // On Unix, you can schedule an fd with the RunLoop by creating a CFSocket around it.  On Win32
 // files and sockets are not interchangeable, and we do cheapo scheduling, where the file is
 // always readable and writable until we hit EOF (similar to the way CFData streams are scheduled).
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define REAL_FILE_SCHEDULING (1)
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 #define SCHEDULE_AFTER_WRITE  (0)
@@ -98,10 +102,18 @@ static void constructCFSocket(_CFFileStreamContext *fileStream, Boolean forRead,
 #endif
 
 static Boolean constructFD(_CFFileStreamContext *fileStream, CFStreamError *error, Boolean forRead, struct _CFStream *stream) {
-    UInt8 path[1024];
     int flags = forRead ? O_RDONLY : (O_CREAT | O_TRUNC | O_WRONLY);
-
-    if (CFURLGetFileSystemRepresentation(fileStream->url, TRUE, path, 1024) == FALSE) {
+#if DEPLOYMENT_TARGET_WINDOWS
+    wchar_t path[CFMaxPathSize];
+    flags |= (_O_BINARY|_O_NOINHERIT);
+    if (_CFURLGetWideFileSystemRepresentation(fileStream->url, TRUE, path, CFMaxPathSize) == FALSE)
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    char path[CFMaxPathSize];
+    if (CFURLGetFileSystemRepresentation(fileStream->url, TRUE, (UInt8 *)path, CFMaxPathSize) == FALSE)
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+     {
         error->error = ENOENT;
         error->domain = kCFStreamErrorDomainPOSIX;
         return FALSE;
@@ -112,8 +124,11 @@ static Boolean constructFD(_CFFileStreamContext *fileStream, CFStreamError *erro
     }
     
     do {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
         fileStream->fd = open((const char *)path, flags, 0666);
-        
+#elif DEPLOYMENT_TARGET_WINDOWS
+       fileStream->fd = _wopen(path, flags, 0666);
+#endif
         if (fileStream->fd < 0)
             break;
         
@@ -822,7 +837,7 @@ CF_EXPORT CFReadStreamRef CFReadStreamCreateWithData(CFAllocatorRef alloc, CFDat
     _CFReadDataStreamContext ctxt;
     CFReadStreamRef result = NULL;
     
-    ctxt.data = CFRetain(data);
+    ctxt.data = (CFDataRef)CFRetain(data);
     result = (CFReadStreamRef)_CFStreamCreateWithConstantCallbacks(alloc, &ctxt, (struct _CFStreamCallBacks *)(&readDataCallBacks), TRUE);
     CFRelease(data);
     return result;
index 019b8a0564a57ef9b385c6c9b169d4ea3142363f..fc370e5c6aa26a5b6351e4770574611753481b44 100644 (file)
--- a/CFData.c
+++ b/CFData.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFData.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
-       Responsibility: Christopher Kane
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
+       Responsibility: Kevin Perry
 */
 
 #include <CoreFoundation/CFData.h>
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
 #include <string.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#include <mach/mach_init.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#include <windows.h> // For GetSystemInfo()
+#endif
+
+#if __LP64__
+#define CFDATA_MAX_SIZE            ((1ULL << 42) - 1)
+#else
+#define CFDATA_MAX_SIZE            ((1ULL << 31) - 1)
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+CF_INLINE unsigned long __CFPageSize() { return vm_page_size; }
+#elif DEPLOYMENT_TARGET_WINDOWS
+CF_INLINE unsigned long __CFPageSize() {
+    SYSTEM_INFO sysInfo;
+    GetSystemInfo(&sysInfo);
+    return sysInfo.dwPageSize;
+}
+#endif
+
+#define INLINE_BYTES_THRESHOLD ((4 * __CFPageSize()) - sizeof(struct __CFData) - 15)
 
 struct __CFData {
     CFRuntimeBase _base;
@@ -38,23 +61,64 @@ struct __CFData {
     uint8_t *_bytes;
 };
 
-/* Bits 3-2 are used for mutability variation */
+/*  
+ Bit 0 = is mutable
+ Bit 1 = growable
+ Bit 2 = bytes inline
+ Bit 3 = use given CFAllocator
+ Bit 5 = allocate collectable memory
+ Bits 1-0 are used for mutability variation
+ Bit 6 = not all bytes have been zeroed yet (mutable)
+ */
+
+enum {
+    __kCFMutable = 0x01,
+    __kCFGrowable = 0x02,
+    __kCFMutableVarietyMask = 0x03,
+    __kCFBytesInline = 0x04,
+    __kCFUseAllocator = 0x08,
+    __kCFAllocatesCollectable = 0x20,
+};
+
+enum {
+    kCFImmutable = 0x0,                /* unchangable and fixed capacity; default */
+    kCFFixedMutable = 0x1,     /* changeable and fixed capacity */
+    kCFMutable = 0x3           /* changeable and variable capacity */
+};
+
+CF_INLINE void __CFDataSetInfoBits(CFDataRef data, UInt32 v) {__CFBitfieldSetValue(((CFRuntimeBase *)data)->_cfinfo[CF_INFO_BITS], 5, 0, v);}
+CF_INLINE Boolean __CFDataGetInfoBit(CFDataRef data, UInt32 b) {return ((((const CFRuntimeBase *)data)->_cfinfo[CF_INFO_BITS] & b) != 0);}
+CF_INLINE Boolean __CFDataIsMutable(CFDataRef data) {return __CFDataGetInfoBit(data, __kCFMutable);}
+CF_INLINE Boolean __CFDataIsGrowable(CFDataRef data) {return __CFDataGetInfoBit(data, __kCFGrowable);}
+CF_INLINE Boolean __CFDataBytesInline(CFDataRef data) {return __CFDataGetInfoBit(data, __kCFBytesInline);}
+CF_INLINE Boolean __CFDataUseAllocator(CFDataRef data) {return __CFDataGetInfoBit(data, __kCFUseAllocator);}
+CF_INLINE Boolean __CFDataAllocatesCollectable(CFDataRef data) {return __CFDataGetInfoBit(data, __kCFAllocatesCollectable);}
 
 CF_INLINE UInt32 __CFMutableVariety(const void *cf) {
-    return __CFBitfieldGetValue(((const CFRuntimeBase *)cf)->_cfinfo[CF_INFO_BITS], 3, 2);
+    return __CFBitfieldGetValue(((const CFRuntimeBase *)cf)->_cfinfo[CF_INFO_BITS], 1, 0);
 }
 
 CF_INLINE void __CFSetMutableVariety(void *cf, UInt32 v) {
-    __CFBitfieldSetValue(((CFRuntimeBase *)cf)->_cfinfo[CF_INFO_BITS], 3, 2, v);
+    __CFBitfieldSetValue(((CFRuntimeBase *)cf)->_cfinfo[CF_INFO_BITS], 1, 0, v);
 }
 
 CF_INLINE UInt32 __CFMutableVarietyFromFlags(UInt32 flags) {
-    return __CFBitfieldGetValue(flags, 1, 0);
+    return (flags & __kCFMutableVarietyMask);
 }
 
 #define __CFGenericValidateMutabilityFlags(flags) \
     CFAssert2(__CFMutableVarietyFromFlags(flags) != 0x2, __kCFLogAssertion, "%s(): flags 0x%x do not correctly specify the mutable variety", __PRETTY_FUNCTION__, flags);
 
+CF_INLINE Boolean __CFDataNeedsToZero(CFDataRef data) {
+    return __CFBitfieldGetValue(((CFRuntimeBase *)data)->_cfinfo[CF_INFO_BITS], 6, 6);
+}
+
+CF_INLINE void __CFDataSetNeedsToZero(CFDataRef data, Boolean zero) {
+    __CFBitfieldSetValue(((CFRuntimeBase *)data)->_cfinfo[CF_INFO_BITS], 6, 6, (zero ? 1 : 0));
+}
+
 CF_INLINE CFIndex __CFDataLength(CFDataRef data) {
     return data->_length;
 }
@@ -87,10 +151,31 @@ CF_INLINE void __CFDataSetNumBytes(CFMutableDataRef data, CFIndex v) {
     data->_capacity = v;
 }
 
+#if __LP64__
+#define CHUNK_SIZE (1ULL << 29)
+#define LOW_THRESHOLD (1ULL << 20)
+#define HIGH_THRESHOLD (1ULL << 32)
+#else
+#define CHUNK_SIZE (1ULL << 26)
+#define LOW_THRESHOLD (1ULL << 20)
+#define HIGH_THRESHOLD (1ULL << 29)
+#endif
+
 CF_INLINE CFIndex __CFDataRoundUpCapacity(CFIndex capacity) {
-    if (capacity < 16) return 16;
-// CF: quite probably, this doubling should slow as the data gets larger and larger; should not use strict doubling
-    return (1 << flsl(capacity));
+    if (capacity < 16) {
+       return 16;
+    } else if (capacity < LOW_THRESHOLD) {
+       /* Up to 4x */
+       int idx = flsl(capacity);
+       return (1 << (idx + ((idx % 2 == 0) ? 0 : 1)));
+    } else if (capacity < HIGH_THRESHOLD) {
+       /* Up to 2x */
+       return (1 << flsl(capacity));
+    } else {
+       /* Round up to next multiple of CHUNK_SIZE */
+       unsigned long newCapacity = CHUNK_SIZE * (1+(capacity >> (flsl(CHUNK_SIZE)-1)));
+       return __CFMin(newCapacity, CFDATA_MAX_SIZE);
+    }
 }
 
 CF_INLINE CFIndex __CFDataNumBytesForCapacity(CFIndex capacity) {
@@ -98,9 +183,13 @@ CF_INLINE CFIndex __CFDataNumBytesForCapacity(CFIndex capacity) {
 }
 
 static void __CFDataHandleOutOfMemory(CFTypeRef obj, CFIndex numBytes) {
-    CFStringRef msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFData failed"), numBytes);
-    CFBadErrorCallBack cb = _CFGetOutOfMemoryErrorCallBack();
-    if (NULL == cb || !cb(obj, CFSTR("NS/CFData"), msg)) {
+    CFStringRef msg;
+    if(0 < numBytes && numBytes <= CFDATA_MAX_SIZE) {
+       msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFData failed"), numBytes);
+    } else {
+       msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFData failed. Maximum size: %ld"), numBytes, CFDATA_MAX_SIZE);
+    }
+    {
         CFLog(kCFLogLevelCritical, CFSTR("%@"), msg);
         HALT;
     }
@@ -158,41 +247,73 @@ static CFStringRef __CFDataCopyDescription(CFTypeRef cf) {
     return result;
 }
 
-enum {
-    kCFImmutable = 0x0,                /* unchangable and fixed capacity; default */
-    kCFMutable = 0x1,          /* changeable and variable capacity */
-    kCFFixedMutable = 0x3      /* changeable and fixed capacity */
-};
+static void *__CFDataInlineBytesPtr(CFDataRef data) {
+    return (void *)((uintptr_t)((int8_t *)data + sizeof(struct __CFData) + 15) & ~0xF);        // 16-byte align
+}
+    
+static Boolean __CFDataShouldAllocateCleared(CFDataRef data, CFIndex size) {
+    Boolean result;
+    if (__CFDataUseAllocator(data)) {
+       result = false;
+    } else {
+       if (__CFDataAllocatesCollectable(data)) {
+#if __LP64__
+           result = false;
+#else
+           result = (size > (64 * 1024));
+#endif
+       } else {
+           result = (size > (128 * 1024));
+       }
+    }
+    return result;
+}
+
+    
+// Check __CFDataShouldAllocateCleared before passing true.
+static void *__CFDataAllocate(CFDataRef data, CFIndex size, Boolean clear) {
+    void *bytes = NULL;
+    if (__CFDataUseAllocator(data)) {
+       CFAllocatorRef allocator = __CFGetAllocator(data);
+       bytes = CFAllocatorAllocate(allocator, size, 0);
+       if (clear) memset((uint8_t *)bytes, 0, size);
+    } else {
+       if (__CFDataAllocatesCollectable(data)) {
+           bytes = auto_zone_allocate_object(auto_zone(), size, AUTO_MEMORY_UNSCANNED, 0, clear);
+       } else {
+           if (clear) {
+               bytes = malloc_zone_calloc(malloc_default_zone(), 1, size);
+           } else {
+               bytes = malloc_zone_malloc(malloc_default_zone(), size);
+           }
+       }
+    }
+    return bytes;
+}
 
 static void __CFDataDeallocate(CFTypeRef cf) {
     CFMutableDataRef data = (CFMutableDataRef)cf;
-    CFAllocatorRef allocator = __CFGetAllocator(data);
-    switch (__CFMutableVariety(data)) {
-    case kCFMutable:
-       _CFAllocatorDeallocateGC(allocator, data->_bytes);
-       data->_bytes = NULL;
-       break;
-    case kCFFixedMutable:
-       break;
-    case kCFImmutable:
-       if (NULL != data->_bytesDeallocator) {
-           if (CF_IS_COLLECTABLE_ALLOCATOR(data->_bytesDeallocator)) {
-               // GC:  for finalization safety, let collector reclaim the buffer in the next GC cycle.
-               auto_zone_release(__CFCollectableZone, data->_bytes);
-            } else {
-               CFAllocatorDeallocate(data->_bytesDeallocator, data->_bytes);
-               CFRelease(data->_bytesDeallocator);
-               data->_bytes = NULL;
+    if (!__CFDataBytesInline(data)) {
+       CFAllocatorRef deallocator = data->_bytesDeallocator;
+       if (deallocator != NULL) {
+           _CFAllocatorDeallocateGC(deallocator, data->_bytes);
+           CFRelease(deallocator);
+           data->_bytes = NULL;
+       } else {
+           if (__CFDataUseAllocator(data)) {
+               _CFAllocatorDeallocateGC(__CFGetAllocator(data), data->_bytes);
+           } else if (!__CFDataAllocatesCollectable(data)) {
+               malloc_zone_free(malloc_default_zone(), data->_bytes);
            }
+           data->_bytes = NULL;
        }
-       break;
     }
 }
 
 static CFTypeID __kCFDataTypeID = _kCFRuntimeNotATypeID;
 
 static const CFRuntimeClass __CFDataClass = {
-    0,
+    _kCFRuntimeScannedObject,
     "CFData",
     NULL,      // init
     NULL,      // copy
@@ -211,21 +332,26 @@ CFTypeID CFDataGetTypeID(void) {
     return __kCFDataTypeID;
 }
 
+
 // NULL bytesDeallocator to this function does not mean the default allocator, it means
 // that there should be no deallocator, and the bytes should be copied.
 static CFMutableDataRef __CFDataInit(CFAllocatorRef allocator, CFOptionFlags flags, CFIndex capacity, const uint8_t *bytes, CFIndex length, CFAllocatorRef bytesDeallocator) {
     CFMutableDataRef memory;
-    CFIndex size;
     __CFGenericValidateMutabilityFlags(flags);
     CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%d) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
     CFAssert3(kCFFixedMutable != __CFMutableVarietyFromFlags(flags) || length <= capacity, __kCFLogAssertion, "%s(): for kCFFixedMutable type, capacity (%d) must be greater than or equal to number of initial elements (%d)", __PRETTY_FUNCTION__, capacity, length);
     CFAssert2(0 <= length, __kCFLogAssertion, "%s(): length (%d) cannot be less than zero", __PRETTY_FUNCTION__, length);
-    size = sizeof(struct __CFData) - sizeof(CFRuntimeBase);
-    if (__CFMutableVarietyFromFlags(flags) != kCFMutable && (bytesDeallocator == NULL)) {
-       size += sizeof(uint8_t) * __CFDataNumBytesForCapacity(capacity);
-    }
-    if (__CFMutableVarietyFromFlags(flags) != kCFMutable) {
-       size += sizeof(uint8_t) * 15;   // for 16-byte alignment fixup
+    Boolean collectableMemory = CF_IS_COLLECTABLE_ALLOCATOR(allocator);
+    Boolean noCopy = bytesDeallocator != NULL;
+    Boolean isMutable = ((flags & __kCFMutable) != 0);
+    Boolean isGrowable = ((flags & __kCFGrowable) != 0);
+    Boolean allocateInline = !isGrowable && !noCopy && capacity < INLINE_BYTES_THRESHOLD;
+    allocator = (allocator == NULL) ? __CFGetDefaultAllocator() : allocator;
+    Boolean useAllocator = (allocator != kCFAllocatorSystemDefault && allocator != kCFAllocatorMalloc && allocator != kCFAllocatorMallocZone);
+    
+    CFIndex size = sizeof(struct __CFData) - sizeof(CFRuntimeBase);
+    if (allocateInline) {
+       size += sizeof(uint8_t) * __CFDataNumBytesForCapacity(capacity) + sizeof(uint8_t) * 15; // for 16-byte alignment fixup
     }
     memory = (CFMutableDataRef)_CFRuntimeCreateInstance(allocator, __kCFDataTypeID, size, NULL);
     if (NULL == memory) {
@@ -233,48 +359,73 @@ static CFMutableDataRef __CFDataInit(CFAllocatorRef allocator, CFOptionFlags fla
     }
     __CFDataSetNumBytesUsed(memory, 0);
     __CFDataSetLength(memory, 0);
-    switch (__CFMutableVarietyFromFlags(flags)) {
-    case kCFMutable:
+    __CFDataSetInfoBits(memory,
+                       (allocateInline ? __kCFBytesInline : 0) | 
+                       (useAllocator ? __kCFUseAllocator : 0) |
+                       (collectableMemory ? __kCFAllocatesCollectable : 0));
+    
+    BOOL finalize = YES;
+    BOOL scan = YES;
+    if (collectableMemory) {
+       if (allocateInline) {
+           // We have no pointer to anything that needs to be reclaimed, so don't scan or finalize.
+           scan = NO;
+           finalize = NO;
+       } else if (noCopy) {
+           if (CF_IS_COLLECTABLE_ALLOCATOR(bytesDeallocator)) {
+               // We're taking responsibility for externally GC-allocated memory, so scan us, but we don't need to finalize.
+               finalize = NO;
+           } else if (bytesDeallocator == kCFAllocatorNull) {
+               // We don't have responsibility for these bytes, so there's no need to be scanned and we don't need to finalize.
+               scan = NO;
+               finalize = NO;
+           } else {
+               // We have a pointer to non-GC-allocated memory, so don't scan, but do finalize.
+               scan = NO;
+           }
+       }
+       if (!scan) auto_zone_set_unscanned(auto_zone(), memory);
+       if (!finalize) auto_zone_set_nofinalize(auto_zone(), memory);
+    }
+    if (isMutable && isGrowable) {
        __CFDataSetCapacity(memory, __CFDataRoundUpCapacity(1));
        __CFDataSetNumBytes(memory, __CFDataNumBytesForCapacity(__CFDataRoundUpCapacity(1)));
-       // GC: if allocated in the collectable zone, mark the object as needing to be scanned.
-       if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) auto_zone_set_layout_type(__CFCollectableZone, memory, AUTO_MEMORY_SCANNED);
-       // assume that allocators give 16-byte aligned memory back -- it is their responsibility
-       CF_WRITE_BARRIER_BASE_ASSIGN(allocator, memory, memory->_bytes, _CFAllocatorAllocateGC(allocator, __CFDataNumBytes(memory) * sizeof(uint8_t), 0));
-       if (__CFOASafe) __CFSetLastAllocationEventName(memory->_bytes, "CFData (store)");
-       if (NULL == memory->_bytes) {
-           CFRelease(memory);
-           return NULL;
-       }
-       memory->_bytesDeallocator = NULL;
        __CFSetMutableVariety(memory, kCFMutable);
-       CFDataReplaceBytes(memory, CFRangeMake(0, 0), bytes, length);
-       break;
-    case kCFFixedMutable:
+    } else {
        /* Don't round up capacity */
        __CFDataSetCapacity(memory, capacity);
        __CFDataSetNumBytes(memory, __CFDataNumBytesForCapacity(capacity));
-       memory->_bytes = (uint8_t *)((uintptr_t)((int8_t *)memory + sizeof(struct __CFData) + 15) & ~0xF);      // 16-byte align
-       memory->_bytesDeallocator = NULL;
        __CFSetMutableVariety(memory, kCFFixedMutable);
-       CFDataReplaceBytes(memory, CFRangeMake(0, 0), bytes, length);
-       break;
-    case kCFImmutable:
-       /* Don't round up capacity */
-       __CFDataSetCapacity(memory, capacity);
-       __CFDataSetNumBytes(memory, __CFDataNumBytesForCapacity(capacity));
-       if (bytesDeallocator != NULL) {
-            CF_WRITE_BARRIER_BASE_ASSIGN(allocator, memory, memory->_bytes, (uint8_t *)bytes);
+    }
+    if (noCopy) {
+       __CFAssignWithWriteBarrier((void **)&memory->_bytes, (uint8_t *)bytes);
+       if (finalize) {
            memory->_bytesDeallocator = (CFAllocatorRef)CFRetain(bytesDeallocator);
-           __CFDataSetNumBytesUsed(memory, length);
-           __CFDataSetLength(memory, length);
+       }
+       if (CF_IS_COLLECTABLE_ALLOCATOR(bytesDeallocator)) {
+           // When given a GC allocator as the deallocator, we can assume that the no-copy memory is GC-allocated with a retain count of (at least) 1 and we should release it now instead of waiting until __CFDataDeallocate.
+           auto_zone_release(auto_zone(), memory->_bytes);
+       }
+       __CFDataSetNumBytesUsed(memory, length);
+       __CFDataSetLength(memory, length);
+       // Mutable no-copy datas are not allowed, so don't bother setting needsToZero flag.
+    } else {
+       Boolean cleared = (isMutable && !isGrowable && !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard));
+       if (!allocateInline) {
+           // assume that allocators give 16-byte aligned memory back -- it is their responsibility
+           __CFAssignWithWriteBarrier((void **)&memory->_bytes, __CFDataAllocate(memory, __CFDataNumBytes(memory) * sizeof(uint8_t), cleared));
+           if (__CFOASafe) __CFSetLastAllocationEventName(memory->_bytes, "CFData (store)");
+           if (NULL == memory->_bytes) {
+               CFRelease(memory);
+               return NULL;
+           }
        } else {
-           memory->_bytes = (uint8_t *)((uintptr_t)((int8_t *)memory + sizeof(struct __CFData) + 15) & ~0xF);  // 16-byte align
-           memory->_bytesDeallocator = NULL;
-           __CFSetMutableVariety(memory, kCFFixedMutable);
-           CFDataReplaceBytes(memory, CFRangeMake(0, 0), bytes, length);
+           memory->_bytes = (uint8_t *)__CFDataInlineBytesPtr(memory);
+           cleared = true;
        }
-       break;
+       __CFDataSetNeedsToZero(memory, !cleared);
+       memory->_bytesDeallocator = NULL;
+       CFDataReplaceBytes(memory, CFRangeMake(0, 0), bytes, length);
     }
     __CFSetMutableVariety(memory, __CFMutableVarietyFromFlags(flags));
     return memory;
@@ -317,65 +468,99 @@ const uint8_t *CFDataGetBytePtr(CFDataRef data) {
 
 uint8_t *CFDataGetMutableBytePtr(CFMutableDataRef data) {
     CF_OBJC_FUNCDISPATCH0(__kCFDataTypeID, uint8_t *, data, "mutableBytes");
-    CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
     return data->_bytes;
 }
 
 void CFDataGetBytes(CFDataRef data, CFRange range, uint8_t *buffer) {
     CF_OBJC_FUNCDISPATCH2(__kCFDataTypeID, void, data, "getBytes:range:", buffer, range);
+    __CFDataValidateRange(data, range, __PRETTY_FUNCTION__);
     memmove(buffer, data->_bytes + range.location, range.length);
 }
 
-static void __CFDataGrow(CFMutableDataRef data, CFIndex numNewValues) {
+/* Allocates new block of data with at least numNewValues more bytes than the current length. If clear is true, the new bytes up to at least the new length with be zeroed. */
+static void __CFDataGrow(CFMutableDataRef data, CFIndex numNewValues, Boolean clear) {
     CFIndex oldLength = __CFDataLength(data);
-    CFIndex capacity = __CFDataRoundUpCapacity(oldLength + numNewValues);
+    CFIndex newLength = oldLength + numNewValues;
+    if (newLength > CFDATA_MAX_SIZE || newLength < 0) __CFDataHandleOutOfMemory(data, newLength * sizeof(uint8_t));
+    CFIndex capacity = __CFDataRoundUpCapacity(newLength);
+    CFIndex numBytes = __CFDataNumBytesForCapacity(capacity);
     CFAllocatorRef allocator = CFGetAllocator(data);
+    void *bytes = NULL;
+    void *oldBytes = data->_bytes;
+    Boolean allocateCleared = clear && __CFDataShouldAllocateCleared(data, numBytes);
+    if (allocateCleared && !__CFDataUseAllocator(data) && (oldLength == 0 || (newLength / oldLength) > 4)) {
+       // If the length that needs to be zeroed is significantly greater than the length of the data, then calloc/memmove is probably more efficient than realloc/memset.
+       bytes = __CFDataAllocate(data, numBytes * sizeof(uint8_t), true);
+       if (NULL != bytes) {
+           memmove(bytes, oldBytes, oldLength);
+           __CFDataDeallocate(data);
+       }
+    }
+    if (bytes == NULL) {
+       // If the calloc/memmove approach either failed or was never attempted, then realloc.
+       allocateCleared = false;
+       if (__CFDataUseAllocator(data)) {
+           bytes = CFAllocatorReallocate(allocator, oldBytes, numBytes * sizeof(uint8_t), 0);
+       } else {
+           bytes = malloc_zone_realloc(__CFDataAllocatesCollectable(data) ? auto_zone() : malloc_default_zone(), oldBytes, numBytes * sizeof(uint8_t));
+       }
+    }
+    if (NULL == bytes) __CFDataHandleOutOfMemory(data, numBytes * sizeof(uint8_t));
     __CFDataSetCapacity(data, capacity);
-    __CFDataSetNumBytes(data, __CFDataNumBytesForCapacity(capacity));
-    void *bytes = _CFAllocatorReallocateGC(allocator, data->_bytes, __CFDataNumBytes(data) * sizeof(uint8_t), 0);
-    if (NULL == bytes) __CFDataHandleOutOfMemory(data, __CFDataNumBytes(data) * sizeof(uint8_t));
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, data, data->_bytes, bytes);
+    __CFDataSetNumBytes(data, numBytes);
+    if (clear && !allocateCleared && oldLength < newLength) memset((uint8_t *)bytes + oldLength, 0, newLength - oldLength);
+    __CFDataSetNeedsToZero(data, !allocateCleared);
+    __CFAssignWithWriteBarrier((void **)&data->_bytes, bytes);
     if (__CFOASafe) __CFSetLastAllocationEventName(data->_bytes, "CFData (store)");
 }
 
-void CFDataSetLength(CFMutableDataRef data, CFIndex length) {
-    CFIndex len;
-    CF_OBJC_FUNCDISPATCH1(__kCFDataTypeID, void, data, "setLength:", length);
-    CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
-    len = __CFDataLength(data);
-    switch (__CFMutableVariety(data)) {
-    case kCFMutable:
-       if (len < length) {
-// CF: should only grow when new length exceeds current capacity, not whenever it exceeds the current length
-           __CFDataGrow(data, length - len);
+void CFDataSetLength(CFMutableDataRef data, CFIndex newLength) {
+    CFIndex oldLength, capacity;
+    Boolean isGrowable;
+    CF_OBJC_FUNCDISPATCH1(__kCFDataTypeID, void, data, "setLength:", newLength);
+    CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
+    oldLength = __CFDataLength(data);
+    capacity = __CFDataCapacity(data);
+    isGrowable = __CFDataIsGrowable(data);
+    if (__CFDataIsMutable(data)) {
+       if (newLength < 0) {
+           if (isGrowable) {
+               __CFDataHandleOutOfMemory(data, newLength);
+           } else {
+               HALT;
+           }
+       } else if (capacity < newLength) {
+           if (isGrowable) {
+               __CFDataGrow(data, newLength - oldLength, true);
+           } else {
+               CFAssert1(newLength <= __CFDataCapacity(data), __kCFLogAssertion, "%s(): fixed-capacity data is full", __PRETTY_FUNCTION__);
+           }
+       } else if (oldLength < newLength && __CFDataNeedsToZero(data)) {
+           memset(data->_bytes + oldLength, 0, newLength - oldLength);
+       } else if (newLength < oldLength) {
+           __CFDataSetNeedsToZero(data, true);
        }
-       break;
-    case kCFFixedMutable:
-       CFAssert1(length <= __CFDataCapacity(data), __kCFLogAssertion, "%s(): fixed-capacity data is full", __PRETTY_FUNCTION__);
-       break;
     }
-    if (len < length) {
-       memset(data->_bytes + len, 0, length - len);
-    }
-    __CFDataSetLength(data, length);
-    __CFDataSetNumBytesUsed(data, length);
+    __CFDataSetLength(data, newLength);
+    __CFDataSetNumBytesUsed(data, newLength);
 }
 
 void CFDataIncreaseLength(CFMutableDataRef data, CFIndex extraLength) {
     CF_OBJC_FUNCDISPATCH1(__kCFDataTypeID, void, data, "increaseLengthBy:", extraLength);
-    CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
     CFDataSetLength(data, __CFDataLength(data) + extraLength);
 }
 
 void CFDataAppendBytes(CFMutableDataRef data, const uint8_t *bytes, CFIndex length) {
     CF_OBJC_FUNCDISPATCH2(__kCFDataTypeID, void, data, "appendBytes:length:", bytes, length);
-    CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
     CFDataReplaceBytes(data, CFRangeMake(__CFDataLength(data), 0), bytes, length); 
 }
 
 void CFDataDeleteBytes(CFMutableDataRef data, CFRange range) {
     CF_OBJC_FUNCDISPATCH3(__kCFDataTypeID, void, data, "replaceBytesInRange:withBytes:length:", range, NULL, 0);
-    CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
     CFDataReplaceBytes(data, range, NULL, 0); 
 }
 
@@ -383,7 +568,7 @@ void CFDataReplaceBytes(CFMutableDataRef data, CFRange range, const uint8_t *new
     CF_OBJC_FUNCDISPATCH3(__kCFDataTypeID, void, data, "replaceBytesInRange:withBytes:length:", range, newBytes, newLength);
     __CFGenericValidateType(data, __kCFDataTypeID);
     __CFDataValidateRange(data, range, __PRETTY_FUNCTION__);
-    CFAssert1(__CFMutableVariety(data) == kCFMutable || __CFMutableVariety(data) == kCFFixedMutable, __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
+    CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
     CFAssert2(0 <= newLength, __kCFLogAssertion, "%s(): newLength (%d) cannot be less than zero", __PRETTY_FUNCTION__, newLength);
 
     CFIndex len = __CFDataLength(data);
@@ -394,7 +579,7 @@ void CFDataReplaceBytes(CFMutableDataRef data, CFRange range, const uint8_t *new
     switch (__CFMutableVariety(data)) {
     case kCFMutable:
        if (__CFDataNumBytes(data) < newCount) {
-           __CFDataGrow(data, newLength - range.length);
+           __CFDataGrow(data, newLength - range.length, false);
        }
        break;
     case kCFFixedMutable:
@@ -411,6 +596,172 @@ void CFDataReplaceBytes(CFMutableDataRef data, CFRange range, const uint8_t *new
     __CFDataSetLength(data, newCount);
 }
 
+#define REVERSE_BUFFER(type, buf, len) { \
+    type tmp; \
+    for(int i = 0; i < (len)/2; i++) { \
+       tmp = (buf)[i]; \
+       (buf)[i] = (buf)[(len) - i - 1]; \
+       (buf)[(len) - i - 1] = tmp; \
+    } \
+}
+
+static void _computeGoodSubstringShift(const uint8_t *needle, int needleLength, unsigned long shift[], unsigned long suff[]) {
+    int f, g, i, j;
+    
+    // Compute suffix lengths
+    
+    suff[needleLength - 1] = needleLength;
+    g = needleLength - 1;
+    for (i = needleLength - 2; i >= 0; --i) {
+        if (i > g && suff[i + needleLength - 1 - f] < i - g)
+            suff[i] = suff[i + needleLength - 1 - f];
+        else {
+            if (i < g)
+                g = i;
+            f = i;
+            while (g >= 0 && needle[g] == needle[g + needleLength - 1 - f])
+                --g;
+            suff[i] = f - g;
+        }
+    }
+    
+    // Compute shift table
+    
+    for (i = 0; i < needleLength; ++i)
+        shift[i] = needleLength;
+    j = 0;
+    for (i = needleLength - 1; i >= 0; --i)
+        if (suff[i] == i + 1)
+            for (; j < needleLength - 1 - i; ++j)
+                if (shift[j] == needleLength)
+                    shift[j] = needleLength - 1 - i;
+    // Set the amount of shift necessary to move each of the suffix matches found into a position where it overlaps with the suffix. If there are duplicate matches the latest one is the one that should take effect.
+    for (i = 0; i <= needleLength - 2; ++i)
+        shift[needleLength - 1 - suff[i]] = needleLength - 1 - i;
+    // Since the Boyer-Moore algorithm moves the pointer back while scanning substrings, add the distance to the end of the potential substring.
+    for (i = 0; i < needleLength - 1; ++i) {
+       shift[i] += (needleLength - 1 - i);
+    }
+}
+
+static const uint8_t * __CFDataSearchBoyerMoore(const CFDataRef data, const uint8_t *haystack, unsigned long haystackLength, const uint8_t *needle, unsigned long needleLength, Boolean backwards) {
+    unsigned long badCharacterShift[UCHAR_MAX + 1] = {0};
+    unsigned long *goodSubstringShift = (unsigned long *)malloc(needleLength * sizeof(unsigned long));
+    unsigned long *suffixLengths = (unsigned long *)malloc(needleLength * sizeof(unsigned long));
+    if (!goodSubstringShift || !suffixLengths) {
+       __CFDataHandleOutOfMemory(data, needleLength * sizeof(unsigned long));
+    }
+    
+    if(backwards) {
+       for (int i = 0; i < sizeof(badCharacterShift) / sizeof(*badCharacterShift); i++)
+           badCharacterShift[i] = needleLength;
+       
+       for (int i = needleLength - 1; i >= 0; i--)
+           badCharacterShift[needle[i]] = i;
+       
+       // To get the correct shift table for backwards search reverse the needle, compute the forwards shift table, and then reverse the result.
+       uint8_t *needleCopy = (uint8_t *)malloc(needleLength * sizeof(uint8_t));
+       if (!needleCopy) {
+           __CFDataHandleOutOfMemory(data, needleLength * sizeof(uint8_t));
+       }
+       memmove(needleCopy, needle, needleLength);
+       REVERSE_BUFFER(uint8_t, needleCopy, needleLength);
+       _computeGoodSubstringShift(needleCopy, needleLength, goodSubstringShift, suffixLengths);
+       REVERSE_BUFFER(unsigned long, goodSubstringShift, needleLength);
+       free(needleCopy);
+    } else {
+       for (int i = 0; i < sizeof(badCharacterShift) / sizeof(*badCharacterShift); i++)
+           badCharacterShift[i] = needleLength;
+       
+       for (int i = 0; i < needleLength; i++)
+           badCharacterShift[needle[i]] = needleLength - i- 1;
+       
+       _computeGoodSubstringShift(needle, needleLength, goodSubstringShift, suffixLengths);
+    }
+    
+    const uint8_t *scan_needle;
+    const uint8_t *scan_haystack;
+    const uint8_t *result = NULL;
+    if(backwards) {
+       const uint8_t *const end_needle = needle + needleLength;
+       scan_needle = needle;
+       scan_haystack = haystack + haystackLength - needleLength;
+       while (scan_haystack >= haystack && scan_needle < end_needle) {
+           if (*scan_haystack == *scan_needle) {
+               scan_haystack++;
+               scan_needle++;
+           } else {
+               scan_haystack -= __CFMax(badCharacterShift[*scan_haystack], goodSubstringShift[scan_needle - needle]);
+               scan_needle = needle;
+           }
+       }
+       if (scan_needle == end_needle) {
+           result = (scan_haystack - needleLength);
+       }
+    } else {
+       const uint8_t *const end_haystack = haystack + haystackLength;
+       scan_needle = needle + needleLength - 1;
+       scan_haystack = haystack + needleLength - 1;
+       while (scan_haystack < end_haystack && scan_needle >= needle) {
+           if (*scan_haystack == *scan_needle) {
+               scan_haystack--;
+               scan_needle--;
+           } else {
+               scan_haystack += __CFMax(badCharacterShift[*scan_haystack], goodSubstringShift[scan_needle - needle]);
+               scan_needle = needle + needleLength - 1;
+           }
+       }
+       if (scan_needle < needle) {
+           result = (scan_haystack + 1);
+       }
+    }
+    
+    free(goodSubstringShift);
+    free(suffixLengths);
+    
+    return result;
+}
+
+CFRange _CFDataFindBytes(CFDataRef data, CFDataRef dataToFind, CFRange searchRange, CFDataSearchFlags compareOptions) {
+    const uint8_t *fullHaystack = CFDataGetBytePtr(data);
+    const uint8_t *needle = CFDataGetBytePtr(dataToFind);
+    unsigned long fullHaystackLength = CFDataGetLength(data);
+    unsigned long needleLength = CFDataGetLength(dataToFind);
+    
+    if(compareOptions & kCFDataSearchAnchored) {
+       if(searchRange.length > needleLength) {
+           if(compareOptions & kCFDataSearchBackwards) {
+               searchRange.location += (searchRange.length - needleLength);
+           }
+           searchRange.length = needleLength;
+       }
+    }
+    if(searchRange.length > fullHaystackLength - searchRange.location) {
+       searchRange.length = fullHaystackLength - searchRange.location;
+    }
+    
+    if(searchRange.length < needleLength || fullHaystackLength == 0 || needleLength == 0) {
+       return CFRangeMake(kCFNotFound, 0);
+    }
+       
+    const uint8_t *haystack = fullHaystack + searchRange.location;
+    const uint8_t *searchResult = __CFDataSearchBoyerMoore(data, haystack, searchRange.length, needle, needleLength, (compareOptions & kCFDataSearchBackwards) != 0);
+    CFIndex resultLocation = (searchResult == NULL) ? kCFNotFound : searchRange.location + (searchResult - haystack);
+    
+    return CFRangeMake(resultLocation, resultLocation == kCFNotFound ? 0: needleLength);
+}
+
+CFRange CFDataFind(CFDataRef data, CFDataRef dataToFind, CFRange searchRange, CFDataSearchFlags compareOptions) {
+    // No objc dispatch
+    __CFGenericValidateType(data, __kCFDataTypeID);
+    __CFGenericValidateType(dataToFind, __kCFDataTypeID);
+    __CFDataValidateRange(data, searchRange, __PRETTY_FUNCTION__);
+    
+    return _CFDataFindBytes(data, dataToFind, searchRange, compareOptions);
+}
+
 #undef __CFDataValidateRange
 #undef __CFGenericValidateMutabilityFlags
-
+#undef INLINE_BYTES_THRESHOLD
+#undef CFDATA_MAX_SIZE
+#undef REVERSE_BUFFER
index b53d8bd9f20d756991be1e8ef9f712d1938516c8..7176ca8487b0befc7c11194d7d832d4e29c1b112 100644 (file)
--- a/CFData.h
+++ b/CFData.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFData.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFDATA__)
@@ -80,6 +80,17 @@ void CFDataReplaceBytes(CFMutableDataRef theData, CFRange range, const UInt8 *ne
 CF_EXPORT
 void CFDataDeleteBytes(CFMutableDataRef theData, CFRange range);
 
+#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED
+enum {
+    kCFDataSearchBackwards = 1UL << 0,
+    kCFDataSearchAnchored = 1UL << 1
+};
+#endif
+typedef CFOptionFlags CFDataSearchFlags;
+
+CF_EXPORT
+CFRange CFDataFind(CFDataRef theData, CFDataRef dataToFind, CFRange searchRange, CFDataSearchFlags compareOptions) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
 CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFDATA__ */
index d47cf9228ade2d196c8d805e4d67074d5bf0c6e9..8c817db2b350e839ce4d7320804ee9a3708f4648 100644 (file)
--- a/CFDate.c
+++ b/CFDate.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFDate.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #include <CoreFoundation/CFNumber.h>
 #include "CFInternal.h"
 #include <math.h>
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <sys/time.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
-const CFTimeInterval kCFAbsoluteTimeIntervalSince1970 = 978307200.0L;
-const CFTimeInterval kCFAbsoluteTimeIntervalSince1904 = 3061152000.0L;
 
 /* cjk: The Julian Date for the reference date is 2451910.5,
         I think, in case that's ever useful. */
 
+
+const CFTimeInterval kCFAbsoluteTimeIntervalSince1970 = 978307200.0L;
+const CFTimeInterval kCFAbsoluteTimeIntervalSince1904 = 3061152000.0L;
+
 __private_extern__ double __CFTSRRate = 0.0;
 static double __CF1_TSRRate = 0.0;
 
@@ -57,21 +62,36 @@ __private_extern__ CFTimeInterval __CFTSRToTimeInterval(int64_t tsr) {
 
 CFAbsoluteTime CFAbsoluteTimeGetCurrent(void) {
     CFAbsoluteTime ret;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_IPHONE
     struct timeval tv;
     gettimeofday(&tv, NULL);
     ret = (CFTimeInterval)tv.tv_sec - kCFAbsoluteTimeIntervalSince1970;
     ret += (1.0E-6 * (CFTimeInterval)tv.tv_usec);
+#elif DEPLOYMENT_TARGET_WINDOWS_SYNC || DEPLOYMENT_TARGET_CODE011
+    FILETIME ft;
+    GetSystemTimeAsFileTime(&ft);
+    ret = _CFAbsoluteTimeFromFileTime(&ft);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     return ret;
 }
 
 __private_extern__ void __CFDateInitialize(void) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_IPHONE
     struct mach_timebase_info info;
     mach_timebase_info(&info);
     __CFTSRRate = (1.0E9 / (double)info.numer) * (double)info.denom;
     __CF1_TSRRate = 1.0 / __CFTSRRate;
+#elif DEPLOYMENT_TARGET_WINDOWS_SYNC || DEPLOYMENT_TARGET_CODE011
+    LARGE_INTEGER freq;
+    if (!QueryPerformanceFrequency(&freq)) {
+        HALT;
+    }
+    __CFTSRRate = (double)freq.QuadPart;
+    __CF1_TSRRate = 1.0 / __CFTSRRate;
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     CFDateGetTypeID(); // cause side-effects
 }
@@ -153,6 +173,7 @@ CFComparisonResult CFDateCompare(CFDateRef date, CFDateRef otherDate, void *cont
 }
 #endif
 
+
 CF_INLINE int32_t __CFDoubleModToInt(double d, int32_t modulus) {
     int32_t result = (int32_t)(float)floor(d - floor(d / modulus) * modulus);
     if (result < 0) result += modulus;
index 4808f4bb9b361d18253f35bc4fc090dcb15ac924..b5c0de2ded5ea730146538176465310a2c3a8b4d 100644 (file)
--- a/CFDate.h
+++ b/CFDate.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFDate.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFDATE__)
@@ -82,12 +82,12 @@ typedef struct {
 } CFGregorianUnits;
 
 enum {
-    kCFGregorianUnitsYears = (1 << 0),
-    kCFGregorianUnitsMonths = (1 << 1),
-    kCFGregorianUnitsDays = (1 << 2),
-    kCFGregorianUnitsHours = (1 << 3),
-    kCFGregorianUnitsMinutes = (1 << 4),
-    kCFGregorianUnitsSeconds = (1 << 5),
+    kCFGregorianUnitsYears = (1UL << 0),
+    kCFGregorianUnitsMonths = (1UL << 1),
+    kCFGregorianUnitsDays = (1UL << 2),
+    kCFGregorianUnitsHours = (1UL << 3),
+    kCFGregorianUnitsMinutes = (1UL << 4),
+    kCFGregorianUnitsSeconds = (1UL << 5),
     kCFGregorianAllUnits = 0x00FFFFFF
 };
 typedef CFOptionFlags CFGregorianUnitFlags;
index e6fe19cc31e90cfe2efb7b94c722b2e088f642d0..f07f66b4ec2784bdcce6dbd8a34bdff999966560 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -20,9 +20,9 @@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
-/*     CFDateFormatter.c
-       Copyright 2002-2003, Apple, Inc. All rights reserved.
-       Responsibility: Christopher Kane
+/*        CFDateFormatter.c
+        Copyright (c) 2002-2009, Apple Inc. All rights reserved.
+        Responsibility: Christopher Kane
 */
 
 #include <CoreFoundation/CFDateFormatter.h>
 #include <CoreFoundation/CFCalendar.h>
 #include <CoreFoundation/CFNumber.h>
 #include "CFInternal.h"
+#include "CFLocaleInternal.h"
 #include <unicode/udat.h>
+#include <unicode/udatpg.h>
 #include <math.h>
 #include <float.h>
 
 extern UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz);
 static void __CFDateFormatterCustomize(CFDateFormatterRef formatter);
 
-extern const CFStringRef kCFDateFormatterCalendarIdentifier;
+CF_EXPORT const CFStringRef kCFDateFormatterCalendarIdentifierKey;
+
+#undef CFReleaseIfNotNull
+#define CFReleaseIfNotNull(X) if (X) CFRelease(X)
 
 #define BUFFER_SIZE 768
 
+CFStringRef CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator, CFStringRef tmplate, CFOptionFlags options, CFLocaleRef locale) {
+    if (allocator) __CFGenericValidateType(allocator, CFAllocatorGetTypeID());
+    if (locale) __CFGenericValidateType(locale, CFLocaleGetTypeID());
+    __CFGenericValidateType(tmplate, CFStringGetTypeID());
+
+    CFStringRef localeName = locale ? CFLocaleGetIdentifier(locale) : CFSTR("");
+    char buffer[BUFFER_SIZE];
+    const char *cstr = CFStringGetCStringPtr(localeName, kCFStringEncodingASCII);
+    if (NULL == cstr) {
+        if (CFStringGetCString(localeName, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) cstr = buffer;
+    }
+    if (NULL == cstr) {
+        return NULL;
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+    UDateTimePatternGenerator *ptg = udatpg_open(cstr, &status);
+    if (NULL == ptg || U_FAILURE(status)) {
+       return NULL;
+    }
+
+    CFIndex jCount = 0; // the only interesting cases are 0, 1, and 2 (adjacent)
+    CFRange r = CFStringFind(tmplate, CFSTR("j"), 0);
+    if (kCFNotFound != r.location) {
+        jCount++;
+        if ((r.location + 1 < CFStringGetLength(tmplate)) && ('j' == CFStringGetCharacterAtIndex(tmplate, r.location + 1))) {
+            jCount++;
+        }
+    }
+
+    UChar pattern[BUFFER_SIZE], skel[BUFFER_SIZE], bpat[BUFFER_SIZE];
+    CFIndex cnt = CFStringGetLength(tmplate);
+    if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
+    CFStringGetCharacters(tmplate, CFRangeMake(0, cnt), (UniChar *)pattern);
+    int32_t patlen = cnt;
+
+    status = U_ZERO_ERROR;
+    int32_t skellen = udatpg_getSkeleton(ptg, pattern, patlen, skel, sizeof(skel) / sizeof(skel[0]), &status);
+    if (U_FAILURE(status)) {
+       return NULL;
+    }
+
+    if ((0 < jCount) && (skellen + jCount < (sizeof(skel) / sizeof(skel[0])))) {
+        skel[skellen++] = 'j';
+        if (1 < jCount) skel[skellen++] = 'j';
+    }
+
+    status = U_ZERO_ERROR;
+    int32_t bpatlen = udatpg_getBestPattern(ptg, skel, skellen, bpat, sizeof(bpat) / sizeof(bpat[0]), &status);
+    if (U_FAILURE(status)) {
+       return NULL;
+    }
+    udatpg_close(ptg);
+
+    return CFStringCreateWithCharacters(allocator, (const UniChar *)bpat, bpatlen);
+}
+
 struct __CFDateFormatter {
     CFRuntimeBase _base;
     UDateFormat *_df;
@@ -50,9 +112,37 @@ struct __CFDateFormatter {
     CFDateFormatterStyle _dateStyle;
     CFStringRef _format;
     CFStringRef _defformat;
-    CFStringRef _calendarName;
-    CFTimeZoneRef _tz;
-    CFDateRef _defaultDate;
+    struct {
+        CFBooleanRef _IsLenient;
+       CFBooleanRef _DoesRelativeDateFormatting;
+       CFBooleanRef _HasCustomFormat;
+        CFTimeZoneRef _TimeZone; 
+        CFCalendarRef _Calendar;
+        CFStringRef _CalendarName;
+        CFDateRef _TwoDigitStartDate;
+        CFDateRef _DefaultDate;
+        CFDateRef _GregorianStartDate;
+        CFArrayRef _EraSymbols;
+        CFArrayRef _LongEraSymbols;
+        CFArrayRef _MonthSymbols;
+        CFArrayRef _ShortMonthSymbols;
+        CFArrayRef _VeryShortMonthSymbols;
+        CFArrayRef _StandaloneMonthSymbols;
+        CFArrayRef _ShortStandaloneMonthSymbols;
+        CFArrayRef _VeryShortStandaloneMonthSymbols;
+        CFArrayRef _WeekdaySymbols;
+        CFArrayRef _ShortWeekdaySymbols;
+        CFArrayRef _VeryShortWeekdaySymbols;
+        CFArrayRef _StandaloneWeekdaySymbols;
+        CFArrayRef _ShortStandaloneWeekdaySymbols;
+        CFArrayRef _VeryShortStandaloneWeekdaySymbols;
+        CFArrayRef _QuarterSymbols;
+        CFArrayRef _ShortQuarterSymbols;
+        CFArrayRef _StandaloneQuarterSymbols;
+        CFArrayRef _ShortStandaloneQuarterSymbols;
+        CFStringRef _AMSymbol;
+        CFStringRef _PMSymbol;
+    } _property;
 };
 
 static CFStringRef __CFDateFormatterCopyDescription(CFTypeRef cf) {
@@ -66,9 +156,156 @@ static void __CFDateFormatterDeallocate(CFTypeRef cf) {
     if (formatter->_locale) CFRelease(formatter->_locale);
     if (formatter->_format) CFRelease(formatter->_format);
     if (formatter->_defformat) CFRelease(formatter->_defformat);
-    if (formatter->_calendarName) CFRelease(formatter->_calendarName);
-    if (formatter->_tz) CFRelease(formatter->_tz);
-    if (formatter->_defaultDate) CFRelease(formatter->_defaultDate);
+    CFReleaseIfNotNull(formatter->_property._IsLenient);
+    CFReleaseIfNotNull(formatter->_property._DoesRelativeDateFormatting);
+    CFReleaseIfNotNull(formatter->_property._TimeZone);
+    CFReleaseIfNotNull(formatter->_property._Calendar);
+    CFReleaseIfNotNull(formatter->_property._CalendarName);
+    CFReleaseIfNotNull(formatter->_property._TwoDigitStartDate);
+    CFReleaseIfNotNull(formatter->_property._DefaultDate);
+    CFReleaseIfNotNull(formatter->_property._GregorianStartDate);
+    CFReleaseIfNotNull(formatter->_property._EraSymbols);
+    CFReleaseIfNotNull(formatter->_property._LongEraSymbols);
+    CFReleaseIfNotNull(formatter->_property._MonthSymbols);
+    CFReleaseIfNotNull(formatter->_property._ShortMonthSymbols);
+    CFReleaseIfNotNull(formatter->_property._VeryShortMonthSymbols);
+    CFReleaseIfNotNull(formatter->_property._StandaloneMonthSymbols);
+    CFReleaseIfNotNull(formatter->_property._ShortStandaloneMonthSymbols);
+    CFReleaseIfNotNull(formatter->_property._VeryShortStandaloneMonthSymbols);
+    CFReleaseIfNotNull(formatter->_property._WeekdaySymbols);
+    CFReleaseIfNotNull(formatter->_property._ShortWeekdaySymbols);
+    CFReleaseIfNotNull(formatter->_property._VeryShortWeekdaySymbols);
+    CFReleaseIfNotNull(formatter->_property._StandaloneWeekdaySymbols);
+    CFReleaseIfNotNull(formatter->_property._ShortStandaloneWeekdaySymbols);
+    CFReleaseIfNotNull(formatter->_property._VeryShortStandaloneWeekdaySymbols);
+    CFReleaseIfNotNull(formatter->_property._QuarterSymbols);
+    CFReleaseIfNotNull(formatter->_property._ShortQuarterSymbols);
+    CFReleaseIfNotNull(formatter->_property._StandaloneQuarterSymbols);
+    CFReleaseIfNotNull(formatter->_property._ShortStandaloneQuarterSymbols);
+    CFReleaseIfNotNull(formatter->_property._AMSymbol);
+    CFReleaseIfNotNull(formatter->_property._PMSymbol);
+}
+
+static CFStringRef __CFDateFormatterCreateForcedString(CFDateFormatterRef formatter, CFStringRef inString);
+
+static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringRef key, CFTypeRef value, Boolean directToICU);
+
+#define RESET_PROPERTY(C, K) \
+    if (df->_property. C) __CFDateFormatterSetProperty(df, K, df->_property. C, true);
+
+static void __ResetUDateFormat(CFDateFormatterRef df, Boolean goingToHaveCustomFormat) {
+    if (df->_df) udat_close(df->_df);
+    df->_df = NULL;
+
+    // uses _timeStyle, _dateStyle, _locale, _property._TimeZone; sets _df, _format, _defformat
+    char loc_buffer[BUFFER_SIZE];
+    loc_buffer[0] = 0;
+    CFStringRef tmpLocName = df->_locale ? CFLocaleGetIdentifier(df->_locale) : CFSTR("");
+    CFStringGetCString(tmpLocName, loc_buffer, BUFFER_SIZE, kCFStringEncodingASCII);
+
+    UChar tz_buffer[BUFFER_SIZE];
+    tz_buffer[0] = 0;
+    CFStringRef tmpTZName = df->_property._TimeZone ? CFTimeZoneGetName(df->_property._TimeZone) : CFSTR("GMT");
+    CFStringGetCharacters(tmpTZName, CFRangeMake(0, CFStringGetLength(tmpTZName)), (UniChar *)tz_buffer);
+
+    df->_property._HasCustomFormat = kCFBooleanFalse;
+
+    int32_t udstyle = 0, utstyle = 0;
+    switch (df->_dateStyle) {
+    case kCFDateFormatterNoStyle: udstyle = UDAT_NONE; break;
+    case kCFDateFormatterShortStyle: udstyle = UDAT_SHORT; break;
+    case kCFDateFormatterMediumStyle: udstyle = UDAT_MEDIUM; break;
+    case kCFDateFormatterLongStyle: udstyle = UDAT_LONG; break;
+    case kCFDateFormatterFullStyle: udstyle = UDAT_FULL; break;
+    }
+    switch (df->_timeStyle) {
+    case kCFDateFormatterNoStyle: utstyle = UDAT_NONE; break;
+    case kCFDateFormatterShortStyle: utstyle = UDAT_SHORT; break;
+    case kCFDateFormatterMediumStyle: utstyle = UDAT_MEDIUM; break;
+    case kCFDateFormatterLongStyle: utstyle = UDAT_LONG; break;
+    case kCFDateFormatterFullStyle: utstyle = UDAT_FULL; break;
+    }
+    Boolean wantRelative = (NULL != df->_property._DoesRelativeDateFormatting && df->_property._DoesRelativeDateFormatting == kCFBooleanTrue);
+    Boolean hasFormat = (NULL != df->_property._HasCustomFormat && df->_property._HasCustomFormat == kCFBooleanTrue) || goingToHaveCustomFormat;
+    if (wantRelative && !hasFormat) {
+       udstyle |= UDAT_RELATIVE;
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+    UDateFormat *icudf = udat_open((UDateFormatStyle)utstyle, (UDateFormatStyle)udstyle, loc_buffer, tz_buffer, CFStringGetLength(tmpTZName), NULL, 0, &status);
+    if (NULL == icudf || U_FAILURE(status)) {
+        return;
+    }
+    udat_setLenient(icudf, 0);
+    if (kCFDateFormatterNoStyle == df->_dateStyle && kCFDateFormatterNoStyle == df->_timeStyle) {
+        udat_applyPattern(icudf, false, NULL, 0);
+    }
+    CFStringRef calident = (CFStringRef)CFLocaleGetValue(df->_locale, kCFLocaleCalendarIdentifierKey);
+    if (calident && CFEqual(calident, kCFCalendarIdentifierGregorian)) {
+        status = U_ZERO_ERROR;
+        udat_set2DigitYearStart(icudf, -631152000000.0, &status); // 1950-01-01 00:00:00 GMT
+    }
+    df->_df = icudf;
+
+    __CFDateFormatterCustomize(df);
+
+    UChar ubuffer[BUFFER_SIZE];
+    status = U_ZERO_ERROR;
+    int32_t ret = udat_toPattern(icudf, false, ubuffer, BUFFER_SIZE, &status);
+    if (U_SUCCESS(status) && ret <= BUFFER_SIZE) {
+        CFStringRef newFormat = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)ubuffer, ret);
+        CFStringRef formatString = __CFDateFormatterCreateForcedString(df, newFormat);
+        CFIndex cnt = CFStringGetLength(formatString);
+        CFAssert1(cnt <= 1024, __kCFLogAssertion, "%s(): format string too long", __PRETTY_FUNCTION__);
+        if (df->_format != formatString && cnt <= 1024) {
+            STACK_BUFFER_DECL(UChar, ubuffer, cnt);
+            const UChar *ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)formatString);
+            if (NULL == ustr) {
+                CFStringGetCharacters(formatString, CFRangeMake(0, cnt), (UniChar *)ubuffer);
+                ustr = ubuffer;
+            }
+            UErrorCode status = U_ZERO_ERROR;
+//            udat_applyPattern(df->_df, false, ustr, cnt, &status);
+            udat_applyPattern(df->_df, false, ustr, cnt);
+            if (U_SUCCESS(status)) {
+                if (df->_format) CFRelease(df->_format);
+                df->_format = (CFStringRef)CFStringCreateCopy(CFGetAllocator(df), formatString);
+            }
+        }
+        CFRelease(formatString);
+        CFRelease(newFormat);
+    }
+    if (df->_defformat) CFRelease(df->_defformat);
+    df->_defformat = df->_format ? (CFStringRef)CFRetain(df->_format) : NULL;
+
+    RESET_PROPERTY(_IsLenient, kCFDateFormatterIsLenientKey);
+    RESET_PROPERTY(_DoesRelativeDateFormatting, kCFDateFormatterDoesRelativeDateFormattingKey);
+    RESET_PROPERTY(_Calendar, kCFDateFormatterCalendarKey);
+    RESET_PROPERTY(_CalendarName, kCFDateFormatterCalendarIdentifierKey);
+    RESET_PROPERTY(_TimeZone, kCFDateFormatterTimeZoneKey);
+    RESET_PROPERTY(_TwoDigitStartDate, kCFDateFormatterTwoDigitStartDateKey);
+    RESET_PROPERTY(_DefaultDate, kCFDateFormatterDefaultDateKey);
+    RESET_PROPERTY(_GregorianStartDate, kCFDateFormatterGregorianStartDateKey);
+    RESET_PROPERTY(_EraSymbols, kCFDateFormatterEraSymbolsKey);
+    RESET_PROPERTY(_LongEraSymbols, kCFDateFormatterLongEraSymbolsKey);
+    RESET_PROPERTY(_MonthSymbols, kCFDateFormatterMonthSymbolsKey);
+    RESET_PROPERTY(_ShortMonthSymbols, kCFDateFormatterShortMonthSymbolsKey);
+    RESET_PROPERTY(_VeryShortMonthSymbols, kCFDateFormatterVeryShortMonthSymbolsKey);
+    RESET_PROPERTY(_StandaloneMonthSymbols, kCFDateFormatterStandaloneMonthSymbolsKey);
+    RESET_PROPERTY(_ShortStandaloneMonthSymbols, kCFDateFormatterShortStandaloneMonthSymbolsKey);
+    RESET_PROPERTY(_VeryShortStandaloneMonthSymbols, kCFDateFormatterVeryShortStandaloneMonthSymbolsKey);
+    RESET_PROPERTY(_WeekdaySymbols, kCFDateFormatterWeekdaySymbolsKey);
+    RESET_PROPERTY(_ShortWeekdaySymbols, kCFDateFormatterShortWeekdaySymbolsKey);
+    RESET_PROPERTY(_VeryShortWeekdaySymbols, kCFDateFormatterVeryShortWeekdaySymbolsKey);
+    RESET_PROPERTY(_StandaloneWeekdaySymbols, kCFDateFormatterStandaloneWeekdaySymbolsKey);
+    RESET_PROPERTY(_ShortStandaloneWeekdaySymbols, kCFDateFormatterShortStandaloneWeekdaySymbolsKey);
+    RESET_PROPERTY(_VeryShortStandaloneWeekdaySymbols, kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey);
+    RESET_PROPERTY(_QuarterSymbols, kCFDateFormatterQuarterSymbolsKey);
+    RESET_PROPERTY(_ShortQuarterSymbols, kCFDateFormatterShortQuarterSymbolsKey);
+    RESET_PROPERTY(_StandaloneQuarterSymbols, kCFDateFormatterStandaloneQuarterSymbolsKey);
+    RESET_PROPERTY(_ShortStandaloneQuarterSymbols, kCFDateFormatterShortStandaloneQuarterSymbolsKey);
+    RESET_PROPERTY(_AMSymbol, kCFDateFormatterAMSymbolKey);
+    RESET_PROPERTY(_PMSymbol, kCFDateFormatterPMSymbolKey);
 }
 
 static CFTypeID __kCFDateFormatterTypeID = _kCFRuntimeNotATypeID;
@@ -76,12 +313,12 @@ static CFTypeID __kCFDateFormatterTypeID = _kCFRuntimeNotATypeID;
 static const CFRuntimeClass __CFDateFormatterClass = {
     0,
     "CFDateFormatter",
-    NULL,      // init
-    NULL,      // copy
+    NULL,        // init
+    NULL,        // copy
     __CFDateFormatterDeallocate,
     NULL,
     NULL,
-    NULL,      // 
+    NULL,        // 
     __CFDateFormatterCopyDescription
 };
 
@@ -102,189 +339,351 @@ CFDateFormatterRef CFDateFormatterCreate(CFAllocatorRef allocator, CFLocaleRef l
     if (locale) __CFGenericValidateType(locale, CFLocaleGetTypeID());
     memory = (struct __CFDateFormatter *)_CFRuntimeCreateInstance(allocator, CFDateFormatterGetTypeID(), size, NULL);
     if (NULL == memory) {
-       return NULL;
+        return NULL;
     }
     memory->_df = NULL;
     memory->_locale = NULL;
     memory->_format = NULL;
     memory->_defformat = NULL;
-    memory->_calendarName = NULL;
-    memory->_tz = NULL;
-    memory->_defaultDate = NULL;
-    if (NULL == locale) locale = CFLocaleGetSystem();
     memory->_dateStyle = dateStyle;
     memory->_timeStyle = timeStyle;
-    int32_t udstyle, utstyle;
+    memory->_property._IsLenient = NULL;
+    memory->_property._DoesRelativeDateFormatting = NULL;
+    memory->_property._HasCustomFormat = NULL;
+    memory->_property._TimeZone = NULL;
+    memory->_property._Calendar = NULL;
+    memory->_property._CalendarName = NULL;
+    memory->_property._TwoDigitStartDate = NULL;
+    memory->_property._DefaultDate = NULL;
+    memory->_property._GregorianStartDate = NULL;
+    memory->_property._EraSymbols = NULL;
+    memory->_property._LongEraSymbols = NULL;
+    memory->_property._MonthSymbols = NULL;
+    memory->_property._ShortMonthSymbols = NULL;
+    memory->_property._VeryShortMonthSymbols = NULL;
+    memory->_property._StandaloneMonthSymbols = NULL;
+    memory->_property._ShortStandaloneMonthSymbols = NULL;
+    memory->_property._VeryShortStandaloneMonthSymbols = NULL;
+    memory->_property._WeekdaySymbols = NULL;
+    memory->_property._ShortWeekdaySymbols = NULL;
+    memory->_property._VeryShortWeekdaySymbols = NULL;
+    memory->_property._StandaloneWeekdaySymbols = NULL;
+    memory->_property._ShortStandaloneWeekdaySymbols = NULL;
+    memory->_property._VeryShortStandaloneWeekdaySymbols = NULL;
+    memory->_property._QuarterSymbols = NULL;
+    memory->_property._ShortQuarterSymbols = NULL;
+    memory->_property._StandaloneQuarterSymbols = NULL;
+    memory->_property._ShortStandaloneQuarterSymbols = NULL;
+    memory->_property._AMSymbol = NULL;
+    memory->_property._PMSymbol = NULL;
+
     switch (dateStyle) {
-    case kCFDateFormatterNoStyle: udstyle = UDAT_NONE; break;
-    case kCFDateFormatterShortStyle: udstyle = UDAT_SHORT; break;
-    case kCFDateFormatterMediumStyle: udstyle = UDAT_MEDIUM; break;
-    case kCFDateFormatterLongStyle: udstyle = UDAT_LONG; break;
-    case kCFDateFormatterFullStyle: udstyle = UDAT_FULL; break;
+    case kCFDateFormatterNoStyle:
+    case kCFDateFormatterShortStyle:
+    case kCFDateFormatterMediumStyle:
+    case kCFDateFormatterLongStyle:
+    case kCFDateFormatterFullStyle: break;
     default:
-       CFAssert2(0, __kCFLogAssertion, "%s(): unknown date style %d", __PRETTY_FUNCTION__, dateStyle);
-       udstyle = UDAT_MEDIUM;
-       memory->_dateStyle = kCFDateFormatterMediumStyle;
-       break;
+        CFAssert2(0, __kCFLogAssertion, "%s(): unknown date style %d", __PRETTY_FUNCTION__, dateStyle);
+        memory->_dateStyle = kCFDateFormatterMediumStyle;
+        break;
     }
     switch (timeStyle) {
-    case kCFDateFormatterNoStyle: utstyle = UDAT_NONE; break;
-    case kCFDateFormatterShortStyle: utstyle = UDAT_SHORT; break;
-    case kCFDateFormatterMediumStyle: utstyle = UDAT_MEDIUM; break;
-    case kCFDateFormatterLongStyle: utstyle = UDAT_LONG; break;
-    case kCFDateFormatterFullStyle: utstyle = UDAT_FULL; break;
+    case kCFDateFormatterNoStyle:
+    case kCFDateFormatterShortStyle:
+    case kCFDateFormatterMediumStyle:
+    case kCFDateFormatterLongStyle:
+    case kCFDateFormatterFullStyle: break;
     default:
-       CFAssert2(0, __kCFLogAssertion, "%s(): unknown time style %d", __PRETTY_FUNCTION__, timeStyle);
-       utstyle = UDAT_MEDIUM;
-       memory->_timeStyle = kCFDateFormatterMediumStyle;
-       break;
+        CFAssert2(0, __kCFLogAssertion, "%s(): unknown time style %d", __PRETTY_FUNCTION__, timeStyle);
+        memory->_timeStyle = kCFDateFormatterMediumStyle;
+        break;
     }
-    CFStringRef localeName = locale ? CFLocaleGetIdentifier(locale) : CFSTR("");
-    char buffer[BUFFER_SIZE];
-    const char *cstr = CFStringGetCStringPtr(localeName, kCFStringEncodingASCII);
-    if (NULL == cstr) {
-       if (CFStringGetCString(localeName, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) cstr = buffer;
-    }
-    if (NULL == cstr) {
-       CFRelease(memory);
+
+    memory->_locale = locale ? CFLocaleCreateCopy(allocator, locale) : (CFLocaleRef)CFRetain(CFLocaleGetSystem());
+    memory->_property._TimeZone = CFTimeZoneCopyDefault();
+    __ResetUDateFormat(memory, false);
+    if (!memory->_df) {
+        CFRelease(memory);
        return NULL;
     }
-    UChar ubuffer[BUFFER_SIZE];
-    memory->_tz = CFTimeZoneCopyDefault();
-    CFStringRef tznam = CFTimeZoneGetName(memory->_tz);
-    CFIndex cnt = CFStringGetLength(tznam);
-    if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
-    CFStringGetCharacters(tznam, CFRangeMake(0, cnt), (UniChar *)ubuffer);
-    UErrorCode status = U_ZERO_ERROR;
-    memory->_df = udat_open((UDateFormatStyle)utstyle, (UDateFormatStyle)udstyle, cstr, ubuffer, cnt, NULL, 0, &status);
-    CFAssert2(memory->_df, __kCFLogAssertion, "%s(): error (%d) creating date formatter", __PRETTY_FUNCTION__, status);
-    if (NULL == memory->_df) {
-       CFRelease(memory->_tz);
-       CFRelease(memory);
-       return NULL;
+    return (CFDateFormatterRef)memory;
+}
+
+extern CFDictionaryRef __CFLocaleGetPrefs(CFLocaleRef locale);
+
+static void __substituteFormatStringFromPrefsDFRelative(CFDateFormatterRef formatter) {
+    CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale);
+
+    CFIndex dateLen = -1;
+    UChar dateBuffer[BUFFER_SIZE];
+    if (kCFDateFormatterNoStyle != formatter->_dateStyle) {
+        CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUDateFormatStrings")) : NULL;
+        if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
+            CFStringRef key;
+            switch (formatter->_dateStyle) {
+            case kCFDateFormatterShortStyle: key = CFSTR("1"); break;
+            case kCFDateFormatterMediumStyle: key = CFSTR("2"); break;
+            case kCFDateFormatterLongStyle: key = CFSTR("3"); break;
+            case kCFDateFormatterFullStyle: key = CFSTR("4"); break;
+            default: key = CFSTR("0"); break;
+            }
+            CFStringRef pref = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key);
+            if (NULL != pref && CFGetTypeID(pref) == CFStringGetTypeID()) {
+                dateLen = __CFMin(CFStringGetLength(pref), BUFFER_SIZE);
+                CFStringGetCharacters(pref, CFRangeMake(0, dateLen), (UniChar *)dateBuffer);
+            }
+        }
     }
-    udat_setLenient(memory->_df, 0);
-    if (kCFDateFormatterNoStyle == dateStyle && kCFDateFormatterNoStyle == timeStyle) {
-       udat_applyPattern(memory->_df, false, NULL, 0);
+    if (-1 == dateLen) {
+        UErrorCode status = U_ZERO_ERROR;
+        int32_t ret = udat_toPatternRelativeDate(formatter->_df, dateBuffer, BUFFER_SIZE, &status);
+        if (!U_FAILURE(status)) {
+            dateLen = ret;
+        }
     }
-    CFTypeRef calident = CFLocaleGetValue(locale, kCFLocaleCalendarIdentifier);
-    if (calident && CFEqual(calident, kCFGregorianCalendar)) {
-       status = U_ZERO_ERROR;
-       udat_set2DigitYearStart(memory->_df, -631152000000.0, &status); // 1950-01-01 00:00:00 GMT
+
+    CFIndex timeLen = -1;
+    UChar timeBuffer[BUFFER_SIZE];
+    if (kCFDateFormatterNoStyle != formatter->_timeStyle) {
+        CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUTimeFormatStrings")) : NULL;
+        if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
+            CFStringRef key;
+            switch (formatter->_timeStyle) {
+            case kCFDateFormatterShortStyle: key = CFSTR("1"); break;
+            case kCFDateFormatterMediumStyle: key = CFSTR("2"); break;
+            case kCFDateFormatterLongStyle: key = CFSTR("3"); break;
+            case kCFDateFormatterFullStyle: key = CFSTR("4"); break;
+            default: key = CFSTR("0"); break;
+            }
+            CFStringRef pref = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key);
+            if (NULL != pref && CFGetTypeID(pref) == CFStringGetTypeID()) {
+                timeLen = __CFMin(CFStringGetLength(pref), BUFFER_SIZE);
+                CFStringGetCharacters(pref, CFRangeMake(0, timeLen), (UniChar *)timeBuffer);
+            }
+        }
     }
-    memory->_locale = locale ? CFLocaleCreateCopy(allocator, locale) : CFLocaleGetSystem();
-    __CFDateFormatterCustomize(memory);
-    status = U_ZERO_ERROR;
-    int32_t ret = udat_toPattern(memory->_df, false, ubuffer, BUFFER_SIZE, &status);
-    if (U_SUCCESS(status) && ret <= BUFFER_SIZE) {
-       memory->_format = CFStringCreateWithCharacters(allocator, (const UniChar *)ubuffer, ret);
+    if (-1 == timeLen) {
+        UErrorCode status = U_ZERO_ERROR;
+        int32_t ret = udat_toPatternRelativeTime(formatter->_df, timeBuffer, BUFFER_SIZE, &status);
+        if (!U_FAILURE(status)) {
+            timeLen = ret;
+        }
     }
-    memory->_defformat = memory->_format ? (CFStringRef)CFRetain(memory->_format) : NULL;
-    return (CFDateFormatterRef)memory;
-}
 
-extern CFDictionaryRef __CFLocaleGetPrefs(CFLocaleRef locale);
+    UErrorCode status = U_ZERO_ERROR;
+    udat_applyPatternRelative(formatter->_df, (0 <= dateLen) ? dateBuffer : NULL, (0 <= dateLen) ? dateLen : 0, (0 <= timeLen) ? timeBuffer : NULL, (0 <= timeLen) ? timeLen : 0, &status);
+}
 
 static void __substituteFormatStringFromPrefsDF(CFDateFormatterRef formatter, bool doTime) {
     CFIndex formatStyle = doTime ? formatter->_timeStyle : formatter->_dateStyle;
     CFStringRef prefName = doTime ? CFSTR("AppleICUTimeFormatStrings") : CFSTR("AppleICUDateFormatStrings");
     if (kCFDateFormatterNoStyle != formatStyle) {
-       CFStringRef pref = NULL;
-       CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale);
-       CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, prefName) : NULL;
-       if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
-           CFStringRef key;
-           switch (formatStyle) {
-           case kCFDateFormatterShortStyle: key = CFSTR("1"); break;
-           case kCFDateFormatterMediumStyle: key = CFSTR("2"); break;
-           case kCFDateFormatterLongStyle: key = CFSTR("3"); break;
-           case kCFDateFormatterFullStyle: key = CFSTR("4"); break;
-           default: key = CFSTR("0"); break;
-           }
-           pref = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key);
-       }
-       if (NULL != pref && CFGetTypeID(pref) == CFStringGetTypeID()) {
-           int32_t icustyle = UDAT_NONE;
-           switch (formatStyle) {
-           case kCFDateFormatterShortStyle: icustyle = UDAT_SHORT; break;
-           case kCFDateFormatterMediumStyle: icustyle = UDAT_MEDIUM; break;
-           case kCFDateFormatterLongStyle: icustyle = UDAT_LONG; break;
-           case kCFDateFormatterFullStyle: icustyle = UDAT_FULL; break;
-           }
-           CFStringRef localeName = CFLocaleGetIdentifier(formatter->_locale);
-           char buffer[BUFFER_SIZE];
-           const char *cstr = CFStringGetCStringPtr(localeName, kCFStringEncodingASCII);
-           if (NULL == cstr) {
-               if (CFStringGetCString(localeName, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) cstr = buffer;
-           }
-           UErrorCode status = U_ZERO_ERROR;
-           UDateFormat *df = udat_open((UDateFormatStyle)(doTime ? icustyle : UDAT_NONE), (UDateFormatStyle)(doTime ? UDAT_NONE : icustyle), cstr, NULL, 0, NULL, 0, &status);
-           if (NULL != df) {
-               UChar ubuffer[BUFFER_SIZE];
-               status = U_ZERO_ERROR;
-               int32_t date_len = udat_toPattern(df, false, ubuffer, BUFFER_SIZE, &status);
-               if (U_SUCCESS(status) && date_len <= BUFFER_SIZE) {
-                   CFStringRef dateString = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)ubuffer, date_len);
-                   status = U_ZERO_ERROR;
-                   int32_t formatter_len = udat_toPattern(formatter->_df, false, ubuffer, BUFFER_SIZE, &status);
-                   if (U_SUCCESS(status) && formatter_len <= BUFFER_SIZE) {
-                       CFMutableStringRef formatString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
-                       CFStringAppendCharacters(formatString, (UniChar *)ubuffer, formatter_len);
-                       // find dateString inside formatString, substitute the pref in that range
-                       CFRange result;
-                       if (CFStringFindWithOptions(formatString, dateString, CFRangeMake(0, formatter_len), 0, &result)) {
-                           CFStringReplace(formatString, result, pref);
-                           int32_t new_len = CFStringGetLength(formatString);
-                           STACK_BUFFER_DECL(UChar, new_buffer, new_len);
-                           const UChar *new_ustr = (UChar *)CFStringGetCharactersPtr(formatString);
-                           if (NULL == new_ustr) {
-                               CFStringGetCharacters(formatString, CFRangeMake(0, new_len), (UniChar *)new_buffer);
-                               new_ustr = new_buffer;
-                               }
-                           status = U_ZERO_ERROR;
-//                         udat_applyPattern(formatter->_df, false, new_ustr, new_len, &status);
-                           udat_applyPattern(formatter->_df, false, new_ustr, new_len);
-                       }
-                       CFRelease(formatString);
-                   }
-                   CFRelease(dateString);
-               }
-               udat_close(df);
-           }
-       }
+        CFStringRef pref = NULL;
+        CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale);
+        CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, prefName) : NULL;
+        if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
+            CFStringRef key;
+            switch (formatStyle) {
+            case kCFDateFormatterShortStyle: key = CFSTR("1"); break;
+            case kCFDateFormatterMediumStyle: key = CFSTR("2"); break;
+            case kCFDateFormatterLongStyle: key = CFSTR("3"); break;
+            case kCFDateFormatterFullStyle: key = CFSTR("4"); break;
+            default: key = CFSTR("0"); break;
+            }
+            pref = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)metapref, key);
+        }
+        if (NULL != pref && CFGetTypeID(pref) == CFStringGetTypeID()) {
+            int32_t icustyle = UDAT_NONE;
+            switch (formatStyle) {
+            case kCFDateFormatterShortStyle: icustyle = UDAT_SHORT; break;
+            case kCFDateFormatterMediumStyle: icustyle = UDAT_MEDIUM; break;
+            case kCFDateFormatterLongStyle: icustyle = UDAT_LONG; break;
+            case kCFDateFormatterFullStyle: icustyle = UDAT_FULL; break;
+            }
+            CFStringRef localeName = CFLocaleGetIdentifier(formatter->_locale);
+            char buffer[BUFFER_SIZE];
+            const char *cstr = CFStringGetCStringPtr(localeName, kCFStringEncodingASCII);
+            if (NULL == cstr) {
+                if (CFStringGetCString(localeName, buffer, BUFFER_SIZE, kCFStringEncodingASCII)) cstr = buffer;
+            }
+            UErrorCode status = U_ZERO_ERROR;
+            UDateFormat *df = udat_open((UDateFormatStyle)(doTime ? icustyle : UDAT_NONE), (UDateFormatStyle)(doTime ? UDAT_NONE : icustyle), cstr, NULL, 0, NULL, 0, &status);
+            if (NULL != df) {
+                UChar ubuffer[BUFFER_SIZE];
+                status = U_ZERO_ERROR;
+                int32_t date_len = udat_toPattern(df, false, ubuffer, BUFFER_SIZE, &status);
+                if (U_SUCCESS(status) && date_len <= BUFFER_SIZE) {
+                    CFStringRef dateString = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)ubuffer, date_len);
+                    status = U_ZERO_ERROR;
+                    int32_t formatter_len = udat_toPattern(formatter->_df, false, ubuffer, BUFFER_SIZE, &status);
+                    if (U_SUCCESS(status) && formatter_len <= BUFFER_SIZE) {
+                        CFMutableStringRef formatString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+                        CFStringAppendCharacters(formatString, (UniChar *)ubuffer, formatter_len);
+                        // find dateString inside formatString, substitute the pref in that range
+                        CFRange result;
+                        if (CFStringFindWithOptions(formatString, dateString, CFRangeMake(0, formatter_len), 0, &result)) {
+                            CFStringReplace(formatString, result, pref);
+                            int32_t new_len = CFStringGetLength(formatString);
+                            STACK_BUFFER_DECL(UChar, new_buffer, new_len);
+                            const UChar *new_ustr = (UChar *)CFStringGetCharactersPtr(formatString);
+                            if (NULL == new_ustr) {
+                                CFStringGetCharacters(formatString, CFRangeMake(0, new_len), (UniChar *)new_buffer);
+                                new_ustr = new_buffer;
+                                }
+                            status = U_ZERO_ERROR;
+//                            udat_applyPattern(formatter->_df, false, new_ustr, new_len, &status);
+                            udat_applyPattern(formatter->_df, false, new_ustr, new_len);
+                        }
+                        CFRelease(formatString);
+                    }
+                    CFRelease(dateString);
+                }
+                udat_close(df);
+            }
+        }
     }
 }
 
 static void __CFDateFormatterApplySymbolPrefs(const void *key, const void *value, void *context) {
     if (CFGetTypeID(key) == CFStringGetTypeID() && CFGetTypeID(value) == CFArrayGetTypeID()) {
-       CFDateFormatterRef formatter = (CFDateFormatterRef)context;
-       UDateFormatSymbolType sym = (UDateFormatSymbolType)CFStringGetIntValue((CFStringRef)key);
-       CFArrayRef array = (CFArrayRef)value;
-       CFIndex idx, cnt = CFArrayGetCount(array);
-       for (idx = 0; idx < cnt; idx++) {
-           CFStringRef item = (CFStringRef)CFArrayGetValueAtIndex(array, idx);
-           if (CFGetTypeID(item) != CFStringGetTypeID()) continue;
-           CFIndex item_cnt = CFStringGetLength(item);
-           STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt));
-           UChar *item_ustr = (UChar *)CFStringGetCharactersPtr(item);
-           if (NULL == item_ustr) {
-               item_cnt = __CFMin(BUFFER_SIZE, item_cnt);
-               CFStringGetCharacters(item, CFRangeMake(0, item_cnt), (UniChar *)item_buffer);
-               item_ustr = item_buffer;
-           }
-           UErrorCode status = U_ZERO_ERROR;
-           udat_setSymbols(formatter->_df, sym, idx, item_ustr, item_cnt, &status);
-       }
+        CFDateFormatterRef formatter = (CFDateFormatterRef)context;
+        UDateFormatSymbolType sym = (UDateFormatSymbolType)CFStringGetIntValue((CFStringRef)key);
+        CFArrayRef array = (CFArrayRef)value;
+        CFIndex idx, cnt = CFArrayGetCount(array);
+        for (idx = 0; idx < cnt; idx++) {
+            CFStringRef item = (CFStringRef)CFArrayGetValueAtIndex(array, idx);
+            if (CFGetTypeID(item) != CFStringGetTypeID()) continue;
+            CFIndex item_cnt = CFStringGetLength(item);
+            STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt));
+            UChar *item_ustr = (UChar *)CFStringGetCharactersPtr(item);
+            if (NULL == item_ustr) {
+                item_cnt = __CFMin(BUFFER_SIZE, item_cnt);
+                CFStringGetCharacters(item, CFRangeMake(0, item_cnt), (UniChar *)item_buffer);
+                item_ustr = item_buffer;
+            }
+            UErrorCode status = U_ZERO_ERROR;
+            udat_setSymbols(formatter->_df, sym, idx, item_ustr, item_cnt, &status);
+        }
     }
 }
 
+static CFStringRef __CFDateFormatterCreateForcedString(CFDateFormatterRef formatter, CFStringRef inString) {
+    if (!inString) return NULL;
+    Boolean doForce24 = false, doForce12 = false;
+    CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale);
+    CFPropertyListRef pref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUForce24HourTime")) : NULL;
+    if (NULL != pref && CFGetTypeID(pref) == CFBooleanGetTypeID()) {
+        doForce24 = CFBooleanGetValue((CFBooleanRef)pref);
+    }
+    pref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUForce12HourTime")) : NULL;
+    if (NULL != pref && CFGetTypeID(pref) == CFBooleanGetTypeID()) {
+        doForce12 = CFBooleanGetValue((CFBooleanRef)pref);
+    }
+    if (!doForce24 && !doForce12) return (CFStringRef)CFRetain(inString);
+    if (doForce24) doForce12 = false; // if both are set, Force24 wins, period
+    CFMutableStringRef outString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+    CFIndex cnt = CFStringGetLength(inString);
+    CFIndex lastSecond = -1, lastMinute = -1, firstHour = -1;
+    Boolean isInQuote = false, hasA = false, had12Hour = false, had24Hour = false;
+    for (CFIndex idx = 0; idx < cnt; idx++) {
+        Boolean emit = true;
+        UniChar ch = CFStringGetCharacterAtIndex(inString, idx);
+        switch (ch) {
+        case '\'': isInQuote = !isInQuote; break;
+        case 'h': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had12Hour = true; if (doForce24) ch = 'H';} break; // switch 12-hour to 24-hour
+        case 'K': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had12Hour = true; if (doForce24) ch = 'k';} break; // switch 12-hour to 24-hour
+        case 'H': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had24Hour = true; if (doForce12) ch = 'h';} break; // switch 24-hour to 12-hour
+        case 'k': if (!isInQuote) {if (-1 == firstHour) firstHour = CFStringGetLength(outString); had24Hour = true; if (doForce12) ch = 'K';} break; // switch 24-hour to 12-hour
+        case 'm': if (!isInQuote) lastMinute = CFStringGetLength(outString); break;
+        case 's': if (!isInQuote) lastSecond = CFStringGetLength(outString); break;
+        case 'a': if (!isInQuote) hasA = true;
+            if (!isInQuote && doForce24) {
+                // skip 'a' and one optional trailing space
+                emit = false;
+                if (idx + 1 < cnt && ' ' == CFStringGetCharacterAtIndex(inString, idx + 1)) idx++;
+            }
+            break;
+        case ' ':
+            if (!isInQuote && doForce24) {
+                // if next character is 'a' AND we have seen the hour designator, skip space and 'a'
+                if (idx + 1 < cnt && 'a' == CFStringGetCharacterAtIndex(inString, idx + 1) && -1 != firstHour) {
+                    emit = false;
+                    idx++;
+                }
+            }
+            break;
+        }
+        if (emit) CFStringAppendCharacters(outString, &ch, 1);
+    }
+    if (doForce12 && !hasA && had24Hour) {
+        CFStringRef locName = CFLocaleGetIdentifier(formatter->_locale);
+        if (-1 != firstHour && (CFStringHasPrefix(locName, CFSTR("ko")) || CFEqual(locName, CFSTR("zh_SG")))) {
+            CFStringInsert(outString, firstHour, CFSTR("a "));
+        } else if (-1 != firstHour && (CFStringHasPrefix(locName, CFSTR("zh")) || CFStringHasPrefix(locName, CFSTR("ja")))) {
+            CFStringInsert(outString, firstHour, CFSTR("a"));
+        } else {
+            CFIndex lastPos = (-1 != lastSecond) ? lastSecond : ((-1 != lastMinute) ? lastMinute : -1);
+            if (-1 != lastPos) {
+                cnt = CFStringGetLength(outString);
+                lastPos++;
+                UniChar ch = (lastPos < cnt) ? CFStringGetCharacterAtIndex(outString, lastPos) : 0;
+                switch (ch) {
+                case '\"': lastPos++; break;
+                case '\'':;
+                   again:;
+                    do {
+                        lastPos++;
+                        ch = (lastPos < cnt) ? CFStringGetCharacterAtIndex(outString, lastPos) : 0;
+                    } while ('\'' != ch && '\0' != ch);
+                    if ('\'' == ch) lastPos++;
+                   ch = (lastPos < cnt) ? CFStringGetCharacterAtIndex(outString, lastPos) : 0;
+                    if ('\'' == ch) goto again;
+                    break;
+                }
+                CFStringInsert(outString, lastPos, CFSTR(" a"));
+            }
+        }
+    }
+    return outString;
+}
+
 static void __CFDateFormatterCustomize(CFDateFormatterRef formatter) {
-    __substituteFormatStringFromPrefsDF(formatter, false);
-    __substituteFormatStringFromPrefsDF(formatter, true);
+    Boolean wantRelative = (NULL != formatter->_property._DoesRelativeDateFormatting && formatter->_property._DoesRelativeDateFormatting == kCFBooleanTrue);
+    Boolean hasFormat = (NULL != formatter->_property._HasCustomFormat && formatter->_property._HasCustomFormat == kCFBooleanTrue);
+    if (wantRelative && !hasFormat) {
+        __substituteFormatStringFromPrefsDFRelative(formatter);
+    } else {
+        __substituteFormatStringFromPrefsDF(formatter, false);
+        __substituteFormatStringFromPrefsDF(formatter, true);
+    }
     CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale);
     CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleICUDateTimeSymbols")) : NULL;
     if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
-       CFDictionaryApplyFunction((CFDictionaryRef)metapref, __CFDateFormatterApplySymbolPrefs, formatter);
+        CFDictionaryApplyFunction((CFDictionaryRef)metapref, __CFDateFormatterApplySymbolPrefs, formatter);
+    }
+    metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleFirstWeekday")) : NULL;
+    CFStringRef calID = (CFStringRef)CFLocaleGetValue(formatter->_locale, kCFLocaleCalendarIdentifierKey);
+    if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
+        metapref = (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)metapref, calID);
+    }
+    if (NULL != metapref && CFGetTypeID(metapref) == CFNumberGetTypeID()) {
+        CFIndex wkdy;
+        if (CFNumberGetValue((CFNumberRef)metapref, kCFNumberCFIndexType, &wkdy)) {
+            UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
+            if (cal) ucal_setAttribute(cal, UCAL_FIRST_DAY_OF_WEEK, wkdy);
+        }
+    }
+    metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleMinDaysInFirstWeek")) : NULL;
+    if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
+        metapref = (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)metapref, calID);
+    }
+    if (NULL != metapref && CFGetTypeID(metapref) == CFNumberGetTypeID()) {
+        CFIndex mwd;
+        if (CFNumberGetValue((CFNumberRef)metapref, kCFNumberCFIndexType, &mwd)) {
+            UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
+            if (cal) ucal_setAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK, mwd);
+        }
     }
 }
 
@@ -311,23 +710,26 @@ CFStringRef CFDateFormatterGetFormat(CFDateFormatterRef formatter) {
 void CFDateFormatterSetFormat(CFDateFormatterRef formatter, CFStringRef formatString) {
     __CFGenericValidateType(formatter, CFDateFormatterGetTypeID());
     __CFGenericValidateType(formatString, CFStringGetTypeID());
+    formatString = __CFDateFormatterCreateForcedString(formatter, formatString);
     CFIndex cnt = CFStringGetLength(formatString);
     CFAssert1(cnt <= 1024, __kCFLogAssertion, "%s(): format string too long", __PRETTY_FUNCTION__);
     if (formatter->_format != formatString && cnt <= 1024) {
-       STACK_BUFFER_DECL(UChar, ubuffer, cnt);
-       const UChar *ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)formatString);
-       if (NULL == ustr) {
-           CFStringGetCharacters(formatString, CFRangeMake(0, cnt), (UniChar *)ubuffer);
-           ustr = ubuffer;
-       }
-       UErrorCode status = U_ZERO_ERROR;
-//     udat_applyPattern(formatter->_df, false, ustr, cnt, &status);
-       udat_applyPattern(formatter->_df, false, ustr, cnt);
-       if (U_SUCCESS(status)) {
-           if (formatter->_format) CFRelease(formatter->_format);
-           formatter->_format = (CFStringRef)CFStringCreateCopy(CFGetAllocator(formatter), formatString);
-       }
+        __ResetUDateFormat(formatter, true);
+        STACK_BUFFER_DECL(UChar, ubuffer, cnt);
+        const UChar *ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)formatString);
+        if (NULL == ustr) {
+            CFStringGetCharacters(formatString, CFRangeMake(0, cnt), (UniChar *)ubuffer);
+            ustr = ubuffer;
+        }
+        UErrorCode status = U_ZERO_ERROR;
+//        udat_applyPattern(formatter->_df, false, ustr, cnt, &status);
+        udat_applyPattern(formatter->_df, false, ustr, cnt);
+        if (U_SUCCESS(status)) {
+            if (formatter->_format) CFRelease(formatter->_format);
+            formatter->_format = (CFStringRef)CFStringCreateCopy(CFGetAllocator(formatter), formatString);
+        }
     }
+    if (formatString) CFRelease(formatString);
 }
 
 CFStringRef CFDateFormatterCreateStringWithDate(CFAllocatorRef allocator, CFDateFormatterRef formatter, CFDateRef date) {
@@ -348,14 +750,14 @@ CFStringRef CFDateFormatterCreateStringWithAbsoluteTime(CFAllocatorRef allocator
     UDate ud = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0 + 0.5;
     used = udat_format(formatter->_df, ud, ubuffer, cnt, NULL, &status);
     if (status == U_BUFFER_OVERFLOW_ERROR || cnt < used) {
-       cnt = used + 1;
-       ustr = (UChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UChar) * cnt, 0);
-       status = U_ZERO_ERROR;
-       used = udat_format(formatter->_df, ud, ustr, cnt, NULL, &status);
+        cnt = used + 1;
+        ustr = (UChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UChar) * cnt, 0);
+        status = U_ZERO_ERROR;
+        used = udat_format(formatter->_df, ud, ustr, cnt, NULL, &status);
     }
     CFStringRef string = NULL;
     if (U_SUCCESS(status)) {
-       string = CFStringCreateWithCharacters(allocator, (const UniChar *)(ustr ? ustr : ubuffer), used);
+        string = CFStringCreateWithCharacters(allocator, (const UniChar *)(ustr ? ustr : ubuffer), used);
     }
     if (ustr) CFAllocatorDeallocate(kCFAllocatorSystemDefault, ustr);
     return string;
@@ -368,7 +770,7 @@ CFDateRef CFDateFormatterCreateDateFromString(CFAllocatorRef allocator, CFDateFo
     __CFGenericValidateType(string, CFStringGetTypeID());
     CFAbsoluteTime at;
     if (CFDateFormatterGetAbsoluteTimeFromString(formatter, string, rangep, &at)) {
-       return CFDateCreate(allocator, at);
+        return CFDateCreate(allocator, at);
     }
     return NULL;
 }
@@ -386,205 +788,305 @@ Boolean CFDateFormatterGetAbsoluteTimeFromString(CFDateFormatterRef formatter, C
     const UChar *ustr = (UChar *)CFStringGetCharactersPtr(string);
     STACK_BUFFER_DECL(UChar, ubuffer, (NULL == ustr) ? range.length : 1);
     if (NULL == ustr) {
-       CFStringGetCharacters(string, range, (UniChar *)ubuffer);
-       ustr = ubuffer;
+        CFStringGetCharacters(string, range, (UniChar *)ubuffer);
+        ustr = ubuffer;
     } else {
         ustr += range.location;
     }
     UDate udate;
     int32_t dpos = 0;
     UErrorCode status = U_ZERO_ERROR;
-    if (formatter->_defaultDate) {
-       CFAbsoluteTime at = CFDateGetAbsoluteTime(formatter->_defaultDate);
-       udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0;
-       UDateFormat *df2 = udat_clone(formatter->_df, &status);
-       UCalendar *cal2 = (UCalendar *)udat_getCalendar(df2);
-       ucal_setMillis(cal2, udate, &status);
+    if (formatter->_property._DefaultDate) {
+        CFAbsoluteTime at = CFDateGetAbsoluteTime(formatter->_property._DefaultDate);
+        udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0;
+        UDateFormat *df2 = udat_clone(formatter->_df, &status);
+        UCalendar *cal2 = (UCalendar *)udat_getCalendar(df2);
+        ucal_setMillis(cal2, udate, &status);
         udat_parseCalendar(formatter->_df, cal2, ustr, range.length, &dpos, &status);
-       udate = ucal_getMillis(cal2, &status);
-       udat_close(df2);
+        udate = ucal_getMillis(cal2, &status);
+        udat_close(df2);
     } else {
         udate = udat_parse(formatter->_df, ustr, range.length, &dpos, &status);
     }
     if (rangep) rangep->length = dpos;
     if (U_FAILURE(status)) {
-       return false;
+        return false;
     }
     if (atp) {
-       *atp = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
+        *atp = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
     }
     return true;
 }
 
-#define SET_SYMBOLS_ARRAY(ICU_CODE, INDEX_BASE) \
-        __CFGenericValidateType(value, CFArrayGetTypeID()); \
-       CFArrayRef array = (CFArrayRef)value; \
-       CFIndex idx, cnt = CFArrayGetCount(array); \
-       for (idx = 0; idx < cnt; idx++) { \
-           CFStringRef item = (CFStringRef)CFArrayGetValueAtIndex(array, idx); \
-           __CFGenericValidateType(item, CFStringGetTypeID()); \
-           CFIndex item_cnt = CFStringGetLength(item); \
-           STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt)); \
-           UChar *item_ustr = (UChar *)CFStringGetCharactersPtr(item); \
-           if (NULL == item_ustr) { \
-               item_cnt = __CFMin(BUFFER_SIZE, item_cnt); \
-               CFStringGetCharacters(item, CFRangeMake(0, item_cnt), (UniChar *)item_buffer); \
-               item_ustr = item_buffer; \
-           } \
-           status = U_ZERO_ERROR; \
-           udat_setSymbols(formatter->_df, ICU_CODE, idx + INDEX_BASE, item_ustr, item_cnt, &status); \
+static void __CFDateFormatterSetSymbolsArray(UDateFormat *icudf, int32_t icucode, int index_base, CFTypeRef value) {
+    UErrorCode status = U_ZERO_ERROR;
+    __CFGenericValidateType(value, CFArrayGetTypeID());
+    CFArrayRef array = (CFArrayRef)value;
+    CFIndex idx, cnt = CFArrayGetCount(array);
+    for (idx = 0; idx < cnt; idx++) {
+       CFStringRef item = (CFStringRef)CFArrayGetValueAtIndex(array, idx);
+       __CFGenericValidateType(item, CFStringGetTypeID());
+       CFIndex item_cnt = CFStringGetLength(item);
+       STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt));
+       UChar *item_ustr = (UChar *)CFStringGetCharactersPtr(item);
+       if (NULL == item_ustr) {
+           item_cnt = __CFMin(BUFFER_SIZE, item_cnt);
+           CFStringGetCharacters(item, CFRangeMake(0, item_cnt), (UniChar *)item_buffer);
+           item_ustr = item_buffer;
+       }
+       status = U_ZERO_ERROR;
+       udat_setSymbols(icudf, (UDateFormatSymbolType)icucode, idx + index_base, item_ustr, item_cnt, &status);
+    }
+}
+
+static CFArrayRef __CFDateFormatterGetSymbolsArray(UDateFormat *icudf, int32_t icucode, int index_base) {
+    UErrorCode status = U_ZERO_ERROR;
+    CFIndex idx, cnt = udat_countSymbols(icudf, (UDateFormatSymbolType)icucode) - index_base;
+    STACK_BUFFER_DECL(CFStringRef, strings, cnt);
+    for (idx = 0; idx < cnt; idx++) {
+        UChar ubuffer[BUFFER_SIZE];
+       CFStringRef str = NULL;
+       status = U_ZERO_ERROR;
+       CFIndex ucnt = udat_getSymbols(icudf, (UDateFormatSymbolType)icucode, idx + index_base, ubuffer, BUFFER_SIZE, &status);
+       if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
+           str = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)ubuffer, ucnt);
        }
+       strings[idx] = !str ? (CFStringRef)CFRetain(CFSTR("<error>")) : str;
+    }
+    CFArrayRef array = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)strings, cnt, &kCFTypeArrayCallBacks);
+    while (cnt--) {
+       CFRelease(strings[cnt]);
+    }
+    return array;
+}
 
-void CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringRef key, CFTypeRef value) {
+#define SET_SYMBOLS_ARRAY(A, B, C) \
+       if (!directToICU) { \
+           oldProperty = formatter->_property. C; \
+           formatter->_property. C = NULL; \
+       } \
+        __CFDateFormatterSetSymbolsArray(formatter->_df, A, B, value); \
+       if (!directToICU) { \
+           formatter->_property. C = __CFDateFormatterGetSymbolsArray(formatter->_df, A, B); \
+       }
+
+static void __CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringRef key, CFTypeRef value, Boolean directToICU) {
     __CFGenericValidateType(formatter, CFDateFormatterGetTypeID());
     __CFGenericValidateType(key, CFStringGetTypeID());
+    CFTypeRef oldProperty = NULL;
     UErrorCode status = U_ZERO_ERROR;
     UChar ubuffer[BUFFER_SIZE];
 
-    if (kCFDateFormatterIsLenient == key) {
-       __CFGenericValidateType(value, CFBooleanGetTypeID());
-       udat_setLenient(formatter->_df, (kCFBooleanTrue == value));
-    } else if (kCFDateFormatterCalendar == key) {
-       __CFGenericValidateType(value, CFCalendarGetTypeID());
-       CFStringRef localeName = CFLocaleGetIdentifier(formatter->_locale);
-       CFDictionaryRef components = CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault, localeName);
-       CFMutableDictionaryRef mcomponents = CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault, 0, components);
-       CFDictionarySetValue(mcomponents, kCFLocaleCalendarIdentifier, CFCalendarGetIdentifier((CFCalendarRef)value));
-       localeName = CFLocaleCreateLocaleIdentifierFromComponents(kCFAllocatorSystemDefault, mcomponents);
-       CFRelease(mcomponents);
-       CFRelease(components);
-       CFLocaleRef newLocale = CFLocaleCreate(CFGetAllocator(formatter->_locale), localeName);
-       CFRelease(localeName);
-       CFRelease(formatter->_locale);
-       formatter->_locale = newLocale;
-       UCalendar *cal = __CFCalendarCreateUCalendar(NULL, CFLocaleGetIdentifier(formatter->_locale), formatter->_tz);
-       if (cal) udat_setCalendar(formatter->_df, cal);
-       if (cal) ucal_close(cal);
-    } else if (kCFDateFormatterCalendarIdentifier == key || kCFDateFormatterCalendarName == key) {
-       __CFGenericValidateType(value, CFStringGetTypeID());
-       CFStringRef localeName = CFLocaleGetIdentifier(formatter->_locale);
-       CFDictionaryRef components = CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault, localeName);
-       CFMutableDictionaryRef mcomponents = CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault, 0, components);
-       CFDictionarySetValue(mcomponents, kCFLocaleCalendarIdentifier, value);
-       localeName = CFLocaleCreateLocaleIdentifierFromComponents(kCFAllocatorSystemDefault, mcomponents);
-       CFRelease(mcomponents);
-       CFRelease(components);
-       CFLocaleRef newLocale = CFLocaleCreate(CFGetAllocator(formatter->_locale), localeName);
-       CFRelease(localeName);
-       CFRelease(formatter->_locale);
-       formatter->_locale = newLocale;
-       UCalendar *cal = __CFCalendarCreateUCalendar(NULL, CFLocaleGetIdentifier(formatter->_locale), formatter->_tz);
-       if (cal) udat_setCalendar(formatter->_df, cal);
-       if (cal) ucal_close(cal);
-    } else if (kCFDateFormatterTimeZone == key) {
-       __CFGenericValidateType(value, CFTimeZoneGetTypeID());
-       CFTimeZoneRef old = formatter->_tz;
-       formatter->_tz = value ? (CFTimeZoneRef)CFRetain(value) : CFTimeZoneCopyDefault();
-       if (old) CFRelease(old);
-       CFStringRef tznam = CFTimeZoneGetName(formatter->_tz);
-       UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
-       CFIndex ucnt = CFStringGetLength(tznam);
-       if (BUFFER_SIZE < ucnt) ucnt = BUFFER_SIZE;
-       CFStringGetCharacters(tznam, CFRangeMake(0, ucnt), (UniChar *)ubuffer);
-       ucal_setTimeZone(cal, ubuffer, ucnt, &status);
-    } else if (kCFDateFormatterDefaultFormat == key) {
-       // read-only attribute
-    } else if (kCFDateFormatterTwoDigitStartDate == key) {
+    if (kCFDateFormatterIsLenientKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _IsLenient;
+            formatter->_property. _IsLenient = NULL;
+       }
+        __CFGenericValidateType(value, CFBooleanGetTypeID());
+        udat_setLenient(formatter->_df, (kCFBooleanTrue == value));
+        UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
+        if (cal) ucal_setAttribute(cal, UCAL_LENIENT, (kCFBooleanTrue == value));
+       if (!directToICU) {
+            formatter->_property. _IsLenient = (CFBooleanRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterIsLenientKey);
+       }
+    } else if (kCFDateFormatterDoesRelativeDateFormattingKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _DoesRelativeDateFormatting;
+            formatter->_property. _DoesRelativeDateFormatting = NULL;
+       }
+        __CFGenericValidateType(value, CFBooleanGetTypeID());
+       if (!directToICU) {
+           if (kCFBooleanTrue != value) value = kCFBooleanFalse;
+            formatter->_property. _DoesRelativeDateFormatting = value ? (CFBooleanRef)CFRetain(value) : NULL;
+           __ResetUDateFormat(formatter, false);
+       }
+    } else if (kCFDateFormatterCalendarKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _Calendar;
+            formatter->_property. _Calendar = NULL;
+       }
+        __CFGenericValidateType(value, CFCalendarGetTypeID());
+        CFStringRef localeName = CFLocaleGetIdentifier(formatter->_locale);
+        CFDictionaryRef components = CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault, localeName);
+        CFMutableDictionaryRef mcomponents = CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault, 0, components);
+        CFDictionarySetValue(mcomponents, kCFLocaleCalendarIdentifierKey, CFCalendarGetIdentifier((CFCalendarRef)value));
+        localeName = CFLocaleCreateLocaleIdentifierFromComponents(kCFAllocatorSystemDefault, mcomponents);
+        CFRelease(mcomponents);
+        CFRelease(components);
+        CFLocaleRef newLocale = CFLocaleCreate(CFGetAllocator(formatter->_locale), localeName);
+        CFRelease(localeName);
+        CFRelease(formatter->_locale);
+        formatter->_locale = newLocale;
+        UCalendar *cal = __CFCalendarCreateUCalendar(NULL, CFLocaleGetIdentifier(formatter->_locale), formatter->_property._TimeZone);
+        if (cal) ucal_setAttribute(cal, UCAL_FIRST_DAY_OF_WEEK, CFCalendarGetFirstWeekday((CFCalendarRef)value));
+        if (cal) ucal_setAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK, CFCalendarGetMinimumDaysInFirstWeek((CFCalendarRef)value));
+        if (cal) udat_setCalendar(formatter->_df, cal);
+        if (cal) ucal_close(cal);
+       if (!directToICU) {
+            formatter->_property. _Calendar = (CFCalendarRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterCalendarKey);
+       }
+    } else if (kCFDateFormatterCalendarIdentifierKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _CalendarName;
+            formatter->_property. _CalendarName = NULL;
+       }
+        __CFGenericValidateType(value, CFStringGetTypeID());
+        CFStringRef localeName = CFLocaleGetIdentifier(formatter->_locale);
+        CFDictionaryRef components = CFLocaleCreateComponentsFromLocaleIdentifier(kCFAllocatorSystemDefault, localeName);
+        CFMutableDictionaryRef mcomponents = CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault, 0, components);
+        CFDictionarySetValue(mcomponents, kCFLocaleCalendarIdentifierKey, value);
+        localeName = CFLocaleCreateLocaleIdentifierFromComponents(kCFAllocatorSystemDefault, mcomponents);
+        CFRelease(mcomponents);
+        CFRelease(components);
+        CFLocaleRef newLocale = CFLocaleCreate(CFGetAllocator(formatter->_locale), localeName);
+        CFRelease(localeName);
+        CFRelease(formatter->_locale);
+        formatter->_locale = newLocale;
+        UCalendar *cal = __CFCalendarCreateUCalendar(NULL, CFLocaleGetIdentifier(formatter->_locale), formatter->_property._TimeZone);
+        if (cal) udat_setCalendar(formatter->_df, cal);
+        if (cal) ucal_close(cal);
+       if (!directToICU) {
+            formatter->_property. _CalendarName = (CFStringRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterCalendarIdentifierKey);
+       }
+    } else if (kCFDateFormatterTimeZoneKey == key) {
+       if (formatter->_property. _TimeZone != value) {
+           if (!directToICU) {
+               oldProperty = formatter->_property. _TimeZone;
+               formatter->_property. _TimeZone = NULL;
+           }
+           __CFGenericValidateType(value, CFTimeZoneGetTypeID());
+           CFTimeZoneRef old = formatter->_property._TimeZone;
+           formatter->_property._TimeZone = value ? (CFTimeZoneRef)CFRetain(value) : CFTimeZoneCopyDefault();
+           if (old) CFRelease(old);
+           CFStringRef tznam = CFTimeZoneGetName(formatter->_property._TimeZone);
+           UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
+           CFIndex ucnt = CFStringGetLength(tznam);
+           if (BUFFER_SIZE < ucnt) ucnt = BUFFER_SIZE;
+           CFStringGetCharacters(tznam, CFRangeMake(0, ucnt), (UniChar *)ubuffer);
+           ucal_setTimeZone(cal, ubuffer, ucnt, &status);
+           if (!directToICU) {
+               old = formatter->_property._TimeZone;
+               formatter->_property. _TimeZone = (CFTimeZoneRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterTimeZoneKey);
+               if (old) CFRelease(old);
+           }
+       }
+    } else if (kCFDateFormatterDefaultFormatKey == key) {
+        // read-only attribute
+    } else if (kCFDateFormatterTwoDigitStartDateKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _TwoDigitStartDate;
+            formatter->_property. _TwoDigitStartDate = NULL;
+       }
         __CFGenericValidateType(value, CFDateGetTypeID());
-       CFAbsoluteTime at = CFDateGetAbsoluteTime((CFDateRef)value);
-       UDate udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0;
-       udat_set2DigitYearStart(formatter->_df, udate, &status);
-    } else if (kCFDateFormatterDefaultDate == key) {
+        CFAbsoluteTime at = CFDateGetAbsoluteTime((CFDateRef)value);
+        UDate udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0;
+        udat_set2DigitYearStart(formatter->_df, udate, &status);
+       if (!directToICU) {
+            formatter->_property. _TwoDigitStartDate = (CFDateRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterTwoDigitStartDateKey);
+       }
+    } else if (kCFDateFormatterDefaultDateKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _DefaultDate;
+            formatter->_property. _DefaultDate = NULL;
+       }
         __CFGenericValidateType(value, CFDateGetTypeID());
-       CFDateRef old = formatter->_defaultDate;
-       formatter->_defaultDate = value ? (CFDateRef)CFRetain(value) : NULL;
-       if (old) CFRelease(old);
-    } else if (kCFDateFormatterEraSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_ERAS, 0)
-    } else if (kCFDateFormatterMonthSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_MONTHS, 0)
-    } else if (kCFDateFormatterShortMonthSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_SHORT_MONTHS, 0)
-    } else if (kCFDateFormatterWeekdaySymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_WEEKDAYS, 1)
-    } else if (kCFDateFormatterShortWeekdaySymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_SHORT_WEEKDAYS, 1)
-    } else if (kCFDateFormatterAMSymbol == key) {
+       if (!directToICU) {
+            formatter->_property._DefaultDate = value ? (CFDateRef)CFRetain(value) : NULL;
+       }
+    } else if (kCFDateFormatterGregorianStartDateKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _GregorianStartDate;
+            formatter->_property. _GregorianStartDate = NULL;
+       }
+        __CFGenericValidateType(value, CFDateGetTypeID());
+        CFAbsoluteTime at = CFDateGetAbsoluteTime((CFDateRef)value);
+        UDate udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0;
+        UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
+        ucal_setGregorianChange(cal, udate, &status);
+       if (!directToICU) {
+            formatter->_property. _GregorianStartDate = (CFDateRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterGregorianStartDateKey);
+       }
+    } else if (kCFDateFormatterEraSymbolsKey == key) {
+       SET_SYMBOLS_ARRAY(UDAT_ERAS, 0, _EraSymbols)
+    } else if (kCFDateFormatterLongEraSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_ERA_NAMES, 0, _LongEraSymbols)
+    } else if (kCFDateFormatterMonthSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_MONTHS, 0, _MonthSymbols)
+    } else if (kCFDateFormatterShortMonthSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_SHORT_MONTHS, 0, _ShortMonthSymbols)
+    } else if (kCFDateFormatterVeryShortMonthSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_NARROW_MONTHS, 0, _VeryShortMonthSymbols)
+    } else if (kCFDateFormatterStandaloneMonthSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_STANDALONE_MONTHS, 0, _StandaloneMonthSymbols)
+    } else if (kCFDateFormatterShortStandaloneMonthSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_MONTHS, 0, _ShortStandaloneMonthSymbols)
+    } else if (kCFDateFormatterVeryShortStandaloneMonthSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_MONTHS, 0, _VeryShortStandaloneMonthSymbols)
+    } else if (kCFDateFormatterWeekdaySymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_WEEKDAYS, 1, _WeekdaySymbols)
+    } else if (kCFDateFormatterShortWeekdaySymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_SHORT_WEEKDAYS, 1, _ShortWeekdaySymbols)
+    } else if (kCFDateFormatterVeryShortWeekdaySymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_NARROW_WEEKDAYS, 1, _VeryShortWeekdaySymbols)
+    } else if (kCFDateFormatterStandaloneWeekdaySymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_STANDALONE_WEEKDAYS, 1, _StandaloneWeekdaySymbols)
+    } else if (kCFDateFormatterShortStandaloneWeekdaySymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_WEEKDAYS, 1, _ShortStandaloneWeekdaySymbols)
+    } else if (kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_WEEKDAYS, 1, _VeryShortStandaloneWeekdaySymbols)
+    } else if (kCFDateFormatterQuarterSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_QUARTERS, 0, _QuarterSymbols)
+    } else if (kCFDateFormatterShortQuarterSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_SHORT_QUARTERS, 0, _ShortQuarterSymbols)
+    } else if (kCFDateFormatterStandaloneQuarterSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_STANDALONE_QUARTERS, 0, _StandaloneQuarterSymbols)
+    } else if (kCFDateFormatterShortStandaloneQuarterSymbolsKey == key) {
+        SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_QUARTERS, 0, _ShortStandaloneQuarterSymbols)
+    } else if (kCFDateFormatterAMSymbolKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _AMSymbol;
+            formatter->_property. _AMSymbol = NULL;
+       }
         __CFGenericValidateType(value, CFStringGetTypeID());
-       CFIndex item_cnt = CFStringGetLength((CFStringRef)value);
-       STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt));
-       UChar *item_ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)value);
-       if (NULL == item_ustr) {
-           item_cnt = __CFMin(BUFFER_SIZE, item_cnt);
-           CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, item_cnt), (UniChar *)item_buffer);
-           item_ustr = item_buffer;
+        CFIndex item_cnt = CFStringGetLength((CFStringRef)value);
+        STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt));
+        UChar *item_ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)value);
+        if (NULL == item_ustr) {
+            item_cnt = __CFMin(BUFFER_SIZE, item_cnt);
+            CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, item_cnt), (UniChar *)item_buffer);
+            item_ustr = item_buffer;
+        }
+        udat_setSymbols(formatter->_df, UDAT_AM_PMS, 0, item_ustr, item_cnt, &status);
+       if (!directToICU) {
+            formatter->_property. _AMSymbol = (CFStringRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterAMSymbolKey);
+       }
+    } else if (kCFDateFormatterPMSymbolKey == key) {
+       if (!directToICU) {
+           oldProperty = formatter->_property. _PMSymbol;
+            formatter->_property. _PMSymbol = NULL;
        }
-       udat_setSymbols(formatter->_df, UDAT_AM_PMS, 0, item_ustr, item_cnt, &status);
-    } else if (kCFDateFormatterPMSymbol == key) {
         __CFGenericValidateType(value, CFStringGetTypeID());
-       CFIndex item_cnt = CFStringGetLength((CFStringRef)value);
-       STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt));
-       UChar *item_ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)value);
-       if (NULL == item_ustr) {
-           item_cnt = __CFMin(BUFFER_SIZE, item_cnt);
-           CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, item_cnt), (UniChar *)item_buffer);
-           item_ustr = item_buffer;
+        CFIndex item_cnt = CFStringGetLength((CFStringRef)value);
+        STACK_BUFFER_DECL(UChar, item_buffer, __CFMin(BUFFER_SIZE, item_cnt));
+        UChar *item_ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)value);
+        if (NULL == item_ustr) {
+            item_cnt = __CFMin(BUFFER_SIZE, item_cnt);
+            CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, item_cnt), (UniChar *)item_buffer);
+            item_ustr = item_buffer;
+        }
+        udat_setSymbols(formatter->_df, UDAT_AM_PMS, 1, item_ustr, item_cnt, &status);
+       if (!directToICU) {
+            formatter->_property. _PMSymbol = (CFStringRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterPMSymbolKey);
        }
-       udat_setSymbols(formatter->_df, UDAT_AM_PMS, 1, item_ustr, item_cnt, &status);
-    } else if (kCFDateFormatterGregorianStartDate == key) {
-       __CFGenericValidateType(value, CFDateGetTypeID());
-       CFAbsoluteTime at = CFDateGetAbsoluteTime((CFDateRef)value);
-       UDate udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0;
-       UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
-       ucal_setGregorianChange(cal, udate, &status);
-    } else if (kCFDateFormatterLongEraSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_ERA_NAMES, 0)
-    } else if (kCFDateFormatterVeryShortMonthSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_NARROW_MONTHS, 0)
-    } else if (kCFDateFormatterStandaloneMonthSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_STANDALONE_MONTHS, 0)
-    } else if (kCFDateFormatterShortStandaloneMonthSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_MONTHS, 0)
-    } else if (kCFDateFormatterVeryShortStandaloneMonthSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_MONTHS, 0)
-    } else if (kCFDateFormatterVeryShortWeekdaySymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_NARROW_WEEKDAYS, 1)
-    } else if (kCFDateFormatterStandaloneWeekdaySymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_STANDALONE_WEEKDAYS, 1)
-    } else if (kCFDateFormatterShortStandaloneWeekdaySymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_WEEKDAYS, 1)
-    } else if (kCFDateFormatterVeryShortStandaloneWeekdaySymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_WEEKDAYS, 1)
-    } else if (kCFDateFormatterQuarterSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_QUARTERS, 1)
-    } else if (kCFDateFormatterShortQuarterSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_SHORT_QUARTERS, 1)
-    } else if (kCFDateFormatterStandaloneQuarterSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_STANDALONE_QUARTERS, 1)
-    } else if (kCFDateFormatterShortStandaloneQuarterSymbols == key) {
-       SET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_QUARTERS, 1)
     } else {
-       CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key);
+        CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key);
     }
+    if (oldProperty) CFRelease(oldProperty);
 }
 
-#define GET_SYMBOLS_ARRAY(ICU_CODE, INDEX_BASE) \
-       CFIndex idx, cnt = udat_countSymbols(formatter->_df, ICU_CODE) - INDEX_BASE; \
-       STACK_BUFFER_DECL(CFStringRef, strings, cnt); \
-       for (idx = 0; idx < cnt; idx++) { \
-           CFStringRef str = NULL; \
-           status = U_ZERO_ERROR; \
-           CFIndex ucnt = udat_getSymbols(formatter->_df, ICU_CODE, idx + INDEX_BASE, ubuffer, BUFFER_SIZE, &status); \
-           if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) { \
-               str = CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, ucnt); \
-           } \
-           strings[idx] = !str ? (CFStringRef)CFRetain(CFSTR("<error>")) : str; \
-       } \
-       CFArrayRef array = CFArrayCreate(CFGetAllocator(formatter), (const void **)strings, cnt, &kCFTypeArrayCallBacks); \
-       while (cnt--) { \
-           CFRelease(strings[cnt]); \
-       } \
-       return array;
+void CFDateFormatterSetProperty(CFDateFormatterRef formatter, CFStringRef key, CFTypeRef value) {
+    __CFDateFormatterSetProperty(formatter, key, value, false);
+}
 
 CFTypeRef CFDateFormatterCopyProperty(CFDateFormatterRef formatter, CFStringRef key) {
     __CFGenericValidateType(formatter, CFDateFormatterGetTypeID());
@@ -592,122 +1094,118 @@ CFTypeRef CFDateFormatterCopyProperty(CFDateFormatterRef formatter, CFStringRef
     UErrorCode status = U_ZERO_ERROR;
     UChar ubuffer[BUFFER_SIZE];
 
-    if (kCFDateFormatterIsLenient == key) {
-       return CFRetain(udat_isLenient(formatter->_df) ? kCFBooleanTrue : kCFBooleanFalse);
-    } else if (kCFDateFormatterCalendar == key) {
-       CFCalendarRef calendar = (CFCalendarRef)CFLocaleGetValue(formatter->_locale, kCFLocaleCalendar);
-       return calendar ? CFRetain(calendar) : NULL;
-    } else if (kCFDateFormatterCalendarIdentifier == key || kCFDateFormatterCalendarName == key) {
-       CFStringRef ident = (CFStringRef)CFLocaleGetValue(formatter->_locale, kCFLocaleCalendarIdentifier);
-       return ident ? CFRetain(ident) : NULL;
-    } else if (kCFDateFormatterTimeZone == key) {
-       return CFRetain(formatter->_tz);
-    } else if (kCFDateFormatterDefaultFormat == key) {
-       return formatter->_defformat ? CFRetain(formatter->_defformat) : NULL;
-    } else if (kCFDateFormatterTwoDigitStartDate == key) {
-       UDate udate = udat_get2DigitYearStart(formatter->_df, &status);
+    if (kCFDateFormatterIsLenientKey == key) {
+       if (formatter->_property._IsLenient) return CFRetain(formatter->_property._IsLenient);
+        return CFRetain(udat_isLenient(formatter->_df) ? kCFBooleanTrue : kCFBooleanFalse);
+    } else if (kCFDateFormatterDoesRelativeDateFormattingKey == key) {
+       if (formatter->_property._DoesRelativeDateFormatting) return CFRetain(formatter->_property._DoesRelativeDateFormatting);
+        return CFRetain(kCFBooleanFalse);
+    } else if (kCFDateFormatterCalendarKey == key) {
+       if (formatter->_property._Calendar) return CFRetain(formatter->_property._Calendar);
+        CFCalendarRef calendar = (CFCalendarRef)CFLocaleGetValue(formatter->_locale, kCFLocaleCalendarKey);
+        return calendar ? CFRetain(calendar) : NULL;
+    } else if (kCFDateFormatterCalendarIdentifierKey == key) {
+       if (formatter->_property._CalendarName) return CFRetain(formatter->_property._CalendarName);
+        CFStringRef ident = (CFStringRef)CFLocaleGetValue(formatter->_locale, kCFLocaleCalendarIdentifierKey);
+        return ident ? CFRetain(ident) : NULL;
+    } else if (kCFDateFormatterTimeZoneKey == key) {
+       if (formatter->_property._TwoDigitStartDate) return CFRetain(formatter->_property._TwoDigitStartDate);
+        return CFRetain(formatter->_property._TimeZone);
+    } else if (kCFDateFormatterDefaultFormatKey == key) {
+        return formatter->_defformat ? CFRetain(formatter->_defformat) : NULL;
+    } else if (kCFDateFormatterTwoDigitStartDateKey == key) {
+       if (formatter->_property._TwoDigitStartDate) return CFRetain(formatter->_property._TwoDigitStartDate);
+        UDate udate = udat_get2DigitYearStart(formatter->_df, &status);
         if (U_SUCCESS(status)) {
-           CFAbsoluteTime at = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
+            CFAbsoluteTime at = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
             return CFDateCreate(CFGetAllocator(formatter), at);
         }
-    } else if (kCFDateFormatterDefaultDate == key) {
-       return formatter->_defaultDate ? CFRetain(formatter->_defaultDate) : NULL;
-    } else if (kCFDateFormatterEraSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_ERAS, 0)
-    } else if (kCFDateFormatterMonthSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_MONTHS, 0)
-    } else if (kCFDateFormatterShortMonthSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_SHORT_MONTHS, 0)
-    } else if (kCFDateFormatterWeekdaySymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_WEEKDAYS, 1)
-    } else if (kCFDateFormatterShortWeekdaySymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_SHORT_WEEKDAYS, 1)
-    } else if (kCFDateFormatterAMSymbol == key) {
-       CFIndex cnt = udat_countSymbols(formatter->_df, UDAT_AM_PMS);
-       if (2 <= cnt) {
-           CFIndex ucnt = udat_getSymbols(formatter->_df, UDAT_AM_PMS, 0, ubuffer, BUFFER_SIZE, &status);
-           if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
-               return CFStringCreateWithCharacters(CFGetAllocator(formatter), (UniChar *)ubuffer, ucnt);
-           }
-       }       
-    } else if (kCFDateFormatterPMSymbol == key) {
-       CFIndex cnt = udat_countSymbols(formatter->_df, UDAT_AM_PMS);
-       if (2 <= cnt) {
-           CFIndex ucnt = udat_getSymbols(formatter->_df, UDAT_AM_PMS, 1, ubuffer, BUFFER_SIZE, &status);
-           if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
-               return CFStringCreateWithCharacters(CFGetAllocator(formatter), (UniChar *)ubuffer, ucnt);
-           }
-       }       
-    } else if (kCFDateFormatterGregorianStartDate == key) {
-       UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
-       UDate udate = ucal_getGregorianChange(cal, &status);
+    } else if (kCFDateFormatterDefaultDateKey == key) {
+        return formatter->_property._DefaultDate ? CFRetain(formatter->_property._DefaultDate) : NULL;
+    } else if (kCFDateFormatterGregorianStartDateKey == key) {
+       if (formatter->_property._GregorianStartDate) return CFRetain(formatter->_property._GregorianStartDate);
+        UCalendar *cal = (UCalendar *)udat_getCalendar(formatter->_df);
+        UDate udate = ucal_getGregorianChange(cal, &status);
         if (U_SUCCESS(status)) {
-           CFAbsoluteTime at = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
+            CFAbsoluteTime at = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
             return CFDateCreate(CFGetAllocator(formatter), at);
         }
-    } else if (kCFDateFormatterLongEraSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_ERA_NAMES, 0)
-    } else if (kCFDateFormatterVeryShortMonthSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_NARROW_MONTHS, 0)
-    } else if (kCFDateFormatterStandaloneMonthSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_STANDALONE_MONTHS, 0)
-    } else if (kCFDateFormatterShortStandaloneMonthSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_MONTHS, 0)
-    } else if (kCFDateFormatterVeryShortStandaloneMonthSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_MONTHS, 0)
-    } else if (kCFDateFormatterVeryShortWeekdaySymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_NARROW_WEEKDAYS, 1)
-    } else if (kCFDateFormatterStandaloneWeekdaySymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_STANDALONE_WEEKDAYS, 1)
-    } else if (kCFDateFormatterShortStandaloneWeekdaySymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_WEEKDAYS, 1)
-    } else if (kCFDateFormatterVeryShortStandaloneWeekdaySymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_STANDALONE_NARROW_WEEKDAYS, 1)
-    } else if (kCFDateFormatterQuarterSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_QUARTERS, 1)
-    } else if (kCFDateFormatterShortQuarterSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_SHORT_QUARTERS, 1)
-    } else if (kCFDateFormatterStandaloneQuarterSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_STANDALONE_QUARTERS, 1)
-    } else if (kCFDateFormatterShortStandaloneQuarterSymbols == key) {
-       GET_SYMBOLS_ARRAY(UDAT_STANDALONE_SHORT_QUARTERS, 1)
+    } else if (kCFDateFormatterEraSymbolsKey == key) {
+       if (formatter->_property._EraSymbols) return CFRetain(formatter->_property._EraSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_ERAS, 0);
+    } else if (kCFDateFormatterLongEraSymbolsKey == key) {
+       if (formatter->_property._LongEraSymbols) return CFRetain(formatter->_property._LongEraSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_ERA_NAMES, 0);
+    } else if (kCFDateFormatterMonthSymbolsKey == key) {
+       if (formatter->_property._MonthSymbols) return CFRetain(formatter->_property._MonthSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_MONTHS, 0);
+    } else if (kCFDateFormatterShortMonthSymbolsKey == key) {
+       if (formatter->_property._ShortMonthSymbols) return CFRetain(formatter->_property._ShortMonthSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_SHORT_MONTHS, 0);
+    } else if (kCFDateFormatterVeryShortMonthSymbolsKey == key) {
+       if (formatter->_property._VeryShortMonthSymbols) return CFRetain(formatter->_property._VeryShortMonthSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_NARROW_MONTHS, 0);
+    } else if (kCFDateFormatterStandaloneMonthSymbolsKey == key) {
+       if (formatter->_property._StandaloneMonthSymbols) return CFRetain(formatter->_property._StandaloneMonthSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_MONTHS, 0);
+    } else if (kCFDateFormatterShortStandaloneMonthSymbolsKey == key) {
+       if (formatter->_property._ShortStandaloneMonthSymbols) return CFRetain(formatter->_property._ShortStandaloneMonthSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_SHORT_MONTHS, 0);
+    } else if (kCFDateFormatterVeryShortStandaloneMonthSymbolsKey == key) {
+       if (formatter->_property._VeryShortStandaloneMonthSymbols) return CFRetain(formatter->_property._VeryShortStandaloneMonthSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_NARROW_MONTHS, 0);
+    } else if (kCFDateFormatterWeekdaySymbolsKey == key) {
+       if (formatter->_property._WeekdaySymbols) return CFRetain(formatter->_property._WeekdaySymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_WEEKDAYS, 1);
+    } else if (kCFDateFormatterShortWeekdaySymbolsKey == key) {
+       if (formatter->_property._ShortWeekdaySymbols) return CFRetain(formatter->_property._ShortWeekdaySymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_SHORT_WEEKDAYS, 1);
+    } else if (kCFDateFormatterVeryShortWeekdaySymbolsKey == key) {
+       if (formatter->_property._VeryShortWeekdaySymbols) return CFRetain(formatter->_property._VeryShortWeekdaySymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_NARROW_WEEKDAYS, 1);
+    } else if (kCFDateFormatterStandaloneWeekdaySymbolsKey == key) {
+       if (formatter->_property._StandaloneWeekdaySymbols) return CFRetain(formatter->_property._StandaloneWeekdaySymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_WEEKDAYS, 1);
+    } else if (kCFDateFormatterShortStandaloneWeekdaySymbolsKey == key) {
+       if (formatter->_property._ShortStandaloneWeekdaySymbols) return CFRetain(formatter->_property._ShortStandaloneWeekdaySymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_SHORT_WEEKDAYS, 1);
+    } else if (kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey == key) {
+       if (formatter->_property._VeryShortStandaloneWeekdaySymbols) return CFRetain(formatter->_property._VeryShortStandaloneWeekdaySymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_NARROW_WEEKDAYS, 1);
+    } else if (kCFDateFormatterQuarterSymbolsKey == key) {
+       if (formatter->_property._QuarterSymbols) return CFRetain(formatter->_property._QuarterSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_QUARTERS, 0);
+    } else if (kCFDateFormatterShortQuarterSymbolsKey == key) {
+       if (formatter->_property._ShortQuarterSymbols) return CFRetain(formatter->_property._ShortQuarterSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_SHORT_QUARTERS, 0);
+    } else if (kCFDateFormatterStandaloneQuarterSymbolsKey == key) {
+       if (formatter->_property._StandaloneQuarterSymbols) return CFRetain(formatter->_property._StandaloneQuarterSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_QUARTERS, 0);
+    } else if (kCFDateFormatterShortStandaloneQuarterSymbolsKey == key) {
+       if (formatter->_property._ShortStandaloneQuarterSymbols) return CFRetain(formatter->_property._ShortStandaloneQuarterSymbols);
+        return __CFDateFormatterGetSymbolsArray(formatter->_df, UDAT_STANDALONE_SHORT_QUARTERS, 0);
+    } else if (kCFDateFormatterAMSymbolKey == key) {
+       if (formatter->_property._AMSymbol) return CFRetain(formatter->_property._AMSymbol);
+        CFIndex cnt = udat_countSymbols(formatter->_df, UDAT_AM_PMS);
+        if (2 <= cnt) {
+            CFIndex ucnt = udat_getSymbols(formatter->_df, UDAT_AM_PMS, 0, ubuffer, BUFFER_SIZE, &status);
+            if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
+                return CFStringCreateWithCharacters(CFGetAllocator(formatter), (UniChar *)ubuffer, ucnt);
+            }
+        }        
+    } else if (kCFDateFormatterPMSymbolKey == key) {
+       if (formatter->_property._PMSymbol) return CFRetain(formatter->_property._PMSymbol);
+        CFIndex cnt = udat_countSymbols(formatter->_df, UDAT_AM_PMS);
+        if (2 <= cnt) {
+            CFIndex ucnt = udat_getSymbols(formatter->_df, UDAT_AM_PMS, 1, ubuffer, BUFFER_SIZE, &status);
+            if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
+                return CFStringCreateWithCharacters(CFGetAllocator(formatter), (UniChar *)ubuffer, ucnt);
+            }
+        }        
     } else {
-       CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key);
+        CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key);
     }
     return NULL;
 }
 
-CONST_STRING_DECL(kCFDateFormatterIsLenient, "kCFDateFormatterIsLenient")
-CONST_STRING_DECL(kCFDateFormatterTimeZone, "kCFDateFormatterTimeZone")
-CONST_STRING_DECL(kCFDateFormatterCalendarName, "kCFDateFormatterCalendarName")
-CONST_STRING_DECL(kCFDateFormatterCalendarIdentifier, "kCFDateFormatterCalendarIdentifier")
-CONST_STRING_DECL(kCFDateFormatterCalendar, "kCFDateFormatterCalendar")
-CONST_STRING_DECL(kCFDateFormatterDefaultFormat, "kCFDateFormatterDefaultFormat")
-
-CONST_STRING_DECL(kCFDateFormatterTwoDigitStartDate, "kCFDateFormatterTwoDigitStartDate")
-CONST_STRING_DECL(kCFDateFormatterDefaultDate, "kCFDateFormatterDefaultDate")
-CONST_STRING_DECL(kCFDateFormatterEraSymbols, "kCFDateFormatterEraSymbols")
-CONST_STRING_DECL(kCFDateFormatterMonthSymbols, "kCFDateFormatterMonthSymbols")
-CONST_STRING_DECL(kCFDateFormatterShortMonthSymbols, "kCFDateFormatterShortMonthSymbols")
-CONST_STRING_DECL(kCFDateFormatterWeekdaySymbols, "kCFDateFormatterWeekdaySymbols")
-CONST_STRING_DECL(kCFDateFormatterShortWeekdaySymbols, "kCFDateFormatterShortWeekdaySymbols")
-CONST_STRING_DECL(kCFDateFormatterAMSymbol, "kCFDateFormatterAMSymbol")
-CONST_STRING_DECL(kCFDateFormatterPMSymbol, "kCFDateFormatterPMSymbol")
-
-CONST_STRING_DECL(kCFDateFormatterLongEraSymbols, "kCFDateFormatterLongEraSymbols")
-CONST_STRING_DECL(kCFDateFormatterVeryShortMonthSymbols, "kCFDateFormatterVeryShortMonthSymbols")
-CONST_STRING_DECL(kCFDateFormatterStandaloneMonthSymbols, "kCFDateFormatterStandaloneMonthSymbols")
-CONST_STRING_DECL(kCFDateFormatterShortStandaloneMonthSymbols, "kCFDateFormatterShortStandaloneMonthSymbols")
-CONST_STRING_DECL(kCFDateFormatterVeryShortStandaloneMonthSymbols, "kCFDateFormatterVeryShortStandaloneMonthSymbols")
-CONST_STRING_DECL(kCFDateFormatterVeryShortWeekdaySymbols, "kCFDateFormatterVeryShortWeekdaySymbols")
-CONST_STRING_DECL(kCFDateFormatterStandaloneWeekdaySymbols, "kCFDateFormatterStandaloneWeekdaySymbols")
-CONST_STRING_DECL(kCFDateFormatterShortStandaloneWeekdaySymbols, "kCFDateFormatterShortStandaloneWeekdaySymbols")
-CONST_STRING_DECL(kCFDateFormatterVeryShortStandaloneWeekdaySymbols, "kCFDateFormatterVeryShortStandaloneWeekdaySymbols")
-CONST_STRING_DECL(kCFDateFormatterQuarterSymbols, "kCFDateFormatterQuarterSymbols")
-CONST_STRING_DECL(kCFDateFormatterShortQuarterSymbols, "kCFDateFormatterShortQuarterSymbols")
-CONST_STRING_DECL(kCFDateFormatterStandaloneQuarterSymbols, "kCFDateFormatterStandaloneQuarterSymbols")
-CONST_STRING_DECL(kCFDateFormatterShortStandaloneQuarterSymbols, "kCFDateFormatterShortStandaloneQuarterSymbols")
-CONST_STRING_DECL(kCFDateFormatterGregorianStartDate, "kCFDateFormatterGregorianStartDate")
-
-#undef BUFFER_SIZE
 
index 16a007e1664e036f1a892a93bc345cc6d88b2e48..4c9d1f7059f0548b3b4acac5f580de5233c48c33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFDateFormatter.h
-       Copyright (c) 2003-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2003-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFDATEFORMATTER__)
@@ -39,6 +39,10 @@ typedef struct __CFDateFormatter *CFDateFormatterRef;
 
 // CFDateFormatters are not thread-safe.  Do not use one from multiple threads!
 
+CF_EXPORT
+CFStringRef CFDateFormatterCreateDateFormatFromTemplate(CFAllocatorRef allocator, CFStringRef tmplate, CFOptionFlags options, CFLocaleRef locale) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+       // no options defined, pass 0 for now
+
 CF_EXPORT
 CFTypeID CFDateFormatterGetTypeID(void) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
 
@@ -149,6 +153,7 @@ CF_EXPORT const CFStringRef kCFDateFormatterShortQuarterSymbols AVAILABLE_MAC_OS
 CF_EXPORT const CFStringRef kCFDateFormatterStandaloneQuarterSymbols AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; // CFArray of CFString
 CF_EXPORT const CFStringRef kCFDateFormatterShortStandaloneQuarterSymbols AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; // CFArray of CFString
 CF_EXPORT const CFStringRef kCFDateFormatterGregorianStartDate AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER; // CFDate
+CF_EXPORT const CFStringRef kCFDateFormatterDoesRelativeDateFormattingKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER; // CFBoolean
 
 // See CFLocale.h for these calendar constants:
 //     const CFStringRef kCFGregorianCalendar;
@@ -158,6 +163,10 @@ CF_EXPORT const CFStringRef kCFDateFormatterGregorianStartDate AVAILABLE_MAC_OS_
 //     const CFStringRef kCFIslamicCivilCalendar;
 //     const CFStringRef kCFHebrewCalendar;
 //     const CFStringRef kCFChineseCalendar;
+//     const CFStringRef kCFRepublicOfChinaCalendar;
+//     const CFStringRef kCFPersianCalendar;
+//     const CFStringRef kCFIndianCalendar;
+//     const CFStringRef kCFISO8601Calendar;   not yet implemented
 
 CF_EXTERN_C_END
 
index 716dc77820d659990c10c26b8084669398ec54c0..f86b4917d1dc97a1b80eaf58fbf0bb710dc76386 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFDictionary.c
-       Copyright 1998-2006, Apple, Inc. All rights reserved.
+       Copyright 1998-2008, Apple, Inc. All rights reserved.
        Responsibility: Christopher Kane
-        Machine generated from Notes/HashingCode.template
+       Machine generated from Notes/HashingCode.template
 */
 
 
 
 
+
 #include <CoreFoundation/CFDictionary.h>
 #include "CFInternal.h"
-#include <mach-o/dyld.h>
+#include "CFBasicHash.h"
+#include <CoreFoundation/CFString.h>
 
 #define CFDictionary 0
 #define CFSet 0
@@ -48,7 +50,8 @@ static const CFDictionaryValueCallBacks __kCFNullDictionaryValueCallBacks = {0,
 
 #define CFHashRef CFDictionaryRef
 #define CFMutableHashRef CFMutableDictionaryRef
-#define __kCFHashTypeID __kCFDictionaryTypeID
+#define CFHashKeyCallBacks CFDictionaryKeyCallBacks
+#define CFHashValueCallBacks CFDictionaryValueCallBacks
 #endif
 
 #if CFSet
@@ -65,7 +68,8 @@ static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL
 
 #define CFHashRef CFSetRef
 #define CFMutableHashRef CFMutableSetRef
-#define __kCFHashTypeID __kCFSetTypeID
+#define CFHashKeyCallBacks CFDictionaryCallBacks
+#define CFHashValueCallBacks CFDictionaryCallBacks
 #endif
 
 #if CFBag
@@ -82,566 +86,29 @@ static const CFDictionaryCallBacks __kCFNullDictionaryCallBacks = {0, NULL, NULL
 
 #define CFHashRef CFBagRef
 #define CFMutableHashRef CFMutableBagRef
-#define __kCFHashTypeID __kCFBagTypeID
-#endif
-
-#define GETNEWKEY(newKey, oldKey) \
-        any_t (*kretain)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))__CFDictionaryGetKeyCallBacks(hc)->retain \
-            : (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        any_t newKey = kretain ? (any_t)INVOKE_CALLBACK3(kretain, allocator, (any_t)key, hc->_context) : (any_t)oldKey
-
-#define RELEASEKEY(oldKey) \
-        void (*krelease)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (void (*)(CFAllocatorRef,any_t,any_pointer_t))__CFDictionaryGetKeyCallBacks(hc)->release \
-            : (void (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        if (krelease) INVOKE_CALLBACK3(krelease, allocator, oldKey, hc->_context)
-        
-#if CFDictionary
-#define GETNEWVALUE(newValue) \
-        any_t (*vretain)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))__CFDictionaryGetValueCallBacks(hc)->retain \
-            : (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        any_t newValue = vretain ? (any_t)INVOKE_CALLBACK3(vretain, allocator, (any_t)value, hc->_context) : (any_t)value
-
-#define RELEASEVALUE(oldValue) \
-    void (*vrelease)(CFAllocatorRef, any_t, any_pointer_t) = \
-      !hasBeenFinalized(hc) \
-        ? (void (*)(CFAllocatorRef,any_t,any_pointer_t))__CFDictionaryGetValueCallBacks(hc)->release \
-        : (void (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-    if (vrelease) INVOKE_CALLBACK3(vrelease, allocator, oldValue, hc->_context)
-
+#define CFHashKeyCallBacks CFDictionaryCallBacks
+#define CFHashValueCallBacks CFDictionaryCallBacks
 #endif
 
-static void __CFDictionaryHandleOutOfMemory(CFTypeRef obj, CFIndex numBytes) {
-    CFStringRef msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFDictionary failed"), numBytes);
-    CFBadErrorCallBack cb = _CFGetOutOfMemoryErrorCallBack();
-    if (NULL == cb || !cb(obj, CFSTR("NS/CFDictionary"), msg)) {
-        CFLog(kCFLogLevelCritical, CFSTR("%@"), msg);
-       HALT;
-    }
-    CFRelease(msg);
-}
-
-
-// Max load is 3/4 number of buckets
-CF_INLINE CFIndex __CFHashRoundUpCapacity(CFIndex capacity) {
-    return 3 * ((CFIndex)1 << (flsl((capacity - 1) / 3)));
-}
-
-// Returns next power of two higher than the capacity
-// threshold for the given input capacity.
-CF_INLINE CFIndex __CFHashNumBucketsForCapacity(CFIndex capacity) {
-    return 4 * ((CFIndex)1 << (flsl((capacity - 1) / 3)));
-}
-
-enum {                /* Bits 1-0 */
-    __kCFHashImmutable = 0,        /* unchangable and fixed capacity */
-    __kCFHashMutable = 1,                /* changeable and variable capacity */
-};
-
-enum {                /* Bits 5-4 (value), 3-2 (key) */
-    __kCFHashHasNullCallBacks = 0,
-    __kCFHashHasCFTypeCallBacks = 1,
-    __kCFHashHasCustomCallBacks = 3        /* callbacks are at end of header */
-};
-
-// Under GC, we fudge the key/value memory in two ways
-// First, if we had null callbacks or null for both retain/release, we use unscanned memory and get
-// standard 'dangling' references.
-// This means that if people were doing addValue:[xxx new] and never removing, well, that doesn't work
-//
-// Second, if we notice standard retain/release implementations we use scanned memory, and fudge the
-// standard callbacks to generally do nothing if the collection was allocated in GC memory. On special
-// CF objects, however, like those used for precious resources like video-card buffers, we do indeed
-// do CFRetain on input and CFRelease on output.  The tricky case is GC finalization; we need to remember
-// that we did the CFReleases so that subsequent collection operations, like removal, don't double CFRelease.
-// (In fact we don't really use CFRetain/CFRelease but go directly to the collector)
-//
-
-enum {
-    __kCFHashFinalized =         (1 << 7),
-    __kCFHashWeakKeys =          (1 << 8),
-    __kCFHashWeakValues =        (1 << 9)
-};
 
 typedef uintptr_t any_t;
 typedef const void * const_any_pointer_t;
 typedef void * any_pointer_t;
 
-struct __CFDictionary {
-    CFRuntimeBase _base;
-    CFIndex _count;             /* number of values */
-    CFIndex _bucketsNum;        /* number of buckets */
-    CFIndex _bucketsUsed;       /* number of used buckets */
-    CFIndex _bucketsCap;        /* maximum number of used buckets */
-    CFIndex _mutations;
-    CFIndex _deletes;
-    any_pointer_t _context;     /* private */
-    CFOptionFlags _xflags;
-    any_t _marker;
-    any_t *_keys;     /* can be NULL if not allocated yet */
-    any_t *_values;   /* can be NULL if not allocated yet */
-};
-
-/* Bits 1-0 of the _xflags are used for mutability variety */
-/* Bits 3-2 of the _xflags are used for key callback indicator bits */
-/* Bits 5-4 of the _xflags are used for value callback indicator bits */
-/* Bit 6 of the _xflags is special KVO actions bit */
-/* Bits 7,8,9 are GC use */
-
-CF_INLINE bool hasBeenFinalized(CFTypeRef collection) {
-    return __CFBitfieldGetValue(((const struct __CFDictionary *)collection)->_xflags, 7, 7) != 0;
-}
-
-CF_INLINE void markFinalized(CFTypeRef collection) {
-    __CFBitfieldSetValue(((struct __CFDictionary *)collection)->_xflags, 7, 7, 1);
-}
-
-
-CF_INLINE CFIndex __CFHashGetType(CFHashRef hc) {
-    return __CFBitfieldGetValue(hc->_xflags, 1, 0);
-}
-
-CF_INLINE CFIndex __CFDictionaryGetSizeOfType(CFIndex t) {
-    CFIndex size = sizeof(struct __CFDictionary);
-    if (__CFBitfieldGetValue(t, 3, 2) == __kCFHashHasCustomCallBacks) {
-        size += sizeof(CFDictionaryKeyCallBacks);
-    }
-    if (__CFBitfieldGetValue(t, 5, 4) == __kCFHashHasCustomCallBacks) {
-        size += sizeof(CFDictionaryValueCallBacks);
-    }
-    return size;
-}
-
-CF_INLINE const CFDictionaryKeyCallBacks *__CFDictionaryGetKeyCallBacks(CFHashRef hc) {
-    CFDictionaryKeyCallBacks *result = NULL;
-    switch (__CFBitfieldGetValue(hc->_xflags, 3, 2)) {
-    case __kCFHashHasNullCallBacks:
-        return &__kCFNullDictionaryKeyCallBacks;
-    case __kCFHashHasCFTypeCallBacks:
-        return &kCFTypeDictionaryKeyCallBacks;
-    case __kCFHashHasCustomCallBacks:
-        break;
-    }
-    result = (CFDictionaryKeyCallBacks *)((uint8_t *)hc + sizeof(struct __CFDictionary));
-    return result;
-}
-
-CF_INLINE Boolean __CFDictionaryKeyCallBacksMatchNull(const CFDictionaryKeyCallBacks *c) {
-    return (NULL == c ||
-        (c->retain == __kCFNullDictionaryKeyCallBacks.retain &&
-         c->release == __kCFNullDictionaryKeyCallBacks.release &&
-         c->copyDescription == __kCFNullDictionaryKeyCallBacks.copyDescription &&
-         c->equal == __kCFNullDictionaryKeyCallBacks.equal &&
-         c->hash == __kCFNullDictionaryKeyCallBacks.hash));
-}
-
-CF_INLINE Boolean __CFDictionaryKeyCallBacksMatchCFType(const CFDictionaryKeyCallBacks *c) {
-    return (&kCFTypeDictionaryKeyCallBacks == c ||
-        (c->retain == kCFTypeDictionaryKeyCallBacks.retain &&
-         c->release == kCFTypeDictionaryKeyCallBacks.release &&
-         c->copyDescription == kCFTypeDictionaryKeyCallBacks.copyDescription &&
-         c->equal == kCFTypeDictionaryKeyCallBacks.equal &&
-         c->hash == kCFTypeDictionaryKeyCallBacks.hash));
-}
-
-CF_INLINE const CFDictionaryValueCallBacks *__CFDictionaryGetValueCallBacks(CFHashRef hc) {
-    CFDictionaryValueCallBacks *result = NULL;
-    switch (__CFBitfieldGetValue(hc->_xflags, 5, 4)) {
-    case __kCFHashHasNullCallBacks:
-        return &__kCFNullDictionaryValueCallBacks;
-    case __kCFHashHasCFTypeCallBacks:
-        return &kCFTypeDictionaryValueCallBacks;
-    case __kCFHashHasCustomCallBacks:
-        break;
-    }
-    if (__CFBitfieldGetValue(hc->_xflags, 3, 2) == __kCFHashHasCustomCallBacks) {
-        result = (CFDictionaryValueCallBacks *)((uint8_t *)hc + sizeof(struct __CFDictionary) + sizeof(CFDictionaryKeyCallBacks));
-    } else {
-        result = (CFDictionaryValueCallBacks *)((uint8_t *)hc + sizeof(struct __CFDictionary));
-    }
-    return result;
-}
-
-CF_INLINE Boolean __CFDictionaryValueCallBacksMatchNull(const CFDictionaryValueCallBacks *c) {
-    return (NULL == c ||
-        (c->retain == __kCFNullDictionaryValueCallBacks.retain &&
-         c->release == __kCFNullDictionaryValueCallBacks.release &&
-         c->copyDescription == __kCFNullDictionaryValueCallBacks.copyDescription &&
-         c->equal == __kCFNullDictionaryValueCallBacks.equal));
-}
-
-CF_INLINE Boolean __CFDictionaryValueCallBacksMatchCFType(const CFDictionaryValueCallBacks *c) {
-    return (&kCFTypeDictionaryValueCallBacks == c ||
-        (c->retain == kCFTypeDictionaryValueCallBacks.retain &&
-         c->release == kCFTypeDictionaryValueCallBacks.release &&
-         c->copyDescription == kCFTypeDictionaryValueCallBacks.copyDescription &&
-         c->equal == kCFTypeDictionaryValueCallBacks.equal));
-}
-
-CFIndex _CFDictionaryGetKVOBit(CFHashRef hc) {
-    return __CFBitfieldGetValue(hc->_xflags, 6, 6);
-}
-
-void _CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
-    __CFBitfieldSetValue(((CFMutableHashRef)hc)->_xflags, 6, 6, ((uintptr_t)bit & 0x1));
-}
-
-CF_INLINE Boolean __CFDictionaryShouldShrink(CFHashRef hc) {
-    return (__kCFHashMutable == __CFHashGetType(hc)) &&
-                !(CF_USING_COLLECTABLE_MEMORY && auto_zone_is_finalized(__CFCollectableZone, hc)) && /* GC:  don't shrink finalizing hcs! */
-                (hc->_bucketsNum < 4 * hc->_deletes || (256 <= hc->_bucketsCap && hc-> _bucketsUsed < 3 * hc->_bucketsCap / 16));
-}
-
-CF_INLINE CFIndex __CFHashGetOccurrenceCount(CFHashRef hc, CFIndex idx) {
-#if CFBag
-    return hc->_values[idx];
-#endif
-    return 1;
-}
-
-CF_INLINE Boolean __CFHashKeyIsValue(CFHashRef hc, any_t key) {
-    return (hc->_marker != key && ~hc->_marker != key) ? true : false;
-}
-
-CF_INLINE Boolean __CFHashKeyIsMagic(CFHashRef hc, any_t key) {
-    return (hc->_marker == key || ~hc->_marker == key) ? true : false;
-}
-
-
-#if !defined(CF_OBJC_KVO_WILLCHANGE)
-#define CF_OBJC_KVO_WILLCHANGE(obj, key)
-#define CF_OBJC_KVO_DIDCHANGE(obj, key)
-#endif
-
-CF_INLINE uintptr_t __CFDictionaryScrambleHash(uintptr_t k) {
-#if 0
-    return k;
-#else
-#if __LP64__
-    uintptr_t a = 0x4368726973746F70ULL;
-    uintptr_t b = 0x686572204B616E65ULL;
-#else
-    uintptr_t a = 0x4B616E65UL;
-    uintptr_t b = 0x4B616E65UL;
-#endif
-    uintptr_t c = 1;
-    a += k;
-#if __LP64__
-    a -= b; a -= c; a ^= (c >> 43);
-    b -= c; b -= a; b ^= (a << 9);
-    c -= a; c -= b; c ^= (b >> 8);
-    a -= b; a -= c; a ^= (c >> 38);
-    b -= c; b -= a; b ^= (a << 23);
-    c -= a; c -= b; c ^= (b >> 5);
-    a -= b; a -= c; a ^= (c >> 35);
-    b -= c; b -= a; b ^= (a << 49);
-    c -= a; c -= b; c ^= (b >> 11);
-    a -= b; a -= c; a ^= (c >> 12);
-    b -= c; b -= a; b ^= (a << 18);
-    c -= a; c -= b; c ^= (b >> 22);
-#else
-    a -= b; a -= c; a ^= (c >> 13);
-    b -= c; b -= a; b ^= (a << 8);
-    c -= a; c -= b; c ^= (b >> 13);
-    a -= b; a -= c; a ^= (c >> 12);
-    b -= c; b -= a; b ^= (a << 16);
-    c -= a; c -= b; c ^= (b >> 5);
-    a -= b; a -= c; a ^= (c >> 3);
-    b -= c; b -= a; b ^= (a << 10);
-    c -= a; c -= b; c ^= (b >> 15);
-#endif
-    return c;
-#endif
-}
-
-static CFIndex __CFDictionaryFindBuckets1a(CFHashRef hc, any_t key) {
-    CFHashCode keyHash = (CFHashCode)key;
-    keyHash = __CFDictionaryScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            return kCFNotFound;
-        } else if (~marker == currKey) {        /* deleted */
-            /* do nothing */
-        } else if (currKey == key) {
-            return probe;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return kCFNotFound;
-        }
-    }
-}
-
-static CFIndex __CFDictionaryFindBuckets1b(CFHashRef hc, any_t key) {
-    const CFDictionaryKeyCallBacks *cb = __CFDictionaryGetKeyCallBacks(hc);
-    CFHashCode keyHash = cb->hash ? (CFHashCode)INVOKE_CALLBACK2(((CFHashCode (*)(any_t, any_pointer_t))cb->hash), key, hc->_context) : (CFHashCode)key;
-    keyHash = __CFDictionaryScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            return kCFNotFound;
-        } else if (~marker == currKey) {        /* deleted */
-            /* do nothing */
-        } else if (currKey == key || (cb->equal && INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))cb->equal, currKey, key, hc->_context))) {
-            return probe;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return kCFNotFound;
-        }
-    }
-}
-
-CF_INLINE CFIndex __CFDictionaryFindBuckets1(CFHashRef hc, any_t key) {
-    if (__kCFHashHasNullCallBacks == __CFBitfieldGetValue(hc->_xflags, 3, 2)) {
-        return __CFDictionaryFindBuckets1a(hc, key);
-    }
-    return __CFDictionaryFindBuckets1b(hc, key);
-}
-
-static void __CFDictionaryFindBuckets2(CFHashRef hc, any_t key, CFIndex *match, CFIndex *nomatch) {
-    const CFDictionaryKeyCallBacks *cb = __CFDictionaryGetKeyCallBacks(hc);
-    CFHashCode keyHash = cb->hash ? (CFHashCode)INVOKE_CALLBACK2(((CFHashCode (*)(any_t, any_pointer_t))cb->hash), key, hc->_context) : (CFHashCode)key;
-    keyHash = __CFDictionaryScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    *match = kCFNotFound;
-    *nomatch = kCFNotFound;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            if (nomatch) *nomatch = probe;
-            return;
-        } else if (~marker == currKey) {        /* deleted */
-            if (nomatch) {
-                *nomatch = probe;
-                nomatch = NULL;
-            }
-        } else if (currKey == key || (cb->equal && INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))cb->equal, currKey, key, hc->_context))) {
-            *match = probe;
-            return;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return;
-        }
-    }
-}
-
-static void __CFDictionaryFindNewMarker(CFHashRef hc) {
-    any_t *keys = hc->_keys;
-    any_t newMarker;
-    CFIndex idx, nbuckets;
-    Boolean hit;
-
-    nbuckets = hc->_bucketsNum;
-    newMarker = hc->_marker;
-    do {
-        newMarker--;
-        hit = false;
-        for (idx = 0; idx < nbuckets; idx++) {
-            if (newMarker == keys[idx] || ~newMarker == keys[idx]) {
-                hit = true;
-                break;
-            }
-        }
-    } while (hit);
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (hc->_marker == keys[idx]) {
-            keys[idx] = newMarker;
-        } else if (~hc->_marker == keys[idx]) {
-            keys[idx] = ~newMarker;
-        }
-    }
-    ((struct __CFDictionary *)hc)->_marker = newMarker;
-}
-
 static Boolean __CFDictionaryEqual(CFTypeRef cf1, CFTypeRef cf2) {
-    CFHashRef hc1 = (CFHashRef)cf1;
-    CFHashRef hc2 = (CFHashRef)cf2;
-    const CFDictionaryKeyCallBacks *cb1, *cb2;
-    const CFDictionaryValueCallBacks *vcb1, *vcb2;
-    any_t *keys;
-    CFIndex idx, nbuckets;
-    if (hc1 == hc2) return true;
-    if (hc1->_count != hc2->_count) return false;
-    cb1 = __CFDictionaryGetKeyCallBacks(hc1);
-    cb2 = __CFDictionaryGetKeyCallBacks(hc2);
-    if (cb1->equal != cb2->equal) return false;
-    vcb1 = __CFDictionaryGetValueCallBacks(hc1);
-    vcb2 = __CFDictionaryGetValueCallBacks(hc2);
-    if (vcb1->equal != vcb2->equal) return false;
-    if (0 == hc1->_bucketsUsed) return true; /* after function comparison! */
-    keys = hc1->_keys;
-    nbuckets = hc1->_bucketsNum;
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (hc1->_marker != keys[idx] && ~hc1->_marker != keys[idx]) {
-#if CFDictionary
-            const_any_pointer_t value;
-            if (!CFDictionaryGetValueIfPresent(hc2, (any_pointer_t)keys[idx], &value)) return false;
-           if (hc1->_values[idx] != (any_t)value) {
-               if (NULL == vcb1->equal) return false;
-               if (!INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))vcb1->equal, hc1->_values[idx], (any_t)value, hc1->_context)) return false;
-            }
-#endif
-#if  CFSet
-            const_any_pointer_t value;
-            if (!CFDictionaryGetValueIfPresent(hc2, (any_pointer_t)keys[idx], &value)) return false;
-#endif
-#if CFBag
-            if (hc1->_values[idx] != CFDictionaryGetCountOfValue(hc2, (any_pointer_t)keys[idx])) return false;
-#endif
-        }
-    }
-    return true;
+    return __CFBasicHashEqual((CFBasicHashRef)cf1, (CFBasicHashRef)cf2);
 }
 
 static CFHashCode __CFDictionaryHash(CFTypeRef cf) {
-    CFHashRef hc = (CFHashRef)cf;
-    return hc->_count;
+    return __CFBasicHashHash((CFBasicHashRef)cf);
 }
 
 static CFStringRef __CFDictionaryCopyDescription(CFTypeRef cf) {
-    CFHashRef hc = (CFHashRef)cf;
-    CFAllocatorRef allocator;
-    const CFDictionaryKeyCallBacks *cb;
-    const CFDictionaryValueCallBacks *vcb;
-    any_t *keys;
-    CFIndex idx, nbuckets;
-    CFMutableStringRef result;
-    cb = __CFDictionaryGetKeyCallBacks(hc);
-    vcb = __CFDictionaryGetValueCallBacks(hc);
-    keys = hc->_keys;
-    nbuckets = hc->_bucketsNum;
-    allocator = CFGetAllocator(hc);
-    result = CFStringCreateMutable(allocator, 0);
-    const char *type = "?";
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashImmutable: type = "immutable"; break;
-    case __kCFHashMutable: type = "mutable"; break;
-    }
-    CFStringAppendFormat(result, NULL, CFSTR("<CFDictionary %p [%p]>{type = %s, count = %u, capacity = %u, pairs = (\n"), cf, allocator, type, hc->_count, hc->_bucketsCap);
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            CFStringRef kDesc = NULL, vDesc = NULL;
-            if (NULL != cb->copyDescription) {
-                kDesc = (CFStringRef)INVOKE_CALLBACK2(((CFStringRef (*)(any_t, any_pointer_t))cb->copyDescription), keys[idx], hc->_context);
-            }
-            if (NULL != vcb->copyDescription) {
-                vDesc = (CFStringRef)INVOKE_CALLBACK2(((CFStringRef (*)(any_t, any_pointer_t))vcb->copyDescription), hc->_values[idx], hc->_context);
-            }
-#if CFDictionary
-            if (NULL != kDesc && NULL != vDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ = %@\n"), idx, kDesc, vDesc);
-                CFRelease(kDesc);
-                CFRelease(vDesc);
-            } else if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ = <%p>\n"), idx, kDesc, hc->_values[idx]);
-                CFRelease(kDesc);
-            } else if (NULL != vDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> = %@\n"), idx, keys[idx], vDesc);
-                CFRelease(vDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> = <%p>\n"), idx, keys[idx], hc->_values[idx]);
-            }
-#endif
-#if CFSet
-            if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@\n"), idx, kDesc);
-                CFRelease(kDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, keys[idx]);
-            }
-#endif
-#if CFBag
-            if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ (%ld)\n"), idx, kDesc, hc->_values[idx]);
-                CFRelease(kDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> (%ld)\n"), idx, keys[idx], hc->_values[idx]);
-            }
-#endif
-        }
-    }
-    CFStringAppend(result, CFSTR(")}"));
-    return result;
+    return __CFBasicHashCopyDescription((CFBasicHashRef)cf);
 }
 
 static void __CFDictionaryDeallocate(CFTypeRef cf) {
-    CFMutableHashRef hc = (CFMutableHashRef)cf;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    const CFDictionaryKeyCallBacks *cb = __CFDictionaryGetKeyCallBacks(hc);
-    const CFDictionaryValueCallBacks *vcb = __CFDictionaryGetValueCallBacks(hc);
-
-    // mark now in case any callout somehow tries to add an entry back in
-    markFinalized(cf);
-    if (vcb->release || cb->release) {
-        any_t *keys = hc->_keys;
-        CFIndex idx, nbuckets = hc->_bucketsNum;
-        for (idx = 0; idx < nbuckets; idx++) {
-            any_t oldkey = keys[idx];
-            if (hc->_marker != oldkey && ~hc->_marker != oldkey) {
-                if (vcb->release) {
-                    INVOKE_CALLBACK3(((void (*)(CFAllocatorRef, any_t, any_pointer_t))vcb->release), allocator, hc->_values[idx], hc->_context);
-                }
-                if (cb->release) {
-                    INVOKE_CALLBACK3(((void (*)(CFAllocatorRef, any_t, any_pointer_t))cb->release), allocator, oldkey, hc->_context);
-                }
-            }
-        }
-    }
-
-    if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-        // return early so that contents are preserved after finalization
-        return;
-    }
-    
-    _CFAllocatorDeallocateGC(allocator, hc->_keys);
-#if CFDictionary || CFBag
-    _CFAllocatorDeallocateGC(allocator, hc->_values);
-#endif
-    hc->_keys = NULL;
-    hc->_values = NULL;
-    hc->_count = 0;  // GC: also zero count, so the hc will appear empty.
-    hc->_bucketsUsed = 0;
-    hc->_bucketsNum = 0;
+    __CFBasicHashDeallocate((CFBasicHashRef)cf);
 }
 
 static CFTypeID __kCFDictionaryTypeID = _kCFRuntimeNotATypeID;
@@ -658,123 +125,183 @@ static const CFRuntimeClass __CFDictionaryClass = {
     __CFDictionaryCopyDescription
 };
 
-__private_extern__ void __CFDictionaryInitialize(void) {
-    __kCFHashTypeID = _CFRuntimeRegisterClass(&__CFDictionaryClass);
-}
-
 CFTypeID CFDictionaryGetTypeID(void) {
-    return __kCFHashTypeID;
+    if (_kCFRuntimeNotATypeID == __kCFDictionaryTypeID) __kCFDictionaryTypeID = _CFRuntimeRegisterClass(&__CFDictionaryClass);
+    return __kCFDictionaryTypeID;
 }
 
-static CFMutableHashRef __CFDictionaryInit(CFAllocatorRef allocator, CFOptionFlags flags, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks
-#if CFDictionary
-, const CFDictionaryValueCallBacks *valueCallBacks
-#endif
-) {
-    struct __CFDictionary *hc;
-    CFIndex size;
-    __CFBitfieldSetValue(flags, 31, 2, 0);
-    CFOptionFlags xflags = 0;
+static uintptr_t __CFDictionaryCallback(CFBasicHashRef ht, uint8_t op, uintptr_t a1, uintptr_t a2, CFBasicHashCallbacks *cb) {
+    switch (op) {
+    case kCFBasicHashCallbackOpCopyCallbacks: {
+        CFBasicHashCallbacks *newcb = NULL;
+        if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
+            newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
+        } else {
+            newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate((CFAllocatorRef)a1, 10 * sizeof(void *), 0);
+        }
+        if (!newcb) HALT;
+        memmove(newcb, (void *)cb, 10 * sizeof(void *));
+        return (uintptr_t)newcb;
+    }
+    case kCFBasicHashCallbackOpFreeCallbacks: {
+        if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
+           auto_zone_release(auto_zone(), cb);
+       } else {
+            CFAllocatorDeallocate((CFAllocatorRef)a1, cb);
+        }
+        return 0;
+    }
+    case kCFBasicHashCallbackOpRetainValue: {
+        const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0];
+        if (NULL == value_retain) return a1;
+        return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpRetainKey: {
+        const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1];
+        if (NULL == key_retain) return a1;
+        return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpReleaseValue: {
+        void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2];
+        if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
+        return 0;
+    }
+    case kCFBasicHashCallbackOpReleaseKey: {
+        void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3];
+        if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
+        return 0;
+    }
+    case kCFBasicHashCallbackOpValueEqual: {
+        Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4];
+        if (NULL == value_equal) return (a1 == a2);
+        return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
+    }
+    case kCFBasicHashCallbackOpKeyEqual: {
+        Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5];
+        if (NULL == key_equal) return (a1 == a2);
+        return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
+    }
+    case kCFBasicHashCallbackOpHashKey: {
+        CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6];
+        if (NULL == hash) return a1;
+        return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpDescribeValue: {
+        CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[7];
+        if (NULL == value_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
+        return (uintptr_t)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpDescribeKey: {
+        CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8];
+        if (NULL == key_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
+        return (uintptr_t)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t)a1);
+    }
+    }
+    return 0;
+}
+
+static CFBasicHashRef __CFDictionaryCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
+
+    CFBasicHashCallbacks *cb = NULL;
+    CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
+    flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
+
+    const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    Boolean std_cb = false;
+    if ((NULL == keyCallBacks || (keyCallBacks && 0 == memcmp(&__kCFNullDictionaryKeyCallBacks, keyCallBacks, sizeof(__kCFNullDictionaryKeyCallBacks))))
+                && (!useValueCB || (NULL == valueCallBacks || (valueCallBacks && 0 == memcmp(&__kCFNullDictionaryValueCallBacks, valueCallBacks, sizeof(__kCFNullDictionaryValueCallBacks)))))) {
+        cb = (CFBasicHashCallbacks *)& CFBasicHashNullCallbacks;
+    } else if ((&kCFTypeDictionaryKeyCallBacks == keyCallBacks || (keyCallBacks && 0 == memcmp(&kCFTypeDictionaryKeyCallBacks, keyCallBacks, sizeof(kCFTypeDictionaryKeyCallBacks))))
+                && (!useValueCB || (&kCFTypeDictionaryValueCallBacks == valueCallBacks || (valueCallBacks && 0 == memcmp(&kCFTypeDictionaryValueCallBacks, valueCallBacks, sizeof(kCFTypeDictionaryValueCallBacks)))))) {
+        std_cb = true;
+        cb = (CFBasicHashCallbacks *)& CFBasicHashStandardCallbacks;
+    } else {
+        Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
+        Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
+        CFStringRef (*key_describe)(const_any_pointer_t) = NULL;
+        CFStringRef (*value_describe)(const_any_pointer_t) = NULL;
+        CFHashCode (*hash_key)(const_any_pointer_t) = NULL;
+        key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
+        key_release = keyCallBacks ? keyCallBacks->release : NULL;
+        key_equal = keyCallBacks ? keyCallBacks->equal : NULL;
+        key_describe = keyCallBacks ? keyCallBacks->copyDescription : NULL;
+        if (useValueCB) {
+            value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
+            value_release = valueCallBacks ? valueCallBacks->release : NULL;
+            value_equal = valueCallBacks ? valueCallBacks->equal : NULL;
+            value_describe = valueCallBacks ? valueCallBacks->copyDescription : NULL;
+        } else {
+            value_retain = key_retain;
+            value_release = key_release;
+            value_equal = key_equal;
+            value_describe = key_describe;
+        }
+        hash_key = keyCallBacks ? keyCallBacks->hash : NULL;
+        FAULT_CALLBACK((void **)&key_retain);
+        FAULT_CALLBACK((void **)&key_release);
+        FAULT_CALLBACK((void **)&value_retain);
+        FAULT_CALLBACK((void **)&value_release);
+        FAULT_CALLBACK((void **)&key_equal);
+        FAULT_CALLBACK((void **)&value_equal);
+        FAULT_CALLBACK((void **)&key_describe);
+        FAULT_CALLBACK((void **)&value_describe);
+        FAULT_CALLBACK((void **)&hash_key);
+
+        CFBasicHashCallbacks *newcb = NULL;
+        if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+            newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
+        } else {
+            newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, 10 * sizeof(void *), 0);
+        }
+        if (!newcb) HALT;
+        newcb->func = (CFBasicHashCallbackType)__CFDictionaryCallback;
+        newcb->context[0] = (uintptr_t)value_retain;
+        newcb->context[1] = (uintptr_t)key_retain;
+        newcb->context[2] = (uintptr_t)value_release;
+        newcb->context[3] = (uintptr_t)key_release;
+        newcb->context[4] = (uintptr_t)value_equal;
+        newcb->context[5] = (uintptr_t)key_equal;
+        newcb->context[6] = (uintptr_t)hash_key;
+        newcb->context[7] = (uintptr_t)value_describe;
+        newcb->context[8] = (uintptr_t)key_describe;
+        cb = newcb;
+    }
+
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-        // preserve NULL for key or value CB, otherwise fix up.
-        if (!keyCallBacks || (keyCallBacks->retain == NULL && keyCallBacks->release == NULL)) {
-            xflags = __kCFHashWeakKeys;
+        if (std_cb || value_retain != NULL || value_release != NULL) {
+            flags |= kCFBasicHashStrongValues;
         }
-#if CFDictionary
-        if (!valueCallBacks || (valueCallBacks->retain == NULL && valueCallBacks->release == NULL)) {
-            xflags |= __kCFHashWeakValues;
+        if (std_cb || key_retain != NULL || key_release != NULL) {
+            flags |= kCFBasicHashStrongKeys;
         }
-#endif
-#if CFBag
-        xflags |= __kCFHashWeakValues;
-#endif
-    }
-    if (__CFDictionaryKeyCallBacksMatchNull(keyCallBacks)) {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasNullCallBacks);
-    } else if (__CFDictionaryKeyCallBacksMatchCFType(keyCallBacks)) {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasCFTypeCallBacks);
-    } else {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasCustomCallBacks);
-    }
-#if CFDictionary
-    if (__CFDictionaryValueCallBacksMatchNull(valueCallBacks)) {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasNullCallBacks);
-    } else if (__CFDictionaryValueCallBacksMatchCFType(valueCallBacks)) {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasCFTypeCallBacks);
-    } else {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasCustomCallBacks);
-    }
-#endif
-    size = __CFDictionaryGetSizeOfType(flags) - sizeof(CFRuntimeBase);
-    hc = (struct __CFDictionary *)_CFRuntimeCreateInstance(allocator, __kCFHashTypeID, size, NULL);
-    if (NULL == hc) {
-        return NULL;
-    }
-    hc->_count = 0;
-    hc->_bucketsUsed = 0;
-    hc->_marker = (any_t)0xa1b1c1d3;
-    hc->_context = NULL;
-    hc->_deletes = 0;
-    hc->_mutations = 1;
-    hc->_xflags = xflags | flags;
-    switch (__CFBitfieldGetValue(flags, 1, 0)) {
-    case __kCFHashImmutable:
-        if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFDictionary (immutable)");
-        break;
-    case __kCFHashMutable:
-        if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFDictionary (mutable-variable)");
-        break;
-    }
-    hc->_bucketsCap = __CFHashRoundUpCapacity(1);
-    hc->_bucketsNum = 0;
-    hc->_keys = NULL;
-    hc->_values = NULL;
-    if (__kCFHashHasCustomCallBacks == __CFBitfieldGetValue(flags, 3, 2)) {
-        CFDictionaryKeyCallBacks *cb = (CFDictionaryKeyCallBacks *)__CFDictionaryGetKeyCallBacks((CFHashRef)hc);
-        *cb = *keyCallBacks;
-        FAULT_CALLBACK((void **)&(cb->retain));
-        FAULT_CALLBACK((void **)&(cb->release));
-        FAULT_CALLBACK((void **)&(cb->copyDescription));
-        FAULT_CALLBACK((void **)&(cb->equal));
-        FAULT_CALLBACK((void **)&(cb->hash));
     }
-#if CFDictionary
-    if (__kCFHashHasCustomCallBacks == __CFBitfieldGetValue(flags, 5, 4)) {
-        CFDictionaryValueCallBacks *vcb = (CFDictionaryValueCallBacks *)__CFDictionaryGetValueCallBacks((CFHashRef)hc);
-        *vcb = *valueCallBacks;
-        FAULT_CALLBACK((void **)&(vcb->retain));
-        FAULT_CALLBACK((void **)&(vcb->release));
-        FAULT_CALLBACK((void **)&(vcb->copyDescription));
-        FAULT_CALLBACK((void **)&(vcb->equal));
-    }
-#endif
-    return hc;
+
+    return CFBasicHashCreate(allocator, flags, cb);
 }
 
 #if CFDictionary
-CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *keys, const_any_pointer_t *values, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks) {
+CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks) {
 #endif
 #if CFSet || CFBag
-CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *keys, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks) {
+CFHashRef CFDictionaryCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks) {
+    const_any_pointer_t *vlist = klist;
+    const CFDictionaryValueCallBacks *valueCallBacks = 0;
 #endif
+    CFTypeID typeID = CFDictionaryGetTypeID();
     CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
-#if CFDictionary
-    CFMutableHashRef hc = __CFDictionaryInit(allocator, __kCFHashImmutable, numValues, keyCallBacks, valueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFDictionaryInit(allocator, __kCFHashImmutable, numValues, keyCallBacks);
-#endif
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashMutable);
+    CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+    if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
     for (CFIndex idx = 0; idx < numValues; idx++) {
-#if CFDictionary
-        CFDictionaryAddValue(hc, keys[idx], values[idx]);
-#endif
-#if CFSet || CFBag
-        CFDictionaryAddValue(hc, keys[idx]);
-#endif
+        CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
     }
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    return (CFHashRef)hc;
+    CFBasicHashMakeImmutable(ht);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
+    return (CFHashRef)ht;
 }
 
 #if CFDictionary
@@ -782,158 +309,90 @@ CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex cap
 #endif
 #if CFSet || CFBag
 CFMutableHashRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks) {
+    const CFDictionaryValueCallBacks *valueCallBacks = 0;
 #endif
+    CFTypeID typeID = CFDictionaryGetTypeID();
     CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
-#if CFDictionary
-    CFMutableHashRef hc = __CFDictionaryInit(allocator, __kCFHashMutable, capacity, keyCallBacks, valueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFDictionaryInit(allocator, __kCFHashMutable, capacity, keyCallBacks);
-#endif
-    return hc;
+    CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
+    return (CFMutableHashRef)ht;
 }
 
-#if CFDictionary || CFSet
-// does not have Add semantics for Bag; it has Set semantics ... is that best?
-static void __CFDictionaryGrow(CFMutableHashRef hc, CFIndex numNewValues);
-
-// This creates a hc which is for CFTypes or NSObjects, with a CFRetain style ownership transfer;
-// the hc does not take a retain (since it claims 1), and the caller does not need to release the inserted objects (since we do it).
-// The incoming objects must also be collectable if allocated out of a collectable allocator - and are neither released nor retained.
-#if CFDictionary
-CFHashRef _CFDictionaryCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const_any_pointer_t *keys, const_any_pointer_t *values, CFIndex numValues) {
-#endif
-#if CFSet || CFBag
-CFHashRef _CFDictionaryCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const_any_pointer_t *keys, CFIndex numValues) {
-#endif
-    CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
-#if CFDictionary
-    CFMutableHashRef hc = __CFDictionaryInit(allocator, __kCFHashMutable, numValues, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFDictionaryInit(allocator, __kCFHashMutable, numValues, &kCFTypeDictionaryKeyCallBacks);
-#endif
-    __CFDictionaryGrow(hc, numValues);
-    for (CFIndex idx = 0; idx < numValues; idx++) {
-        CFIndex match, nomatch;
-        __CFDictionaryFindBuckets2(hc, (any_t)keys[idx], &match, &nomatch);
-        if (kCFNotFound == match) {
-            CFAllocatorRef allocator = __CFGetAllocator(hc);
-            any_t newKey = (any_t)keys[idx];
-            if (__CFHashKeyIsMagic(hc, newKey)) {
-                __CFDictionaryFindNewMarker(hc);
-            }
-            if (hc->_keys[nomatch] == ~hc->_marker) {
-                hc->_deletes--;
-            }
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-            any_t newValue = (any_t)values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-            hc->_values[nomatch] = 1;
-#endif
-            hc->_bucketsUsed++;
-            hc->_count++;
-        } else {
-            CFAllocatorRef allocator = __CFGetAllocator(hc);
+CFHashRef CFDictionaryCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
+    CFTypeID typeID = CFDictionaryGetTypeID();
+    CFAssert1(other, __kCFLogAssertion, "%s(): other CFDictionary cannot be NULL", __PRETTY_FUNCTION__);
+    __CFGenericValidateType(other, typeID);
+    CFBasicHashRef ht = NULL;
+    if (CF_IS_OBJC(typeID, other)) {
+        CFIndex numValues = CFDictionaryGetCount(other);
+        const_any_pointer_t vbuffer[256], kbuffer[256];
+        const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
 #if CFSet || CFBag
-            any_t oldKey = hc->_keys[match];
-            any_t newKey = (any_t)keys[idx];
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-            if (__CFHashKeyIsMagic(hc, newKey)) {
-                __CFDictionaryFindNewMarker(hc);
-            }
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-            RELEASEKEY(oldKey);
+        const_any_pointer_t *klist = vlist;
+        CFDictionaryGetValues(other, vlist);
 #endif
 #if CFDictionary
-            any_t oldValue = hc->_values[match];
-            any_t newValue = (any_t)values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-            RELEASEVALUE(oldValue);
+        const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
+        CFDictionaryGetKeysAndValues(other, klist, vlist);
 #endif
+        ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
+        if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+        for (CFIndex idx = 0; idx < numValues; idx++) {
+            CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
         }
+        if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
+        if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
+    } else {
+        ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
     }
-    if (!isMutable) __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    return (CFHashRef)hc;
-}
-#endif
-
-CFHashRef CFDictionaryCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
-    CFMutableHashRef hc = CFDictionaryCreateMutableCopy(allocator, CFDictionaryGetCount(other), other);
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFDictionary (immutable)");
-    return hc;
+    CFBasicHashMakeImmutable(ht);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (immutable)");
+    return (CFHashRef)ht;
 }
 
 CFMutableHashRef CFDictionaryCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) {
-    CFIndex numValues = CFDictionaryGetCount(other);
-    const_any_pointer_t *list, buffer[256];
-    list = (numValues <= 256) ? buffer : (const_any_pointer_t *)CFAllocatorAllocate(allocator, numValues * sizeof(const_any_pointer_t), 0);
-    if (list != buffer && __CFOASafe) __CFSetLastAllocationEventName(list, "CFDictionary (temp)");
-#if CFDictionary
-    const_any_pointer_t *vlist, vbuffer[256];
-    vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(allocator, numValues * sizeof(const_any_pointer_t), 0);
-    if (vlist != vbuffer && __CFOASafe) __CFSetLastAllocationEventName(vlist, "CFDictionary (temp)");
-#endif
+    CFTypeID typeID = CFDictionaryGetTypeID();
+    CFAssert1(other, __kCFLogAssertion, "%s(): other CFDictionary cannot be NULL", __PRETTY_FUNCTION__);
+    __CFGenericValidateType(other, typeID);
+    CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
+    CFBasicHashRef ht = NULL;
+    if (CF_IS_OBJC(typeID, other)) {
+        CFIndex numValues = CFDictionaryGetCount(other);
+        const_any_pointer_t vbuffer[256], kbuffer[256];
+        const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
 #if CFSet || CFBag
-    CFDictionaryGetValues(other, list);
+        const_any_pointer_t *klist = vlist;
+        CFDictionaryGetValues(other, vlist);
 #endif
 #if CFDictionary
-    CFDictionaryGetKeysAndValues(other, list, vlist);
+        const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
+        CFDictionaryGetKeysAndValues(other, klist, vlist);
 #endif
-    const CFDictionaryKeyCallBacks *kcb;
-    const CFDictionaryValueCallBacks *vcb;
-    if (CF_IS_OBJC(__kCFHashTypeID, other)) {
-        kcb = &kCFTypeDictionaryKeyCallBacks;
-        vcb = &kCFTypeDictionaryValueCallBacks;
+        ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
+        if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+        for (CFIndex idx = 0; idx < numValues; idx++) {
+            CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
+        }
+        if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
+        if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
     } else {
-        kcb = __CFDictionaryGetKeyCallBacks(other);
-        vcb = __CFDictionaryGetValueCallBacks(other);
+        ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
     }
-#if CFDictionary
-    CFMutableHashRef hc = __CFDictionaryInit(allocator, __kCFHashMutable, capacity, kcb, vcb);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFDictionaryInit(allocator, __kCFHashMutable, capacity, kcb);
-#endif
-    if (0 == capacity) _CFDictionarySetCapacity(hc, numValues);
-    for (CFIndex idx = 0; idx < numValues; idx++) {
-#if CFDictionary
-        CFDictionaryAddValue(hc, list[idx], vlist[idx]);
-#endif
-#if CFSet || CFBag
-        CFDictionaryAddValue(hc, list[idx]);
-#endif
-    }
-    if (list != buffer) CFAllocatorDeallocate(allocator, list);
-#if CFDictionary
-    if (vlist != vbuffer) CFAllocatorDeallocate(allocator, vlist);
-#endif
-    return hc;
-}
-
-// Used by NSHashTables/NSMapTables and KVO
-void _CFDictionarySetContext(CFHashRef hc, any_pointer_t context) {
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    CF_WRITE_BARRIER_BASE_ASSIGN(__CFGetAllocator(hc), hc, hc->_context, context);
-}
-
-any_pointer_t _CFDictionaryGetContext(CFHashRef hc) {
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    return hc->_context;
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
+    return (CFMutableHashRef)ht;
 }
 
 CFIndex CFDictionaryGetCount(CFHashRef hc) {
-    if (CFDictionary || CFSet) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, CFIndex, hc, "count");
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    return hc->_count;
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, CFIndex, hc, "count");
+    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, CFIndex, hc, "count");
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    return CFBasicHashGetCount((CFBasicHashRef)hc);
 }
 
 #if CFDictionary
@@ -942,12 +401,10 @@ CFIndex CFDictionaryGetCountOfKey(CFHashRef hc, const_any_pointer_t key) {
 #if CFSet || CFBag
 CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    CFIndex match = __CFDictionaryFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? __CFHashGetOccurrenceCount(hc, match) : 0);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForObject:", key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
 }
 
 #if CFDictionary
@@ -956,74 +413,66 @@ Boolean CFDictionaryContainsKey(CFHashRef hc, const_any_pointer_t key) {
 #if CFSet || CFBag
 Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t key) {
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFDictionaryFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? true : false);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsObject:", key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
 }
 
-#if CFDictionary
-CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
-    CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForObject:", value);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    any_t *keys = hc->_keys;
-    Boolean (*equal)(any_t, any_t, any_pointer_t) = (Boolean (*)(any_t, any_t, any_pointer_t))__CFDictionaryGetValueCallBacks(hc)->equal;
-    CFIndex cnt = 0;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            if ((hc->_values[idx] == (any_t)value) || (equal && INVOKE_CALLBACK3(equal, hc->_values[idx], (any_t)value, hc->_context))) {
-                cnt++;
-            }
-        }
-    }
-    return cnt;
+const_any_pointer_t CFDictionaryGetValue(CFHashRef hc, const_any_pointer_t key) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, const_any_pointer_t, hc, "objectForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, const_any_pointer_t, hc, "member:", key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
 }
 
-Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
-    CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsObject:", value);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    any_t *keys = hc->_keys;
-    Boolean (*equal)(any_t, any_t, any_pointer_t) = (Boolean (*)(any_t, any_t, any_pointer_t))__CFDictionaryGetValueCallBacks(hc)->equal;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            if ((hc->_values[idx] == (any_t)value) || (equal && INVOKE_CALLBACK3(equal, hc->_values[idx], (any_t)value, hc->_context))) {
-                return true;
+Boolean CFDictionaryGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "_getValue:forKey:", (any_t *)value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "_getValue:forObj:", (any_t *)value, key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    if (0 < bkt.count) {
+        if (value) {
+            if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongValues)) {
+                __CFAssignWithWriteBarrier((void **)value, (void *)bkt.weak_value);
+            } else {
+                *value = (const_any_pointer_t)bkt.weak_value;
             }
         }
+        return true;
     }
     return false;
 }
-#endif
-
-const_any_pointer_t CFDictionaryGetValue(CFHashRef hc, const_any_pointer_t key) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, const_any_pointer_t, hc, "objectForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, const_any_pointer_t, hc, "member:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    CFIndex match = __CFDictionaryFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? (const_any_pointer_t)(CFDictionary ? hc->_values[match] : hc->_keys[match]) : 0);
-}
 
-Boolean CFDictionaryGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "_getValue:forKey:", (any_t *)value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "_getValue:forObj:", (any_t *)value, key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFDictionaryFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? ((value ? __CFObjCStrongAssign((const_any_pointer_t)(CFDictionary ? hc->_values[match] : hc->_keys[match]), value) : 0), true) : false);
+#if CFDictionary
+CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
+    CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForObject:", value);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
 }
 
-#if CFDictionary
-Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
-    CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFDictionaryFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? ((actualkey ? __CFObjCStrongAssign((const_any_pointer_t)hc->_keys[match], actualkey) : NULL), true) : false);
+Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
+    CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsObject:", value);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
+}
+
+CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
+    CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    if (0 < bkt.count) {
+        if (actualkey) {
+            if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongKeys)) {
+                __CFAssignWithWriteBarrier((void **)actualkey, (void *)bkt.weak_key);
+            } else {
+                *actualkey = (const_any_pointer_t)bkt.weak_key;
+            }
+        }
+        return true;
+    }
+    return false;
 }
 #endif
 
@@ -1034,183 +483,113 @@ void CFDictionaryGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, con
 void CFDictionaryGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
     const_any_pointer_t *valuebuf = 0;
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "getObjects:", (any_t *)keybuf);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (CF_USING_COLLECTABLE_MEMORY) {
-        // GC: speculatively issue a write-barrier on the copied to buffers
-        __CFObjCWriteBarrierRange(keybuf, hc->_count * sizeof(any_t));
-        __CFObjCWriteBarrierRange(valuebuf, hc->_count * sizeof(any_t));
-    }
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            for (CFIndex cnt = __CFHashGetOccurrenceCount(hc, idx); cnt--;) {
-                if (keybuf) *keybuf++ = (const_any_pointer_t)keys[idx];
-                if (valuebuf) *valuebuf++ = (const_any_pointer_t)hc->_values[idx];
-            }
-        }
-    }
-}
-
-#if CFDictionary || CFSet
-unsigned long _CFDictionaryFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
-    /* copy as many as count items over */
-    if (0 == state->state) {        /* first time */
-        state->mutationsPtr = (unsigned long *)&hc->_mutations;
-    }
-    state->itemsPtr = (unsigned long *)stackbuffer;
-    CFIndex cnt = 0;
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = (CFIndex)state->state, nbuckets = hc->_bucketsNum; idx < nbuckets && cnt < (CFIndex)count; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            state->itemsPtr[cnt++] = (unsigned long)keys[idx];
-        }
-        state->state++;
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "getObjects:", (any_t *)keybuf);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    if (kCFUseCollectableAllocator) {
+        CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
+        __block const_any_pointer_t *keys = keybuf, *values = valuebuf;
+        CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
+                for (CFIndex cnt = bkt.count; cnt--;) {
+                    if (keybuf && (flags & kCFBasicHashStrongKeys)) { __CFAssignWithWriteBarrier((void **)keys, (void *)bkt.weak_key); keys++; }
+                    if (keybuf && !(flags & kCFBasicHashStrongKeys)) { *keys++ = (const_any_pointer_t)bkt.weak_key; }
+                    if (valuebuf && (flags & kCFBasicHashStrongValues)) { __CFAssignWithWriteBarrier((void **)values, (void *)bkt.weak_value); values++; }
+                    if (valuebuf && !(flags & kCFBasicHashStrongValues)) { *values++ = (const_any_pointer_t)bkt.weak_value; }
+                }
+                return (Boolean)true;
+            });
+    } else {
+        CFBasicHashGetElements((CFBasicHashRef)hc, CFDictionaryGetCount(hc), (uintptr_t *)valuebuf, NULL, (uintptr_t *)keybuf, NULL);
     }
-    return cnt;
 }
-#endif
 
 void CFDictionaryApplyFunction(CFHashRef hc, CFDictionaryApplierFunction applier, any_pointer_t context) {
     FAULT_CALLBACK((void **)&(applier));
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_apply:context:", applier, context);
-    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_applyValues:context:", applier, context);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            for (CFIndex cnt = __CFHashGetOccurrenceCount(hc, idx); cnt--;) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "_apply:context:", applier, context);
+    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "_applyValues:context:", applier, context);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
 #if CFDictionary
-                INVOKE_CALLBACK3(applier, (const_any_pointer_t)keys[idx], (const_any_pointer_t)hc->_values[idx], context);
+            INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context);
 #endif
-#if CFSet || CFBag
-                INVOKE_CALLBACK2(applier, (const_any_pointer_t)keys[idx], context);
+#if CFSet
+            INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
 #endif
+#if CFBag
+            for (CFIndex cnt = bkt.count; cnt--;) {
+                INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
             }
-        }
-    }
+#endif
+            return (Boolean)true;
+        });
 }
 
-static void __CFDictionaryGrow(CFMutableHashRef hc, CFIndex numNewValues) {
-    any_t *oldkeys = hc->_keys;
-    any_t *oldvalues = hc->_values;
-    CFIndex nbuckets = hc->_bucketsNum;
-    hc->_bucketsCap = __CFHashRoundUpCapacity(hc->_bucketsUsed + numNewValues);
-    hc->_bucketsNum = __CFHashNumBucketsForCapacity(hc->_bucketsCap);
-    hc->_deletes = 0;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    CFOptionFlags weakOrStrong = (hc->_xflags & __kCFHashWeakKeys) ? 0 : __kCFAllocatorGCScannedMemory;
-    any_t *mem = (any_t *)_CFAllocatorAllocateGC(allocator, hc->_bucketsNum * sizeof(any_t), weakOrStrong);
-    if (NULL == mem) __CFDictionaryHandleOutOfMemory(hc, hc->_bucketsNum * sizeof(any_t));
-    if (__CFOASafe) __CFSetLastAllocationEventName(mem, "CFDictionary (key-store)");
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, hc, hc->_keys, mem);
-    CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;  // GC: avoids write-barrier in weak case.
-    any_t *keysBase = mem;
-#if CFDictionary || CFBag
-    weakOrStrong = (hc->_xflags & __kCFHashWeakValues) ? 0 : __kCFAllocatorGCScannedMemory;
-    mem = (any_t *)_CFAllocatorAllocateGC(allocator, hc->_bucketsNum * sizeof(any_t), weakOrStrong);
-    if (NULL == mem) __CFDictionaryHandleOutOfMemory(hc, hc->_bucketsNum * sizeof(any_t));
-    if (__CFOASafe) __CFSetLastAllocationEventName(mem, "CFDictionary (value-store)");
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, hc, hc->_values, mem);
-#endif
-#if CFDictionary
-    CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator; // GC: avoids write-barrier in weak case.
-    any_t *valuesBase = mem;
-#endif
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        hc->_keys[idx] = hc->_marker;
-#if CFDictionary || CFBag
-        hc->_values[idx] = 0;
-#endif
-    }
-    if (NULL == oldkeys) return;
-    for (CFIndex idx = 0; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, oldkeys[idx])) {
-            CFIndex match, nomatch;
-            __CFDictionaryFindBuckets2(hc, oldkeys[idx], &match, &nomatch);
-            CFAssert3(kCFNotFound == match, __kCFLogAssertion, "%s(): two values (%p, %p) now hash to the same slot; mutable value changed while in table or hash value is not immutable", __PRETTY_FUNCTION__, oldkeys[idx], hc->_keys[match]);
-            if (kCFNotFound != nomatch) {
-                CF_WRITE_BARRIER_BASE_ASSIGN(keysAllocator, keysBase, hc->_keys[nomatch], oldkeys[idx]);
-#if CFDictionary
-                CF_WRITE_BARRIER_BASE_ASSIGN(valuesAllocator, valuesBase, hc->_values[nomatch], oldvalues[idx]);
-#endif
-#if CFBag
-                hc->_values[nomatch] = oldvalues[idx];
-#endif
-            }
-        }
-    }
-    _CFAllocatorDeallocateGC(allocator, oldkeys);
-    _CFAllocatorDeallocateGC(allocator, oldvalues);
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT unsigned long _CFDictionaryFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
+    if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return 0;
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count);
+}
+
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT Boolean _CFDictionaryIsMutable(CFHashRef hc) {
+    if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return false;
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    return CFBasicHashIsMutable((CFBasicHashRef)hc);
+}
+
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT void _CFDictionarySetCapacity(CFMutableHashRef hc, CFIndex cap) {
+    if (CF_IS_OBJC(__kCFDictionaryTypeID, hc)) return;
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    CFAssert3(CFDictionaryGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFDictionaryGetCount(hc));
+    CFBasicHashSetCapacity((CFBasicHashRef)hc, cap);
+}
+
+CF_INLINE CFIndex __CFDictionaryGetKVOBit(CFHashRef hc) {
+    return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0);
+}
+
+CF_INLINE void __CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
+    __CFBitfieldSetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0, ((uintptr_t)bit & 0x1));
+}
+
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT CFIndex _CFDictionaryGetKVOBit(CFHashRef hc) {
+    return __CFDictionaryGetKVOBit(hc);
 }
 
 // This function is for Foundation's benefit; no one else should use it.
-void _CFDictionarySetCapacity(CFMutableHashRef hc, CFIndex cap) {
-    if (CF_IS_OBJC(__kCFHashTypeID, hc)) return;
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    CFAssert1(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): collection is immutable", __PRETTY_FUNCTION__);
-    CFAssert3(hc->_bucketsUsed <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than bucket count (%ld)", __PRETTY_FUNCTION__, cap, hc->_bucketsUsed);
-    __CFDictionaryGrow(hc, cap - hc->_bucketsUsed);
+CF_EXPORT void _CFDictionarySetKVOBit(CFHashRef hc, CFIndex bit) {
+    __CFDictionarySetKVOBit(hc, bit);
 }
 
 
+#if !defined(CF_OBJC_KVO_WILLCHANGE)
+#define CF_OBJC_KVO_WILLCHANGE(obj, key)
+#define CF_OBJC_KVO_DIDCHANGE(obj, key)
+#define CF_OBJC_KVO_WILLCHANGEALL(obj)
+#define CF_OBJC_KVO_DIDCHANGEALL(obj)
+#endif
+
 #if CFDictionary
 void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
 #endif
 #if CFSet || CFBag
 void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
+    const_any_pointer_t value = key;
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_addObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "addObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        if (hc->_bucketsUsed == hc->_bucketsCap || NULL == hc->_keys) {
-            __CFDictionaryGrow(hc, 1);
-        }
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    CFIndex match, nomatch;
-    __CFDictionaryFindBuckets2(hc, (any_t)key, &match, &nomatch);
-    if (kCFNotFound != match) {
-#if CFBag
-        CF_OBJC_KVO_WILLCHANGE(hc, hc->_keys[match]);
-        hc->_values[match]++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, hc->_keys[match]);
-#endif
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        GETNEWKEY(newKey, key);
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFDictionaryFindNewMarker(hc);
-        }
-        if (hc->_keys[nomatch] == ~hc->_marker) {
-            hc->_deletes--;
-        }
-        CF_OBJC_KVO_WILLCHANGE(hc, key);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-        hc->_values[nomatch] = 1;
-#endif
-        hc->_bucketsUsed++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, key);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "addObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "addObject:", key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 #if CFDictionary
@@ -1218,51 +597,18 @@ void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, cons
 #endif
 #if CFSet || CFBag
 void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
-#endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_replaceObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "_replaceObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFIndex match = __CFDictionaryFindBuckets1(hc, (any_t)key);
-    if (kCFNotFound == match) return;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-#if CFSet || CFBag
-    GETNEWKEY(newKey, key);
-#endif
-#if CFDictionary
-    GETNEWVALUE(newValue);
+    const_any_pointer_t value = key;
 #endif
-    any_t oldKey = hc->_keys[match];
-    CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFSet || CFBag
-    CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-    CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-    if (__CFHashKeyIsMagic(hc, newKey)) {
-        __CFDictionaryFindNewMarker(hc);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "replaceObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "replaceObject:", key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
-    CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-#endif
-#if CFDictionary
-    any_t oldValue = hc->_values[match];
-    CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-    CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-#endif
-    CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-#if CFSet || CFBag
-    RELEASEKEY(oldKey);
-#endif
-#if CFDictionary
-    RELEASEVALUE(oldValue);
-#endif
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 #if CFDictionary
@@ -1270,198 +616,48 @@ void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key, const_an
 #endif
 #if CFSet || CFBag
 void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
-#endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "setObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "_setObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        if (hc->_bucketsUsed == hc->_bucketsCap || NULL == hc->_keys) {
-            __CFDictionaryGrow(hc, 1);
-        }
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    CFIndex match, nomatch;
-    __CFDictionaryFindBuckets2(hc, (any_t)key, &match, &nomatch);
-    if (kCFNotFound == match) {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        GETNEWKEY(newKey, key);
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFDictionaryFindNewMarker(hc);
-        }
-        if (hc->_keys[nomatch] == ~hc->_marker) {
-            hc->_deletes--;
-        }
-        CF_OBJC_KVO_WILLCHANGE(hc, key);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-        hc->_values[nomatch] = 1;
-#endif
-        hc->_bucketsUsed++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, key);
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-#if CFSet || CFBag
-        GETNEWKEY(newKey, key);
-#endif
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        any_t oldKey = hc->_keys[match];
-        CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFSet || CFBag
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFDictionaryFindNewMarker(hc);
-        }
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-#endif
-#if CFDictionary
-        any_t oldValue = hc->_values[match];
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-#endif
-        CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-#if CFSet || CFBag
-        RELEASEKEY(oldKey);
-#endif
-#if CFDictionary
-        RELEASEVALUE(oldValue);
+    const_any_pointer_t value = key;
 #endif
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "setObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "_setObject:", key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+//#warning this for a dictionary used to not replace the key
+    CFBasicHashSetValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 void CFDictionaryRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "removeObjectForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "removeObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFIndex match = __CFDictionaryFindBuckets1(hc, (any_t)key);
-    if (kCFNotFound == match) return;
-    if (1 < __CFHashGetOccurrenceCount(hc, match)) {
-#if CFBag
-        CF_OBJC_KVO_WILLCHANGE(hc, hc->_keys[match]);
-        hc->_values[match]--;
-        hc->_count--;
-        CF_OBJC_KVO_DIDCHANGE(hc, hc->_keys[match]);
-#endif
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        any_t oldKey = hc->_keys[match];
-        CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-#if CFDictionary
-        any_t oldValue = hc->_values[match];
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], 0);
-#endif
-#if CFBag
-        hc->_values[match] = 0;
-#endif
-        hc->_count--;
-        hc->_bucketsUsed--;
-        hc->_deletes++;
-        CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-        RELEASEKEY(oldKey);
-#if CFDictionary
-        RELEASEVALUE(oldValue);
-#endif
-        if (__CFDictionaryShouldShrink(hc)) {
-            __CFDictionaryGrow(hc, 0);
-        } else {
-            // When the probeskip == 1 always and only, a DELETED slot followed by an EMPTY slot
-            // can be converted to an EMPTY slot.  By extension, a chain of DELETED slots followed
-            // by an EMPTY slot can be converted to EMPTY slots, which is what we do here.
-            if (match < hc->_bucketsNum - 1 && hc->_keys[match + 1] == hc->_marker) {
-                while (0 <= match && hc->_keys[match] == ~hc->_marker) {
-                    hc->_keys[match] = hc->_marker;
-                    hc->_deletes--;
-                    match--;
-                }
-            }
-        }
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "removeObjectForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "removeObject:", key);
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 void CFDictionaryRemoveAllValues(CFMutableHashRef hc) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, void, hc, "removeAllObjects");
-    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, void, hc, "removeAllObjects");
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            any_t oldKey = keys[idx];
-            CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFDictionary || CFSet
-            hc->_count--;
-#endif
-#if CFBag
-            hc->_count -= hc->_values[idx];
-#endif
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[idx], ~hc->_marker);
-#if CFDictionary
-            any_t oldValue = hc->_values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[idx], 0);
-#endif
-#if CFBag
-            hc->_values[idx] = 0;
-#endif
-            hc->_bucketsUsed--;
-            hc->_deletes++;
-            CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-            RELEASEKEY(oldKey);
-#if CFDictionary
-            RELEASEVALUE(oldValue);
-#endif
-        }
-    }
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        keys[idx] = hc->_marker;
-    }
-    hc->_deletes = 0;
-    hc->_bucketsUsed = 0;
-    hc->_count = 0;
-    if (__CFDictionaryShouldShrink(hc) && (256 <= hc->_bucketsCap)) {
-        __CFDictionaryGrow(hc, 128);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, void, hc, "removeAllObjects");
+    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, void, hc, "removeAllObjects");
+    __CFGenericValidateType(hc, __kCFDictionaryTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGEALL(hc);
+    CFBasicHashRemoveAllValues((CFBasicHashRef)hc);
+    CF_OBJC_KVO_DIDCHANGEALL(hc);
 }
 
 #undef CF_OBJC_KVO_WILLCHANGE
 #undef CF_OBJC_KVO_DIDCHANGE
+#undef CF_OBJC_KVO_WILLCHANGEALL
+#undef CF_OBJC_KVO_DIDCHANGEALL
 
index 2ca8ecf2b5dac43164afa55f31b4eb5cf2007d89..26611ac49aea6f56bd3bc87a965d6b82f961bff5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFDictionary.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 /*!
@@ -69,9 +69,9 @@
 
        Computational Complexity
        The access time for a value in the dictionary is guaranteed to be at
-       worst O(lg N) for any implementation, current and future, but will
+       worst O(N) for any implementation, current and future, but will
        often be O(1) (constant time). Insertion or deletion operations
-       will typically be constant time as well, but are O(N*lg N) in the
+       will typically be constant time as well, but are O(N*N) in the
        worst case in some implementations. Access of values through a key
        is faster than accessing values directly (if there are any such
        operations). Dictionaries will tend to use significantly more memory
index cae76446f5e3360966a354967e08c455436687b4..ab8895db6ac45e64893673f20579b02437916f46 100644 (file)
--- a/CFError.c
+++ b/CFError.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFError.c
-       Copyright 2006, Apple, Inc. All rights reserved.
+       Copyright 2006-2009, Apple Inc. All rights reserved.
        Responsibility: Ali Ozer
 */
 
 #include <CoreFoundation/CFError.h>
 #include <CoreFoundation/CFError_Private.h>
 #include "CFInternal.h"
-#include "CFPriv.h"
-#if DEPLOYMENT_TARGET_MACOSX
+#include <CoreFoundation/CFPriv.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <objc/runtime.h>
 #include <mach/mach_error.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 /* Pre-defined userInfo keys
@@ -225,13 +228,28 @@ CFStringRef _CFErrorCreateLocalizedDescription(CFErrorRef err) {
     CFStringRef localizedDesc = _CFErrorCopyUserInfoKey(err, kCFErrorLocalizedDescriptionKey);
     if (localizedDesc) return localizedDesc;
 
-    // Cache the CF bundle since we will be using it for localized strings. !!! Might be good to check for NULL, although that indicates some serious problem.
+    // Cache the CF bundle since we will be using it for localized strings.
     CFBundleRef cfBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreFoundation"));
 
+    if (!cfBundle) {   // This should be rare, but has been observed in the wild, due to running out of file descriptors. Normally we might not go to such extremes, but since we want to be able to present reasonable errors even in the case of errors such as running out of file descriptors, why not. This is CFError after all. !!! Be sure to have the same logic here as below for going through various options for fetching the strings.
+    
+       CFStringRef result = NULL, reasonOrDesc;
+
+       if ((reasonOrDesc = _CFErrorCopyUserInfoKey(err, kCFErrorLocalizedFailureReasonKey))) {     // First look for kCFErrorLocalizedFailureReasonKey
+           result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("The operation couldn\\U2019t be completed. %@"), reasonOrDesc);
+       } else if ((reasonOrDesc = _CFErrorCopyUserInfoKey(err, kCFErrorDescriptionKey))) {         // Then try kCFErrorDescriptionKey
+           result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("The operation couldn\\U2019t be completed. (%@ error %ld - %@)"), CFErrorGetDomain(err), (long)CFErrorGetCode(err), reasonOrDesc);
+       } else {        // Last resort, just the domain and code
+           result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("The operation couldn\\U2019t be completed. (%@ error %ld.)"), CFErrorGetDomain(err), (long)CFErrorGetCode(err));
+       }
+       if (reasonOrDesc) CFRelease(reasonOrDesc);
+       return result;
+    }
+
     // Then look for kCFErrorLocalizedFailureReasonKey; if there, create a full sentence from that.
     CFStringRef reason = _CFErrorCopyUserInfoKey(err, kCFErrorLocalizedFailureReasonKey);
     if (reason) {
-       CFStringRef operationFailedStr = CFCopyLocalizedStringFromTableInBundle(CFSTR("Operation could not be completed. %@"), CFSTR("Error"), cfBundle, "A generic error string indicating there was a problem. The %@ will be replaced by a second sentence which indicates why the operation failed.");
+       CFStringRef operationFailedStr = CFCopyLocalizedStringFromTableInBundle(CFSTR("The operation couldn\\U2019t be completed. %@"), CFSTR("Error"), cfBundle, "A generic error string indicating there was a problem. The %@ will be replaced by a second sentence which indicates why the operation failed.");
         CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, operationFailedStr, reason);
        CFRelease(operationFailedStr);
         CFRelease(reason);
@@ -243,12 +261,12 @@ CFStringRef _CFErrorCreateLocalizedDescription(CFErrorRef err) {
     CFStringRef desc = _CFErrorCopyUserInfoKey(err, kCFErrorDescriptionKey);
     CFStringRef localizedDomain = CFCopyLocalizedStringFromTableInBundle(CFErrorGetDomain(err), CFSTR("Error"), cfBundle, "These are localized in the comment above");
     if (desc) {     // We have kCFErrorDescriptionKey, so include that with the error domain and code
-       CFStringRef operationFailedStr = CFCopyLocalizedStringFromTableInBundle(CFSTR("Operation could not be completed. (%@ error %ld - %@)"), CFSTR("Error"), cfBundle, "A generic error string indicating there was a problem, followed by a parenthetical sentence which indicates error domain, code, and a description when there is no other way to present an error to the user. The first %@ indicates the error domain, %ld indicates the error code, and the second %@ indicates the description; so this might become '(Mach error 42 - Server error.)' for instance.");
+       CFStringRef operationFailedStr = CFCopyLocalizedStringFromTableInBundle(CFSTR("The operation couldn\\U2019t be completed. (%@ error %ld - %@)"), CFSTR("Error"), cfBundle, "A generic error string indicating there was a problem, followed by a parenthetical sentence which indicates error domain, code, and a description when there is no other way to present an error to the user. The first %@ indicates the error domain, %ld indicates the error code, and the second %@ indicates the description; so this might become '(Mach error 42 - Server error.)' for instance.");
        result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, operationFailedStr, localizedDomain, (long)CFErrorGetCode(err), desc);
        CFRelease(operationFailedStr);
         CFRelease(desc);
     } else {        // We don't have kCFErrorDescriptionKey, so just use error domain and code
-       CFStringRef operationFailedStr = CFCopyLocalizedStringFromTableInBundle(CFSTR("Operation could not be completed. (%@ error %ld.)"), CFSTR("Error"), cfBundle, "A generic error string indicating there was a problem, followed by a parenthetical sentence which indicates error domain and code when there is no other way to present an error to the user. The %@ indicates the error domain while %ld indicates the error code; so this might become '(Mach error 42.)' for instance.");
+       CFStringRef operationFailedStr = CFCopyLocalizedStringFromTableInBundle(CFSTR("The operation couldn\\U2019t be completed. (%@ error %ld.)"), CFSTR("Error"), cfBundle, "A generic error string indicating there was a problem, followed by a parenthetical sentence which indicates error domain and code when there is no other way to present an error to the user. The %@ indicates the error domain while %ld indicates the error code; so this might become '(Mach error 42.)' for instance.");
        result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, operationFailedStr, localizedDomain, (long)CFErrorGetCode(err));
        CFRelease(operationFailedStr);
     }
@@ -276,11 +294,20 @@ CFStringRef _CFErrorCreateDebugDescription(CFErrorRef err) {
     CFStringRef desc = CFErrorCopyDescription(err);
     CFStringRef debugDesc = _CFErrorCopyUserInfoKey(err, kCFErrorDebugDescriptionKey);
     CFDictionaryRef userInfo = _CFErrorGetUserInfo(err);
+    CFErrorRef underlyingError = NULL;    
     CFMutableStringRef result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
     CFStringAppendFormat(result, NULL, CFSTR("Error Domain=%@ Code=%d"), CFErrorGetDomain(err), (long)CFErrorGetCode(err));
-    if (userInfo) CFStringAppendFormat(result, NULL, CFSTR(" UserInfo=%p"), userInfo);
+    if (userInfo) {
+        CFStringAppendFormat(result, NULL, CFSTR(" UserInfo=%p"), userInfo);
+        underlyingError = (CFErrorRef)CFDictionaryGetValue(userInfo, kCFErrorUnderlyingErrorKey);
+    }
     CFStringAppendFormat(result, NULL, CFSTR(" \"%@\""), desc);
     if (debugDesc && CFStringGetLength(debugDesc) > 0) CFStringAppendFormat(result, NULL, CFSTR(" (%@)"), debugDesc);
+    if (underlyingError) {
+        CFStringRef underlyingErrorDesc = _CFErrorCreateDebugDescription(underlyingError);
+        CFStringAppendFormat(result, NULL, CFSTR(" Underlying Error=(%@)"), underlyingErrorDesc);
+        CFRelease(underlyingErrorDesc);
+    }
     if (debugDesc) CFRelease(debugDesc);
     if (desc) CFRelease(desc);
     return result;
@@ -422,7 +449,7 @@ static CFTypeRef _CFErrorPOSIXCallBack(CFErrorRef err, CFStringRef key) {
     return errStr;
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 /* Built-in callback for Mach domain.
 */
 static CFTypeRef _CFErrorMachCallBack(CFErrorRef err, CFStringRef key) {
@@ -432,6 +459,9 @@ static CFTypeRef _CFErrorMachCallBack(CFErrorRef err, CFStringRef key) {
     }
     return NULL;
 }
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 
@@ -450,8 +480,11 @@ static void _CFErrorInitializeCallBackTable(void) {
         // Note, even though the table looks like it was initialized, we go on to register the items on this thread as well, since otherwise we might consult the table before the items are actually registered.
     }
     CFErrorSetCallBackForDomain(kCFErrorDomainPOSIX, _CFErrorPOSIXCallBack);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED    
     CFErrorSetCallBackForDomain(kCFErrorDomainMach, _CFErrorMachCallBack);
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 }
 
index 4382294bad29ca39135663c52943861e76dfe1d2..ca4aa92c6ba6baceb8a1da7cfe17d620c7fc0e30 100644 (file)
--- a/CFError.h
+++ b/CFError.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFError.h
-       Copyright (c) 2006-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2006-2009, Apple Inc. All rights reserved.
 */
 
 /*!
index 2cfd3ea0665cc9f48dbe3cb9aa45f50105d8734f..2f8b75e71e41c45bfee476a52c821c99759d858e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFError_Private.h
-        Copyright (c) 2006-2007, Apple Inc. All rights reserved.
+        Copyright (c) 2006-2009, Apple Inc. All rights reserved.
        
        This is Apple-internal SPI for CFError.
 */
@@ -39,9 +39,10 @@ typedef CFTypeRef (*CFErrorUserInfoKeyCallBack)(CFErrorRef err, CFStringRef key)
 CF_EXPORT void CFErrorSetCallBackForDomain(CFStringRef domainName, CFErrorUserInfoKeyCallBack callBack) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
 CF_EXPORT CFErrorUserInfoKeyCallBack CFErrorGetCallBackForDomain(CFStringRef domainName) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
 
+
 /* A key for "true" debugging descriptions which should never be shown to the user. It's only used when the CFError is shown to the console, and nothing else is available. For instance the rather terse and techie OSStatus descriptions are in this boat.
 */
-CF_EXPORT const CFStringRef kCFErrorDebugDescription AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
+CF_EXPORT const CFStringRef kCFErrorDebugDescriptionKey AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
 
 
 CF_EXTERN_C_END
index cdeca523dc1330f306dc26528649699e30b639ad..ea8fce4b85ace6fed23c1e67d506a073f31e6fac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFFileUtilities.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #include "CFInternal.h"
-#include "CFPriv.h"
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <pwd.h>
+#include <CoreFoundation/CFPriv.h>
+#if DEPLOYMENT_TARGET_WINDOWS
+#include <io.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 #include <errno.h>
-#include <stdio.h>
 
-#define CF_OPENFLGS    (0)
+#define close _close
+#define write _write
+#define read _read
+#define open _NS_open
+#define stat _NS_stat
+#define fstat _fstat
+#define mkdir(a,b) _NS_mkdir(a)
+#define rmdir _NS_rmdir
+#define unlink _NS_unlink
+
+#define statinfo _stat
+
+#else
+    #include <string.h>
+    #include <unistd.h>
+    #include <dirent.h>
+    #include <sys/stat.h>
+    #include <sys/types.h>
+    #include <pwd.h>
+    #include <fcntl.h>
+    #include <errno.h>
+    #include <stdio.h>
+
+#define statinfo stat
+
+#endif
+
 
+CF_INLINE int openAutoFSNoWait() {
+#if DEPLOYMENT_TARGET_WINDOWS
+    return -1;
+#else
+    return (__CFProphylacticAutofsAccess ? open("/dev/autofs_nowait", 0) : -1);
+#endif
+}
+
+CF_INLINE void closeAutoFSNoWait(int fd) {
+#if DEPLOYMENT_TARGET_WINDOWS
+#else
+    if (-1 != fd) close(fd);
+#endif
+}
 
 __private_extern__ CFStringRef _CFCopyExtensionForAbstractType(CFStringRef abstractType) {
     return (abstractType ? (CFStringRef)CFRetain(abstractType) : NULL);
@@ -46,42 +82,37 @@ __private_extern__ CFStringRef _CFCopyExtensionForAbstractType(CFStringRef abstr
 
 
 __private_extern__ Boolean _CFCreateDirectory(const char *path) {
-#if 0 || 0
-    return CreateDirectoryA(path, (LPSECURITY_ATTRIBUTES)NULL);
-#else
-    int no_hang_fd = open("/dev/autofs_nowait", 0);
+    int no_hang_fd = openAutoFSNoWait();
     int ret = ((mkdir(path, 0777) == 0) ? true : false);
-    close(no_hang_fd);
+    closeAutoFSNoWait(no_hang_fd);
     return ret;
-#endif
 }
 
+#if DEPLOYMENT_TARGET_WINDOWS
+// todo: remove this function and make callers use _CFCreateDirectory
+__private_extern__ Boolean _CFCreateDirectoryWide(const wchar_t *path) {
+    return CreateDirectoryW(path, 0);
+}
+#endif
+
 __private_extern__ Boolean _CFRemoveDirectory(const char *path) {
-#if 0 || 0
-    return RemoveDirectoryA(path);
-#else
-    int no_hang_fd = open("/dev/autofs_nowait", 0);
+    int no_hang_fd = openAutoFSNoWait();
     int ret = ((rmdir(path) == 0) ? true : false);
-    close(no_hang_fd);
+    closeAutoFSNoWait(no_hang_fd);
     return ret;
-#endif
 }
 
 __private_extern__ Boolean _CFDeleteFile(const char *path) {
-#if 0 || 0
-    return DeleteFileA(path);
-#else
-    int no_hang_fd = open("/dev/autofs_nowait", 0);
+    int no_hang_fd = openAutoFSNoWait();
     int ret = unlink(path) == 0;
-    close(no_hang_fd);
+    closeAutoFSNoWait(no_hang_fd);
     return ret;
-#endif
 }
 
 __private_extern__ Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void **bytes, CFIndex *length, CFIndex maxLength) {
     // maxLength is the number of bytes desired, or 0 if the whole file is desired regardless of length.
-    struct stat statBuf;
     int fd = -1;
+    struct statinfo statBuf;
     char path[CFMaxPathSize];
     if (!CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize)) {
         return false;
@@ -90,26 +121,23 @@ __private_extern__ Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef u
     *bytes = NULL;
 
     
-#if 0 || 0
-    fd = open(path, O_RDONLY|CF_OPENFLGS, 0666|_S_IREAD);
-#else
-    int no_hang_fd = open("/dev/autofs_nowait", 0);
+    int no_hang_fd = openAutoFSNoWait();
     fd = open(path, O_RDONLY|CF_OPENFLGS, 0666);
-#endif
+
     if (fd < 0) {
-        close(no_hang_fd);
+        closeAutoFSNoWait(no_hang_fd);
         return false;
     }
     if (fstat(fd, &statBuf) < 0) {
         int saveerr = thread_errno();
         close(fd);
-        close(no_hang_fd);
+        closeAutoFSNoWait(no_hang_fd);
         thread_set_errno(saveerr);
         return false;
     }
     if ((statBuf.st_mode & S_IFMT) != S_IFREG) {
         close(fd);
-        close(no_hang_fd);
+        closeAutoFSNoWait(no_hang_fd);
         thread_set_errno(EACCES);
         return false;
     }
@@ -130,69 +158,52 @@ __private_extern__ Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef u
         if (read(fd, *bytes, desiredLength) < 0) {
             CFAllocatorDeallocate(alloc, *bytes);
             close(fd);
-           close(no_hang_fd);
+               closeAutoFSNoWait(no_hang_fd);
             return false;
         }
         *length = desiredLength;
     }
     close(fd);
-    close(no_hang_fd);
+    closeAutoFSNoWait(no_hang_fd);
     return true;
 }
 
 __private_extern__ Boolean _CFWriteBytesToFile(CFURLRef url, const void *bytes, CFIndex length) {
-    struct stat statBuf;
     int fd = -1;
     int mode;
+    struct statinfo statBuf;
     char path[CFMaxPathSize];
     if (!CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize)) {
         return false;
     }
 
-#if 0 || 0
+    int no_hang_fd = openAutoFSNoWait();
     mode = 0666;
     if (0 == stat(path, &statBuf)) {
         mode = statBuf.st_mode;
     } else if (thread_errno() != ENOENT) {
+        closeAutoFSNoWait(no_hang_fd);
         return false;
     }
-    fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|CF_OPENFLGS, 0666|_S_IWRITE);
+    fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|CF_OPENFLGS, 0666);
     if (fd < 0) {
+        closeAutoFSNoWait(no_hang_fd);
         return false;
     }
     if (length && write(fd, bytes, length) != length) {
         int saveerr = thread_errno();
         close(fd);
+        closeAutoFSNoWait(no_hang_fd);
         thread_set_errno(saveerr);
         return false;
     }
+#if DEPLOYMENT_TARGET_WINDOWS
     FlushFileBuffers((HANDLE)_get_osfhandle(fd));
-    close(fd);
 #else
-    int no_hang_fd = open("/dev/autofs_nowait", 0);
-    mode = 0666;
-    if (0 == stat(path, &statBuf)) {
-        mode = statBuf.st_mode;
-    } else if (thread_errno() != ENOENT) {
-       close(no_hang_fd);
-        return false;
-    }
-    fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|CF_OPENFLGS, 0666);
-    if (fd < 0) {
-       close(no_hang_fd);
-        return false;
-    }
-    if (length && write(fd, bytes, length) != length) {
-        int saveerr = thread_errno();
-        close(fd);
-       close(no_hang_fd);
-        thread_set_errno(saveerr);
-        return false;
-    }
     fsync(fd);
-    close(fd);
-    close(no_hang_fd);
 #endif
+    close(fd);
+    closeAutoFSNoWait(no_hang_fd);
     return true;
 }
 
@@ -207,15 +218,105 @@ __private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc
     // MF:!!! Need to use four-letter type codes where appropriate.
     CFStringRef extension = (matchingAbstractType ? _CFCopyExtensionForAbstractType(matchingAbstractType) : NULL);
     CFIndex extLen = (extension ? CFStringGetLength(extension) : 0);
+
+
+#if DEPLOYMENT_TARGET_WINDOWS
+    // This is a replacement for 'dirent' below, and also uses wchar_t to support unicode paths
+    wchar_t extBuff[CFMaxPathSize];
+    
+    if (extLen > 0) {
+        CFStringGetBytes(extension, CFRangeMake(0, extLen), kCFStringEncodingUTF16, 0, false, (uint8_t *)extBuff, CFMaxPathLength, &extLen);
+        extBuff[extLen] = '\0';
+    }
+    
+    wchar_t pathBuf[CFMaxPathSize];
+    
+    if (!dirPath) {
+        if (!_CFURLGetWideFileSystemRepresentation(dirURL, true, pathBuf, CFMaxPathLength)) {
+            if (extension) CFRelease(extension);
+            return NULL;
+        }
+        
+        pathLength = wcslen(pathBuf);
+
+    } else {
+        // Convert dirPath to a wide representation and put it into our pathBuf
+        // Get the real length of the string in UTF16 characters
+        CFStringRef dirPathStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, dirPath, kCFStringEncodingUTF8);
+        CFIndex strLen = CFStringGetLength(dirPathStr);
+        
+        // Copy the string into the buffer and terminate
+        CFStringGetCharacters(dirPathStr, CFRangeMake(0, strLen), (UniChar *)pathBuf);
+        pathBuf[strLen] = 0;
+        
+        CFRelease(dirPathStr);
+    }
+    
+    WIN32_FIND_DATAW  file;
+    HANDLE handle;
+    
+    if (pathLength + 2 >= CFMaxPathLength) {
+        if (extension) {
+            CFRelease(extension);
+        }
+        return NULL;
+    }
+
+    pathBuf[pathLength] = '\\';
+    pathBuf[pathLength + 1] = '*';
+    pathBuf[pathLength + 2] = '\0';
+    handle = FindFirstFileW(pathBuf, (LPWIN32_FIND_DATAW)&file);
+    if (INVALID_HANDLE_VALUE == handle) {
+        pathBuf[pathLength] = '\0';
+        if (extension) {
+            CFRelease(extension);
+        }
+        return NULL;
+    }
+
+    files = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
+
+    do {
+        CFURLRef fileURL;
+        CFIndex namelen = wcslen(file.cFileName);
+        if (file.cFileName[0] == '.' && (namelen == 1 || (namelen == 2  && file.cFileName[1] == '.'))) {
+            continue;
+        }
+
+        if (extLen > namelen) continue;    // if the extension is the same length or longer than the name, it can't possibly match.
+
+        if (extLen > 0) {
+            // Check to see if it matches the extension we're looking for.
+            if (_wcsicmp(&(file.cFileName[namelen - extLen]), (const wchar_t *)extBuff) != 0) {
+                continue;
+            }
+        }
+       if (dirURL == NULL) {
+           CFStringRef dirURLStr = CFStringCreateWithBytes(alloc, (const uint8_t *)pathBuf, pathLength, kCFStringEncodingUTF16, NO);
+           dirURL = CFURLCreateWithFileSystemPath(alloc, dirURLStr, kCFURLWindowsPathStyle, true);
+           CFRelease(dirURLStr);
+            releaseBase = true;
+        }
+        // MF:!!! What about the trailing slash?
+        CFStringRef fileURLStr = CFStringCreateWithBytes(alloc, (const uint8_t *)file.cFileName, namelen, kCFStringEncodingUTF16, NO);
+        fileURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, fileURLStr, kCFURLWindowsPathStyle, (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false, dirURL);
+        CFArrayAppendValue(files, fileURL);
+        CFRelease(fileURL);
+        CFRelease(fileURLStr);
+    } while (FindNextFileW(handle, &file));
+    FindClose(handle);
+    pathBuf[pathLength] = '\0';
+
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
     uint8_t extBuff[CFMaxPathSize];
     
     if (extLen > 0) {
         CFStringGetBytes(extension, CFRangeMake(0, extLen), CFStringFileSystemEncoding(), 0, false, extBuff, CFMaxPathLength, &extLen);
         extBuff[extLen] = '\0';
     }
-
+    
     uint8_t pathBuf[CFMaxPathSize];
-
+    
     if (!dirPath) {
         if (!CFURLGetFileSystemRepresentation(dirURL, true, pathBuf, CFMaxPathLength)) {
             if (extension) CFRelease(extension);
@@ -226,19 +327,18 @@ __private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc
         }
     }
     
-#if (DEPLOYMENT_TARGET_MACOSX) || defined(__svr4__) || defined(__hpux__) || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
     struct dirent buffer;
     struct dirent *dp;
     int err;
    
-    int no_hang_fd = open("/dev/autofs_nowait", 0);
+    int no_hang_fd = __CFProphylacticAutofsAccess ? open("/dev/autofs_nowait", 0) : -1;
  
     DIR *dirp = opendir(dirPath);
     if (!dirp) {
         if (extension) {
             CFRelease(extension);
         }
-       close(no_hang_fd);
+       if (-1 != no_hang_fd) close(no_hang_fd);
         return NULL;
         // raiseErrno("opendir", path);
     }
@@ -270,7 +370,7 @@ __private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc
             if (!isDir) {
                 // Ugh; must stat.
                 char subdirPath[CFMaxPathLength];
-                struct stat statBuf;
+                struct statinfo statBuf;
                 strlcpy(subdirPath, dirPath, sizeof(subdirPath));
                 strlcat(subdirPath, "/", sizeof(subdirPath));
                 strlcat(subdirPath, dp->d_name, sizeof(subdirPath));
@@ -286,7 +386,7 @@ __private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc
         CFRelease(fileURL);
     }
     err = closedir(dirp);
-    close(no_hang_fd);
+    if (-1 != no_hang_fd) close(no_hang_fd);
     if (err != 0) {
         CFRelease(files);
         if (releaseBase) {
@@ -300,7 +400,7 @@ __private_extern__ CFMutableArrayRef _CFContentsOfDirectory(CFAllocatorRef alloc
     
 #else
     
-#error _CFContentsOfDirectory() unknown architechture, not implemented
+#error _CFContentsOfDirectory() unknown architecture, not implemented
     
 #endif
 
@@ -317,19 +417,19 @@ __private_extern__ SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pa
     Boolean fileExists;
     Boolean isDirectory = false;
 
-    struct stat64 statBuf;
-    char path[CFMaxPathSize];
-
     if ((exists == NULL) && (posixMode == NULL) && (size == NULL) && (modTime == NULL) && (ownerID == NULL) && (dirContents == NULL)) {
         // Nothing to do.
         return 0;
     }
 
+    struct statinfo statBuf;
+    char path[CFMaxPathSize];
+
     if (!CFURLGetFileSystemRepresentation(pathURL, true, (uint8_t *)path, CFMaxPathLength)) {
         return -1;
     }
 
-    if (stat64(path, &statBuf) != 0) {
+    if (stat(path, &statBuf) != 0) {
         // stat failed, but why?
         if (thread_errno() == ENOENT) {
             fileExists = false;
@@ -368,9 +468,12 @@ __private_extern__ SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pa
 
     if (modTime != NULL) {
         if (fileExists) {
-            CFAbsoluteTime theTime = (CFAbsoluteTime)statBuf.st_mtimespec.tv_sec - kCFAbsoluteTimeIntervalSince1970;
-           theTime += (CFAbsoluteTime)statBuf.st_mtimespec.tv_nsec / 1000000000.0;
-            *modTime = CFDateCreate(alloc, theTime);
+#if DEPLOYMENT_TARGET_WINDOWS
+            struct timespec ts = {statBuf.st_mtime, 0};
+#else
+            struct timespec ts = statBuf.st_mtimespec;
+#endif
+            *modTime = CFDateCreate(alloc, _CFAbsoluteTimeFromFileTimeSpec(ts));
         } else {
             *modTime = NULL;
         }
@@ -389,7 +492,7 @@ __private_extern__ SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pa
     if (dirContents != NULL) {
         if (fileExists && isDirectory) {
 
-            CFMutableArrayRef contents = _CFContentsOfDirectory(alloc, path, NULL, pathURL, NULL);
+            CFMutableArrayRef contents = _CFContentsOfDirectory(alloc, (char *)path, NULL, pathURL, NULL);
 
             if (contents) {
                 *dirContents = contents;
@@ -405,9 +508,9 @@ __private_extern__ SInt32 _CFGetFileProperties(CFAllocatorRef alloc, CFURLRef pa
 
 
 // MF:!!! Should pull in the rest of the UniChar based path utils from Foundation.
-#if (DEPLOYMENT_TARGET_MACOSX) || defined(__svr4__) || defined(__hpux__) || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
     #define UNIX_PATH_SEMANTICS
-#elif defined(__WIN32__)
+#elif DEPLOYMENT_TARGET_WINDOWS
     #define WINDOWS_PATH_SEMANTICS
 #else
 #error Unknown platform
diff --git a/CFICUConverters.c b/CFICUConverters.c
new file mode 100644 (file)
index 0000000..2698c3b
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*
+ *  CFICUConverters.c
+ *  CoreFoundation
+ *
+ *  Created by Aki Inoue on 07/12/04.
+ *  Copyright 2007-2009, Apple Inc. All rights reserved.
+ *
+ */
+
+#include "CFStringEncodingDatabase.h"
+#include "CFStringEncodingConverterPriv.h"
+#include "CFICUConverters.h"
+#include <CoreFoundation/CFStringEncodingExt.h>
+#include <unicode/ucnv.h>
+#include <unicode/uversion.h>
+#include "CFInternal.h"
+#include <stdio.h>
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#define strncasecmp_l(a, b, c, d) _strnicmp(a, b, c)
+#define snprintf _snprintf
+#endif
+
+// Thread data support
+typedef struct {
+    uint8_t _numSlots;
+    uint8_t _nextSlot;
+    UConverter **_converters;
+} __CFICUThreadData;
+
+static void __CFICUThreadDataDestructor(void *context) {
+    __CFICUThreadData * data = (__CFICUThreadData *)context;
+    
+    if (NULL != data->_converters) { // scan to make sure deallocation
+        UConverter **converter = data->_converters;
+        UConverter **limit = converter + data->_numSlots;
+        
+        while (converter < limit) {
+            if (NULL != converter) ucnv_close(*converter);
+            ++converter;
+        }
+        CFAllocatorDeallocate(NULL, data->_converters);
+    }
+    
+    CFAllocatorDeallocate(NULL, data);
+}
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#import <pthread.h>
+
+CF_INLINE __CFICUThreadData *__CFStringEncodingICUGetThreadData() {
+    __CFICUThreadData * data;
+
+    pthread_key_init_np(__CFTSDKeyICUConverter, __CFICUThreadDataDestructor);
+    data = (__CFICUThreadData *)pthread_getspecific(__CFTSDKeyICUConverter);
+
+    if (NULL == data) {
+        data = (__CFICUThreadData *)CFAllocatorAllocate(NULL, sizeof(__CFICUThreadData), 0);
+        memset(data, 0, sizeof(__CFICUThreadData));
+        pthread_setspecific(__CFTSDKeyICUConverter, (const void *)data);
+    }
+
+    return data;
+}
+#elif DEPLOYMENT_TARGET_WINDOWS
+__private_extern__ void __CFStringEncodingICUThreadDataCleaner(void *context) { __CFICUThreadDataDestructor(context); }
+
+CF_INLINE __CFICUThreadData *__CFStringEncodingICUGetThreadData() {
+    __CFThreadSpecificData *threadData = __CFGetThreadSpecificData_inline();
+
+    if (NULL == threadData->_icuThreadData) {
+        threadData->_icuThreadData = (__CFICUThreadData *)CFAllocatorAllocate(NULL, sizeof(__CFICUThreadData), 0);
+        memset(threadData->_icuThreadData, 0, sizeof(__CFICUThreadData));
+    }
+
+    return (__CFICUThreadData *)threadData->_icuThreadData;
+}
+#else
+#error Need implementation for thread data
+#endif
+
+__private_extern__ const char *__CFStringEncodingGetICUName(CFStringEncoding encoding) {
+#define STACK_BUFFER_SIZE (60)
+    char buffer[STACK_BUFFER_SIZE];
+    const char *result = NULL;
+    UErrorCode errorCode = U_ZERO_ERROR;
+    uint32_t codepage = 0;
+
+    if (kCFStringEncodingUTF7_IMAP == encoding) return "IMAP-mailbox-name";
+
+    if (kCFStringEncodingUnicode != (encoding & 0x0F00)) codepage = __CFStringEncodingGetWindowsCodePage(encoding); // we don't use codepage for UTF to avoid little endian weirdness of Windows
+
+    if ((0 != codepage) && (snprintf(buffer, STACK_BUFFER_SIZE, "windows-%d", codepage) < STACK_BUFFER_SIZE) && (NULL != (result = ucnv_getAlias(buffer, 0, &errorCode)))) return result;
+
+    if (__CFStringEncodingGetCanonicalName(encoding, buffer, STACK_BUFFER_SIZE)) result = ucnv_getAlias(buffer, 0, &errorCode);
+
+    return result;
+#undef STACK_BUFFER_SIZE
+}
+
+__private_extern__ CFStringEncoding __CFStringEncodingGetFromICUName(const char *icuName) {
+    uint32_t codepage;
+    UErrorCode errorCode = U_ZERO_ERROR;
+
+    if ((0 == strncasecmp_l(icuName, "windows-", strlen("windows-"), NULL)) && (0 != (codepage = strtol(icuName + strlen("windows-"), NULL, 10)))) return __CFStringEncodingGetFromWindowsCodePage(codepage);
+
+    if (0 != ucnv_countAliases(icuName, &errorCode)) {
+        CFStringEncoding encoding;
+        const char *name;
+
+        // Try WINDOWS platform
+        name = ucnv_getStandardName(icuName, "WINDOWS", &errorCode);
+        
+        if (NULL != name) {
+            if ((0 == strncasecmp_l(name, "windows-", strlen("windows-"), NULL)) && (0 != (codepage = strtol(name + strlen("windows-"), NULL, 10)))) return __CFStringEncodingGetFromWindowsCodePage(codepage);
+            
+            if (strncasecmp_l(icuName, name, strlen(name), NULL) && (kCFStringEncodingInvalidId != (encoding = __CFStringEncodingGetFromCanonicalName(name)))) return encoding;
+        }
+
+        // Try JAVA platform
+        name = ucnv_getStandardName(icuName, "JAVA", &errorCode);
+        if ((NULL != name) && strncasecmp_l(icuName, name, strlen(name), NULL) && (kCFStringEncodingInvalidId != (encoding = __CFStringEncodingGetFromCanonicalName(name)))) return encoding;
+
+        // Try MIME platform
+        name = ucnv_getStandardName(icuName, "MIME", &errorCode);
+        if ((NULL != name) && strncasecmp_l(icuName, name, strlen(name), NULL) && (kCFStringEncodingInvalidId != (encoding = __CFStringEncodingGetFromCanonicalName(name)))) return encoding;
+    }
+
+    return kCFStringEncodingInvalidId;
+}
+
+CF_INLINE UConverter *__CFStringEncodingConverterCreateICUConverter(const char *icuName, uint32_t flags, bool toUnicode) {
+    UConverter *converter;
+    UErrorCode errorCode = U_ZERO_ERROR;
+    uint8_t streamID = CFStringEncodingStreamIDFromMask(flags);
+
+    if (0 != streamID) { // this is a part of streaming previously created
+        __CFICUThreadData *data = __CFStringEncodingICUGetThreadData();
+
+        --streamID; // map to array index
+
+        if ((streamID < data->_numSlots) && (NULL != data->_converters[streamID])) return data->_converters[streamID];
+    }
+
+    converter = ucnv_open(icuName, &errorCode);
+
+    if (NULL != converter) {
+        char lossyByte = CFStringEncodingMaskToLossyByte(flags);
+
+        if ((0 == lossyByte) && (0 != (flags & kCFStringEncodingAllowLossyConversion))) lossyByte = '?';
+
+        if (0 ==lossyByte) {
+            if (toUnicode) {
+                ucnv_setToUCallBack(converter, &UCNV_TO_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+            } else {
+                ucnv_setFromUCallBack(converter, &UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, &errorCode);
+            }
+        } else {
+            ucnv_setSubstChars(converter, &lossyByte, 1, &errorCode);
+        }
+    }
+
+    return converter;
+}
+
+#define ICU_CONVERTER_SLOT_INCREMENT (10)
+#define ICU_CONVERTER_MAX_SLOT (255)
+
+static CFIndex __CFStringEncodingConverterReleaseICUConverter(UConverter *converter, uint32_t flags, CFIndex status) {
+    uint8_t streamID = CFStringEncodingStreamIDFromMask(flags);
+
+    if ((kCFStringEncodingInvalidInputStream != status) && ((0 != (flags & kCFStringEncodingPartialInput)) || ((kCFStringEncodingInsufficientOutputBufferLength == status) && (0 != (flags & kCFStringEncodingPartialOutput))))) {
+        if (0 == streamID) {
+            __CFICUThreadData *data = __CFStringEncodingICUGetThreadData();
+
+            if (NULL == data->_converters) {
+                data->_converters = (UConverter **)CFAllocatorAllocate(NULL, sizeof(UConverter *) * ICU_CONVERTER_SLOT_INCREMENT, 0);
+                memset(data->_converters, 0, sizeof(UConverter *) * ICU_CONVERTER_SLOT_INCREMENT);
+                data->_numSlots = ICU_CONVERTER_SLOT_INCREMENT;
+                data->_nextSlot = 0;
+            } else if ((data->_nextSlot >= data->_numSlots) || (NULL != data->_converters[data->_nextSlot])) { // Need to find one
+                CFIndex index;
+
+                for (index = 0;index < data->_numSlots;index++) {
+                    if (NULL == data->_converters[index]) {
+                        data->_nextSlot = index;
+                        break;
+                    }
+                }
+
+                if (index >= data->_numSlots) { // we're full
+                    UConverter **newConverters;
+                    CFIndex newSize = data->_numSlots + ICU_CONVERTER_SLOT_INCREMENT;
+
+                    if (newSize > ICU_CONVERTER_MAX_SLOT) { // something is terribly wrong
+                        CFLog(kCFLogLevelError, CFSTR("Per-thread streaming ID for ICU converters exhausted. Ignoring..."));
+                        ucnv_close(converter);
+                        return 0;
+                    }
+
+                    newConverters = (UConverter **)CFAllocatorAllocate(NULL, sizeof(UConverter *) * newSize, 0);
+                    memset(newConverters, 0, sizeof(UConverter *) * newSize);
+                    memcpy(newConverters, data->_converters, sizeof(UConverter *) * data->_numSlots);
+                    CFAllocatorDeallocate(NULL, data->_converters);
+                    data->_converters = newConverters;
+                    data->_nextSlot = data->_numSlots;
+                    data->_numSlots = newSize;
+                }
+            }
+
+            data->_converters[data->_nextSlot] = converter;
+            streamID = data->_nextSlot + 1;
+
+            // now find next slot
+            ++data->_nextSlot;
+
+            if ((data->_nextSlot >= data->_numSlots) || (NULL != data->_converters[data->_nextSlot])) {
+                data->_nextSlot = 0;
+
+                while ((data->_nextSlot < data->_numSlots) && (NULL != data->_converters[data->_nextSlot])) ++data->_nextSlot;
+            }
+        }
+
+        return CFStringEncodingStreamIDToMask(streamID);
+    }
+
+    if (0 != streamID) {
+        __CFICUThreadData *data = __CFStringEncodingICUGetThreadData();
+
+        --streamID; // map to array index
+
+        if ((streamID < data->_numSlots) && (converter == data->_converters[streamID])) {
+            data->_converters[streamID] = NULL;
+            if (data->_nextSlot > streamID) data->_nextSlot = streamID;
+        }
+    }
+
+    ucnv_close(converter);
+
+    return 0;
+}
+
+#define MAX_BUFFER_SIZE (1000)
+
+#if (U_ICU_VERSION_MAJOR_NUM > 4) || ((U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM > 0))
+#warning Unknown ICU version. Check binary compatibility issues for rdar://problem/6024743
+#endif
+#define HAS_ICU_BUG_6024743 (1)
+#define HAS_ICU_BUG_6025527 (1)
+
+__private_extern__ CFIndex __CFStringEncodingICUToBytes(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen) {
+    UConverter *converter;
+    UErrorCode errorCode = U_ZERO_ERROR;
+    const UTF16Char *source = characters;
+    const UTF16Char *sourceLimit = source + numChars;
+    char *destination = (char *)bytes;
+    const char *destinationLimit = destination + maxByteLen;
+    bool flush = ((0 == (flags & kCFStringEncodingPartialInput)) ? true : false);
+    CFIndex status;
+
+    if (NULL == (converter = __CFStringEncodingConverterCreateICUConverter(icuName, flags, false))) return kCFStringEncodingConverterUnavailable;
+
+    if (0 == maxByteLen) {
+        char buffer[MAX_BUFFER_SIZE];
+        CFIndex totalLength = 0;
+
+        while ((source < sourceLimit) && (U_ZERO_ERROR == errorCode)) {
+            destination = buffer;
+            destinationLimit = destination + MAX_BUFFER_SIZE;
+
+            ucnv_fromUnicode(converter, &destination, destinationLimit, (const UChar **)&source, (const UChar *)sourceLimit, NULL, flush, &errorCode);
+
+            totalLength += (destination - buffer);
+
+            if (U_BUFFER_OVERFLOW_ERROR == errorCode) errorCode = U_ZERO_ERROR;
+        }
+
+        if (NULL != usedByteLen) *usedByteLen = totalLength;
+    } else {
+        ucnv_fromUnicode(converter, &destination, destinationLimit, (const UChar **)&source, (const UChar *)sourceLimit, NULL, flush, &errorCode);
+        
+        if (NULL != usedByteLen) *usedByteLen = destination - (const char *)bytes;
+    }
+
+    status = ((U_ZERO_ERROR == errorCode) ? kCFStringEncodingConversionSuccess : ((U_BUFFER_OVERFLOW_ERROR == errorCode) ? kCFStringEncodingInsufficientOutputBufferLength : kCFStringEncodingInvalidInputStream));
+
+    if (NULL != usedCharLen) {
+#if HAS_ICU_BUG_6024743
+/* ICU has a serious behavioral inconsistency issue that the source pointer returned from ucnv_fromUnicode() is after illegal input. We have to keep track of any changes in this area in order to prevent future binary compatiibility issues */
+       if (kCFStringEncodingInvalidInputStream == status) {
+#define MAX_ERROR_BUFFER_LEN (32)
+           UTF16Char errorBuffer[MAX_ERROR_BUFFER_LEN];
+           int8_t errorLength = MAX_ERROR_BUFFER_LEN;
+#undef MAX_ERROR_BUFFER_LEN
+
+           errorCode = U_ZERO_ERROR;
+
+           ucnv_getInvalidUChars(converter, (UChar *)errorBuffer, &errorLength, &errorCode);
+
+           if (U_ZERO_ERROR == errorCode) {
+               source -= errorLength;
+           } else {
+               // Gah, something is terribly wrong. Reset everything
+               source = characters; // 0 length
+               if (NULL != usedByteLen) *usedByteLen = 0;
+           }
+       }
+#endif
+       *usedCharLen = source - characters;
+    }
+
+    status |= __CFStringEncodingConverterReleaseICUConverter(converter, flags, status);
+
+    return status;
+}
+
+__private_extern__ CFIndex __CFStringEncodingICUToUnicode(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) {
+    UConverter *converter;
+    UErrorCode errorCode = U_ZERO_ERROR;
+    const char *source = (const char *)bytes;
+    const char *sourceLimit = source + numBytes;
+    UTF16Char *destination = characters;
+    const UTF16Char *destinationLimit = destination + maxCharLen;
+    bool flush = ((0 == (flags & kCFStringEncodingPartialInput)) ? true : false);
+    CFIndex status;
+
+    if (NULL == (converter = __CFStringEncodingConverterCreateICUConverter(icuName, flags, true))) return kCFStringEncodingConverterUnavailable;
+
+    if (0 == maxCharLen) {
+        UTF16Char buffer[MAX_BUFFER_SIZE];
+        CFIndex totalLength = 0;
+        
+        while ((source < sourceLimit) && (U_ZERO_ERROR == errorCode)) {
+            destination = buffer;
+            destinationLimit = destination + MAX_BUFFER_SIZE;
+            
+            ucnv_toUnicode(converter, (UChar **)&destination, (const UChar *)destinationLimit, &source, sourceLimit, NULL, flush, &errorCode);
+            
+            totalLength += (destination - buffer);
+            
+            if (U_BUFFER_OVERFLOW_ERROR == errorCode) errorCode = U_ZERO_ERROR;
+        }
+        
+        if (NULL != usedCharLen) *usedCharLen = totalLength;
+    } else {
+        ucnv_toUnicode(converter, (UChar **)&destination, (const UChar *)destinationLimit, &source, sourceLimit, NULL, flush, &errorCode);
+
+        if (NULL != usedCharLen) *usedCharLen = destination - characters;
+    }
+
+    status = ((U_ZERO_ERROR == errorCode) ? kCFStringEncodingConversionSuccess : ((U_BUFFER_OVERFLOW_ERROR == errorCode) ? kCFStringEncodingInsufficientOutputBufferLength : kCFStringEncodingInvalidInputStream));
+
+    if (NULL != usedByteLen) {
+#if HAS_ICU_BUG_6024743
+       /* ICU has a serious behavioral inconsistency issue that the source pointer returned from ucnv_toUnicode() is after illegal input. We have to keep track of any changes in this area in order to prevent future binary compatiibility issues */
+       if (kCFStringEncodingInvalidInputStream == status) {
+#define MAX_ERROR_BUFFER_LEN (32)
+           char errorBuffer[MAX_ERROR_BUFFER_LEN];
+           int8_t errorLength = MAX_ERROR_BUFFER_LEN;
+#undef MAX_ERROR_BUFFER_LEN
+
+           errorCode = U_ZERO_ERROR;
+           
+           ucnv_getInvalidChars(converter, errorBuffer, &errorLength, &errorCode);
+           
+           if (U_ZERO_ERROR == errorCode) {
+#if HAS_ICU_BUG_6025527
+                // Another ICU oddness here. ucnv_getInvalidUChars() writes the '\0' terminator, and errorLength includes the extra byte.
+                if ((errorLength > 0) && ('\0' == errorBuffer[errorLength - 1])) --errorLength;
+#endif
+               source -= errorLength;
+           } else {
+               // Gah, something is terribly wrong. Reset everything
+               source = (const char *)bytes; // 0 length
+               if (NULL != usedCharLen) *usedCharLen = 0;
+           }
+       }
+#endif
+
+       *usedByteLen = source - (const char *)bytes;
+    }
+    
+    status |= __CFStringEncodingConverterReleaseICUConverter(converter, flags, status);
+
+    return status;
+}
+
+__private_extern__ CFIndex __CFStringEncodingICUCharLength(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) {
+    CFIndex usedCharLen;
+    return (__CFStringEncodingICUToUnicode(icuName, flags, bytes, numBytes, NULL, NULL, 0, &usedCharLen) == kCFStringEncodingConversionSuccess ? usedCharLen : 0);
+}
+
+__private_extern__ CFIndex __CFStringEncodingICUByteLength(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars) {
+    CFIndex usedByteLen;
+    return (__CFStringEncodingICUToBytes(icuName, flags, characters, numChars, NULL, NULL, 0, &usedByteLen) == kCFStringEncodingConversionSuccess ? usedByteLen : 0);
+}
+
+__private_extern__ CFStringEncoding *__CFStringEncodingCreateICUEncodings(CFAllocatorRef allocator, CFIndex *numberOfIndex) {
+    CFIndex count = ucnv_countAvailable();
+    CFIndex numEncodings = 0;
+    CFStringEncoding *encodings;
+    CFStringEncoding encoding;
+    CFIndex index;
+
+    if (0 == count) return NULL;
+
+    encodings = (CFStringEncoding *)CFAllocatorAllocate(NULL, sizeof(CFStringEncoding) * count, 0);
+
+    for (index = 0;index < count;index++) {
+        encoding = __CFStringEncodingGetFromICUName(ucnv_getAvailableName(index));
+
+        if (kCFStringEncodingInvalidId != encoding) encodings[numEncodings++] = encoding;
+    }
+
+    if (0 == numEncodings) {
+        CFAllocatorDeallocate(allocator, encodings);
+        encodings = NULL;
+    }
+
+    *numberOfIndex = numEncodings;
+
+    return encodings;
+}
diff --git a/CFICUConverters.h b/CFICUConverters.h
new file mode 100644 (file)
index 0000000..2798c6c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*
+ *  CFICUConverters.h
+ *  CoreFoundation
+ *
+ *  Created by Aki Inoue on 07/12/04.
+ *  Copyright (c) 2007-2009, Apple Inc. All rights reserved.
+ *
+ */
+
+#include <CoreFoundation/CFString.h>
+
+__private_extern__ const char *__CFStringEncodingGetICUName(CFStringEncoding encoding);
+
+__private_extern__ CFStringEncoding __CFStringEncodingGetFromICUName(const char *icuName);
+
+
+__private_extern__ CFIndex __CFStringEncodingICUToBytes(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen);
+__private_extern__ CFIndex __CFStringEncodingICUToUnicode(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen);
+__private_extern__ CFIndex __CFStringEncodingICUCharLength(const char *icuName, uint32_t flags, const uint8_t *bytes, CFIndex numBytes);
+__private_extern__ CFIndex __CFStringEncodingICUByteLength(const char *icuName, uint32_t flags, const UniChar *characters, CFIndex numChars);
+
+// The caller is responsible for freeing the memory (use CFAllocatorDeallocate)
+__private_extern__ CFStringEncoding *__CFStringEncodingCreateICUEncodings(CFAllocatorRef allocator, CFIndex *numberOfIndex);
+
+#if DEPLOYMENT_TARGET_WINDOWS
+__private_extern__ void __CFStringEncodingICUThreadDataCleaner(void *context);
+#endif
+
index cc4bd803379ea9fa9ee543caeaa144c7b476e5bd..12505f1cc3fb50ee085a7d5b87150d6f949b3eb0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFInternal.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 /*
@@ -35,6 +35,8 @@
 #if !defined(__COREFOUNDATION_CFINTERNAL__)
 #define __COREFOUNDATION_CFINTERNAL__ 1
 
+CF_EXTERN_C_BEGIN
+
 #include <CoreFoundation/CFBase.h>
 #include <CoreFoundation/CFURL.h>
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFArray.h>
 #include <CoreFoundation/CFRunLoop.h>
 #include <CoreFoundation/CFStorage.h>
-#include "CFLogUtilities.h"
-#include "CFRuntime.h"
-#if DEPLOYMENT_TARGET_MACOSX
+#include <CoreFoundation/CFLogUtilities.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <limits.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <xlocale.h>
+#include <libkern/OSAtomic.h>
 #include <mach/mach_time.h>
+#include <mach/mach.h>
+#include <unistd.h>
 #endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 #include <sys/time.h>
 #include <pthread.h>
+#include <signal.h>
 #endif
-#include <limits.h>
-#include "auto_stubs.h"
-#if !defined (__WIN32__)
+#if DEPLOYMENT_TARGET_WINDOWS
 #include <pthread.h>
-#endif //__WIN32__
-#ifndef __WIN32__
-#include <libkern/OSAtomic.h>
-#endif //__WIN32__
+#endif
+
 
 #if defined(__BIG_ENDIAN__)
 #define __CF_BIG_ENDIAN__ 1
@@ -72,7 +75,7 @@
 #endif
 
 
-#include "ForFoundationOnly.h"
+#include <CoreFoundation/ForFoundationOnly.h>
 
 CF_EXPORT const char *_CFProcessName(void);
 CF_EXPORT CFStringRef _CFProcessNameString(void);
@@ -89,17 +92,20 @@ CF_EXPORT CFStringRef _CFStringCreateHostName(void);
 
 CF_EXPORT void _CFMachPortInstallNotifyPort(CFRunLoopRef rl, CFStringRef mode);
 
-#if defined(__ppc__) || defined(__ppc64__)
-    #define HALT asm __volatile__("trap")
+#if defined(__ppc__)
+    #define HALT do {asm __volatile__("trap"); kill(getpid(), 9); } while (0)
 #elif defined(__i386__) || defined(__x86_64__)
     #if defined(__GNUC__)
-        #define HALT asm __volatile__("int3")
+        #define HALT do {asm __volatile__("int3"); kill(getpid(), 9); } while (0)
     #elif defined(_MSC_VER)
-        #define HALT __asm int 3;
+        #define HALT do { DebugBreak(); abort(); } while (0)
     #else
         #error Compiler not supported
     #endif
 #endif
+#if defined(__arm__)
+    #define HALT do {asm __volatile__("bkpt 0xCF"); kill(getpid(), 9); } while (0)
+#endif
 
 #if defined(DEBUG)
     #define __CFAssert(cond, prio, desc, a1, a2, a3, a4, a5)   \
@@ -150,35 +156,62 @@ extern void __CFGenericValidateType_(CFTypeRef cf, CFTypeID type, const char *fu
 #define __CFBitSet(V, N)  ((V) |= (1UL << (N)))
 #define __CFBitClear(V, N)  ((V) &= ~(1UL << (N)))
 
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+// The fixed range 50 - 59 of pthread_specific keys is reserved
+// for CoreFoundation; see <System/pthread_machdep.h>.
+// 60 - 69 are reserved for Foundation; Foundation uses 64 - 69
+// and reserves 60-63 for CoreFoundation.
+// Foundation knows about the value of __CFTSDKeyAutoreleaseData1
+enum {
+       __CFTSDKeyUnused50 = 50,
+       __CFTSDKeyAllocator = 51,
+       __CFTSDKeyExceptionData = 52,
+       __CFTSDKeyRunLoopCntr = 53,
+       __CFTSDKeyRunLoop = 54,
+       __CFTSDKeyICUConverter = 55,
+       __CFTSDKeyCollatorLocale = 56,
+       __CFTSDKeyCollatorUCollator = 57,
+       __CFTSDKeyIsInNSCache = 58,
+       __CFTSDKeyIsInCFLog = 59,
+       __CFTSDKeyIsInGCDMainQ = 60,
+       __CFTSDKeyUnused61 = 61,
+       __CFTSDKeyAutoreleaseData1 = 62,
+       __CFTSDKeyAutoreleaseData2 = 63,  // autorelease pool stuff must be higher than run loop constants
+};
+
+extern int pthread_key_init_np(int, void (*)(void *));
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
 typedef struct ___CFThreadSpecificData {
     void *_unused1;
     void *_allocator;
+    void *_runLoop;
+    int _runLoop_pid;
+    HHOOK _messageHook;
+    void *_icuThreadData;
+
 // If you add things to this struct, add cleanup to __CFFinalizeThreadData()
 } __CFThreadSpecificData;
 
 extern __CFThreadSpecificData *__CFGetThreadSpecificData(void);
 __private_extern__ void __CFFinalizeThreadData(void *arg);
+extern DWORD __CFTSDKey;
 
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-extern pthread_key_t __CFTSDKey;
-#endif
-
-//extern void *pthread_getspecific(pthread_key_t key);
+// implemented in windowsSyncHelper.c
+__private_extern__ __CFThreadSpecificData *__CFGetThreadSpecificData_inline(void);
 
-CF_INLINE __CFThreadSpecificData *__CFGetThreadSpecificData_inline(void) {
-#if DEPLOYMENT_TARGET_MACOSX|| DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-    __CFThreadSpecificData *data = pthread_getspecific(__CFTSDKey);
-    return data ? data : __CFGetThreadSpecificData();
-#elif defined(__WIN32__)
-    __CFThreadSpecificData *data = (__CFThreadSpecificData *)TlsGetValue(__CFTSDKey);
-    return data ? data : __CFGetThreadSpecificData();
 #endif
-}
 
 #define __kCFAllocatorTypeID_CONST     2
 
 CF_INLINE CFAllocatorRef __CFGetDefaultAllocator(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    CFAllocatorRef allocator = pthread_getspecific(__CFTSDKeyAllocator);
+#else
     CFAllocatorRef allocator = (CFAllocatorRef)__CFGetThreadSpecificData_inline()->_allocator;
+#endif
     if (NULL == allocator) {
        allocator = kCFAllocatorSystemDefault;
     }
@@ -239,6 +272,19 @@ CF_INLINE auto_memory_type_t CF_GET_GC_MEMORY_TYPE(CFOptionFlags flags) {
     return type;
 }
 
+CF_INLINE void __CFAssignWithWriteBarrier(void **location, void *value) {
+    if (kCFUseCollectableAllocator) {
+        objc_assign_strongCast((id)value, (id *)location);
+    } else {
+        *location = value;
+    }
+}
+
+// Zero-retain count CFAllocator functions, i.e. memory that will be collected, no dealloc necessary
+CF_EXPORT void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint);
+CF_EXPORT void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint);
+CF_EXPORT void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr);
+
 CF_EXPORT CFAllocatorRef _CFTemporaryMemoryAllocator(void);
 
 extern SInt64 __CFTimeIntervalToTSR(CFTimeInterval ti);
@@ -252,11 +298,20 @@ extern Boolean __CFStringScanInteger(CFStringInlineBuffer *buf, CFTypeRef locale
 extern Boolean __CFStringScanDouble(CFStringInlineBuffer *buf, CFTypeRef locale, SInt32 *indexPtr, double *resultPtr); 
 extern Boolean __CFStringScanHex(CFStringInlineBuffer *buf, SInt32 *indexPtr, unsigned *result);
 
+extern const char *__CFgetenv(const char *n);
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#define STACK_BUFFER_DECL(T, N, C) T N[C]
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define STACK_BUFFER_DECL(T, N, C) T *N = (T *)_alloca((C) * sizeof(T))
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 
-#define STACK_BUFFER_DECL(T, N, C) T N[C];
 
 #ifdef __CONSTANT_CFSTRINGS__
 #define CONST_STRING_DECL(S, V) const CFStringRef S = (const CFStringRef)__builtin___CFStringMakeConstantString(V);
+#define PE_CONST_STRING_DECL(S, V) __private_extern__ const CFStringRef S = (const CFStringRef)__builtin___CFStringMakeConstantString(V);
 #else
 
 struct CF_CONST_STRING {
@@ -265,48 +320,37 @@ struct CF_CONST_STRING {
     uint32_t _length;
 };
 
-extern int __CFConstantStringClassReference[];
+CF_EXPORT int __CFConstantStringClassReference[];
 
 /* CFNetwork also has a copy of the CONST_STRING_DECL macro (for use on platforms without constant string support in cc); please warn cfnetwork-core@group.apple.com of any necessary changes to this macro. -- REW, 1/28/2002 */
-#if 0
-#define ___WindowsConstantStringClassReference &__CFConstantStringClassReference
-#else
-#define ___WindowsConstantStringClassReference NULL
-#endif
 
-#if __CF_BIG_ENDIAN__
+#if __CF_BIG_ENDIAN__ && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
 #define CONST_STRING_DECL(S, V)                        \
 static struct CF_CONST_STRING __ ## S ## __ = {{&__CFConstantStringClassReference, {0x0000, 0x07c8}}, V, sizeof(V) - 1}; \
 const CFStringRef S = (CFStringRef) & __ ## S ## __;
-#elif !defined (__WIN32__)
+#define PE_CONST_STRING_DECL(S, V)                     \
+static struct CF_CONST_STRING __ ## S ## __ = {{&__CFConstantStringClassReference, {0x0000, 0x07c8}}, V, sizeof(V) - 1}; \
+__private_extern__ const CFStringRef S = (CFStringRef) & __ ## S ## __;
+#elif __CF_LITTLE_ENDIAN__ && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
 #define CONST_STRING_DECL(S, V)                        \
 static struct CF_CONST_STRING __ ## S ## __ = {{&__CFConstantStringClassReference, {0x07c8, 0x0000}}, V, sizeof(V) - 1}; \
 const CFStringRef S = (CFStringRef) & __ ## S ## __;
-#elif 0
-#define CONST_STRING_DECL(S, V)                        \
-static struct CF_CONST_STRING __ ## S ## __ = {{___WindowsConstantStringClassReference, {0xc8, 0x07, 0x00, 0x00}},(uint8_t *) V, sizeof(V) - 1}; \
-const CFStringRef S = (CFStringRef) & __ ## S ## __;
-
-#define CONST_STRING_DECL_EXPORT(S, V)                 \
-struct CF_CONST_STRING __ ## S ## __ = {{___WindowsConstantStringClassReference, {0xc8, 0x07, 0x00, 0x00}}, (uint8_t *)V, sizeof(V) - 1}; \
-CF_EXPORT const CFStringRef S = (CFStringRef) & __ ## S ## __;
-
-#else
+#define PE_CONST_STRING_DECL(S, V)                     \
+static struct CF_CONST_STRING __ ## S ## __ = {{&__CFConstantStringClassReference, {0x07c8, 0x0000}}, V, sizeof(V) - 1}; \
+__private_extern__ const CFStringRef S = (CFStringRef) & __ ## S ## __;
+#elif DEPLOYMENT_TARGET_WINDOWS
 #define CONST_STRING_DECL(S, V)                        \
-static struct CF_CONST_STRING __ ## S ## __ = {{NULL, {0xc8, 0x07, 0x00, 0x00}},(uint8_t *) V, sizeof(V) - 1}; \
+static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringClassReference, {0xc8, 0x07, 0x00, 0x00}}, (uint8_t *)(V), sizeof(V) - 1}; \
 const CFStringRef S = (CFStringRef) & __ ## S ## __;
-
-#define CONST_STRING_DECL_EXPORT(S, V)                 \
-struct CF_CONST_STRING __ ## S ## __ = {{NULL, {0xc8, 0x07, 0x00, 0x00}}, (uint8_t *)V, sizeof(V) - 1}; \
-CF_EXPORT const CFStringRef S = (CFStringRef) & __ ## S ## __;
-
-#endif // __WIN32__
+#define PE_CONST_STRING_DECL(S, V)                     \
+static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringClassReference, {0xc8, 0x07, 0x00, 0x00}}, (uint8_t *)(V), sizeof(V) - 1}; \
+__private_extern__ const CFStringRef S = (CFStringRef) & __ ## S ## __;
+#endif
 #endif // __BIG_ENDIAN__
 
-#undef ___WindowsConstantStringClassReference
 
 /* Buffer size for file pathname */
-#if 0 || 0
+#if DEPLOYMENT_TARGET_WINDOWS
     #define CFMaxPathSize ((CFIndex)262)
     #define CFMaxPathLength ((CFIndex)260)
 #else
@@ -314,10 +358,15 @@ CF_EXPORT const CFStringRef S = (CFStringRef) & __ ## S ## __;
     #define CFMaxPathLength ((CFIndex)1024)
 #endif
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+extern bool __CFOASafe;
+extern void __CFSetLastAllocationEventName(void *ptr, const char *classname);
+#else
 #define __CFOASafe 0
 #define __CFSetLastAllocationEventName(a, b) ((void) 0)
+#endif
+
 
-CF_EXPORT CFStringRef _CFCreateLimitedUniqueString(void);
 
 /* Comparators are passed the address of the values; this is somewhat different than CFComparatorFunction is used in public API usually. */
 CF_EXPORT CFIndex      CFBSearch(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context);
@@ -332,42 +381,56 @@ extern const void *__CFStringCollectionCopy(CFAllocatorRef allocator, const void
 extern const void *__CFTypeCollectionRetain(CFAllocatorRef allocator, const void *ptr);
 extern void __CFTypeCollectionRelease(CFAllocatorRef allocator, const void *ptr);
 
+extern CFTypeRef CFMakeUncollectable(CFTypeRef cf);
 
-#if DEPLOYMENT_TARGET_MACOSX
+__private_extern__ void _CFRaiseMemoryException(CFStringRef reason);
 
-typedef OSSpinLock CFSpinLock_t;
+__private_extern__ Boolean __CFProphylacticAutofsAccess;
 
-#define CFSpinLockInit OS_SPINLOCK_INIT
-#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) (X = CFSpinLockInit)
 
-CF_INLINE void __CFSpinLock(CFSpinLock_t *lockp) {
-    OSSpinLockLock(lockp);
-}
-
-CF_INLINE void __CFSpinUnlock(CFSpinLock_t *lockp) {
-    OSSpinLockUnlock(lockp);
-}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 
-#elif defined(__WIN32__)
+typedef OSSpinLock CFSpinLock_t;
 
-typedef CRITICAL_SECTION CFSpinLock_t;
+#define CFSpinLockInit OS_SPINLOCK_INIT
+#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) (X = CFSpinLockInit)
 
-#define CFSpinLockInit {0}
+#define __CFSpinLock(LP) ({ \
+    OSSpinLock *__lockp__ = (LP); \
+    OSSpinLock __lockv__ = *__lockp__; \
+    if (0 != __lockv__ && ~0 != __lockv__ && (uintptr_t)__lockp__ != (uintptr_t)__lockv__) { \
+        CFLog(3, CFSTR("In '%s', file %s, line %d, during lock, spin lock %p has value 0x%x, which is neither locked nor unlocked.  The memory has been smashed."), __PRETTY_FUNCTION__, __FILE__, __LINE__, __lockp__, __lockv__); \
+        /* HALT; */ \
+    } \
+    OSSpinLockLock(__lockp__); })
+
+#define __CFSpinUnlock(LP) ({ \
+    OSSpinLock *__lockp__ = (LP); \
+    OSSpinLock __lockv__ = *__lockp__; \
+    if (~0 != __lockv__ && (uintptr_t)__lockp__ != (uintptr_t)__lockv__) { \
+        CFLog(3, CFSTR("In '%s', file %s, line %d, during unlock, spin lock %p has value 0x%x, which is not locked.  The memory has been smashed or the lock is being unlocked when not locked."), __PRETTY_FUNCTION__, __FILE__, __LINE__, __lockp__, __lockv__); \
+        /* HALT; */ \
+    } \
+    OSSpinLockUnlock(__lockp__); })
+
+#elif DEPLOYMENT_TARGET_WINDOWS
+
+typedef int32_t CFSpinLock_t;
+#define CFSpinLockInit 0
+#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) (X = CFSpinLockInit)
 
-// For some reason, the {0} initializer does not work when the spinlock is a member of a structure; hence this macro
-#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) InitializeCriticalSection(&X)
-extern CFSpinLock_t *theLock;
-CF_INLINE void __CFSpinLock(CFSpinLock_t *slock) {
-    if (NULL == slock->DebugInfo) {
-        InitializeCriticalSection(slock);
+CF_INLINE void __CFSpinLock(volatile CFSpinLock_t *lock) {
+    while (InterlockedCompareExchange((LONG volatile *)lock, ~0, 0) != 0) {
+       Sleep(0);
     }
-    EnterCriticalSection(slock);
 }
 
-CF_INLINE void __CFSpinUnlock(CFSpinLock_t *lock) {
-    LeaveCriticalSection(lock);
+CF_INLINE void __CFSpinUnlock(volatile CFSpinLock_t *lock) {
+    MemoryBarrier();
+    *lock = 0;
 }
 
+
 #else
 
 #warning CF spin locks not defined for this platform -- CF is not thread-safe
@@ -376,17 +439,31 @@ CF_INLINE void __CFSpinUnlock(CFSpinLock_t *lock) {
 
 #endif
 
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+extern uint8_t __CF120293;
+extern uint8_t __CF120290;
+extern void __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__(void);
+#define CHECK_FOR_FORK() do { __CF120290 = true; if (__CF120293) __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__(); } while (0)
+#define CHECK_FOR_FORK_RET(...) do { CHECK_FOR_FORK(); if (__CF120293) return __VA_ARGS__; } while (0)
+#define HAS_FORKED() (__CF120293)
+#endif
+
 #if !defined(CHECK_FOR_FORK)
 #define CHECK_FOR_FORK() do { } while (0)
 #endif
 
+#if !defined(CHECK_FOR_FORK_RET)
+#define CHECK_FOR_FORK_RET(...) do { } while (0)
+#endif
+
 #if !defined(HAS_FORKED)
 #define HAS_FORKED() 0
 #endif
 
-#if defined(__svr4__) || defined(__hpux__) || defined(__WIN32__)
+#if DEPLOYMENT_TARGET_WINDOWS
 #include <errno.h>
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 #include <sys/errno.h>
 #endif
 
@@ -404,6 +481,9 @@ CF_EXPORT CFStringRef _CFCopyExtensionForAbstractType(CFStringRef abstractType);
 /* These functions all act on a c-strings which must be in the file system encoding. */
     
 CF_EXPORT Boolean _CFCreateDirectory(const char *path);
+#if DEPLOYMENT_TARGET_WINDOWS
+CF_EXPORT Boolean _CFCreateDirectoryWide(const wchar_t *path);
+#endif
 CF_EXPORT Boolean _CFRemoveDirectory(const char *path);
 CF_EXPORT Boolean _CFDeleteFile(const char *path);
 
@@ -412,7 +492,7 @@ CF_EXPORT Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void
     /* maxLength of zero means the whole file.  Otherwise it sets a limit on the number of bytes read. */
 
 CF_EXPORT Boolean _CFWriteBytesToFile(CFURLRef url, const void *bytes, CFIndex length);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 CF_EXPORT Boolean _CFWriteBytesToFileWithAtomicity(CFURLRef url, const void *bytes, unsigned int length, SInt32 mode, Boolean atomic);
 #endif
 
@@ -441,6 +521,34 @@ CF_EXPORT CFIndex _CFLengthAfterDeletingLastPathComponent(UniChar *unichars, CFI
 CF_EXPORT CFIndex _CFStartOfPathExtension(UniChar *unichars, CFIndex length);
 CF_EXPORT CFIndex _CFLengthAfterDeletingPathExtension(UniChar *unichars, CFIndex length);
 
+#define __CFMaxRuntimeTypes    65535
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
+
+#include <objc/runtime.h>
+
+extern int32_t __CFRuntimeClassTableSize;
+
+extern uintptr_t *__CFRuntimeObjCClassTable;
+CF_INLINE uintptr_t __CFISAForTypeID(CFTypeID typeID) {
+    return (typeID < __CFRuntimeClassTableSize) ? __CFRuntimeObjCClassTable[typeID] : 0;
+}
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+extern id objc_msgSend(id, SEL, ...);
+#elif DEPLOYMENT_TARGET_WINDOWS && defined(__cplusplus)
+extern "C" __declspec(dllimport) id objc_msgSend(id, SEL, ...);
+#elif DEPLOYMENT_TARGET_WINDOWS
+extern __declspec(dllimport) id objc_msgSend(id, SEL, ...);
+#endif
+
+extern void * (*__CFSendObjCMsg)(const void *, SEL, ...);
+
+CF_INLINE Boolean CF_IS_OBJC(CFTypeID typeID, const void *obj) {
+    return (typeID >= __CFRuntimeClassTableSize) || (((CFRuntimeBase *)obj)->_cfisa != __CFISAForTypeID(typeID) && ((CFRuntimeBase *)obj)->_cfisa > (uintptr_t)0xFFF);
+}
+
+#endif
 #define CF_IS_OBJC(typeID, obj)        (false)
 
 #define CF_OBJC_VOIDCALL0(obj, sel)
@@ -451,25 +559,13 @@ CF_EXPORT CFIndex _CFLengthAfterDeletingPathExtension(UniChar *unichars, CFIndex
 #define CF_OBJC_CALL1(rettype, retvar, obj, sel, a1)
 #define CF_OBJC_CALL2(rettype, retvar, obj, sel, a1, a2)
 
-#if defined (__WIN32__)
-#define CF_OBJC_FUNCDISPATCH0(typeID, rettype, obj, sel) ((void)0)
-#define CF_OBJC_FUNCDISPATCH1(typeID, rettype, obj, sel, a1) ((void)0)
-#define CF_OBJC_FUNCDISPATCH2(typeID, rettype, obj, sel, a1, a2) ((void)0)
-#define CF_OBJC_FUNCDISPATCH3(typeID, rettype, obj, sel, a1, a2, a3) ((void)0)
-#define CF_OBJC_FUNCDISPATCH4(typeID, rettype, obj, sel, a1, a2, a3, a4) ((void)0)
-#define CF_OBJC_FUNCDISPATCH5(typeID, rettype, obj, sel, a1, a2, a3, a4, a5) ((void)0)
-#else
 #define CF_OBJC_FUNCDISPATCH0(typeID, rettype, obj, sel)
 #define CF_OBJC_FUNCDISPATCH1(typeID, rettype, obj, sel, a1)
 #define CF_OBJC_FUNCDISPATCH2(typeID, rettype, obj, sel, a1, a2)
 #define CF_OBJC_FUNCDISPATCH3(typeID, rettype, obj, sel, a1, a2, a3)
 #define CF_OBJC_FUNCDISPATCH4(typeID, rettype, obj, sel, a1, a2, a3, a4)
 #define CF_OBJC_FUNCDISPATCH5(typeID, rettype, obj, sel, a1, a2, a3, a4, a5)
-#endif //__WIN32__
 
-#define __CFISAForTypeID(x) (0)
-
-#define __CFMaxRuntimeTypes    65535
 
 /* See comments in CFBase.c
 */
@@ -511,7 +607,7 @@ extern void *__CF_INVOKE_CALLBACK(void *, ...);
 //   DEFINE_WEAK_CARBONCORE_FUNC(void, DisposeHandle, (Handle h), (h))
 //
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 
 extern void *__CFLookupCFNetworkFunction(const char *name);
 
@@ -524,9 +620,20 @@ static R __CFNetwork_ ## N P {                             \
     return __VA_ARGS__ ;                               \
 }
 
+#define DEFINE_WEAK_CFNETWORK_FUNC_FAIL(R, N, P, A, FAILACTION, ...)   \
+static R __CFNetwork_ ## N P {                         \
+    static R (*dyfunc) P = (void *)(~(uintptr_t)0);    \
+    if ((void *)(~(uintptr_t)0) == dyfunc) {           \
+       dyfunc = __CFLookupCFNetworkFunction(#N); }     \
+    if (dyfunc) { return dyfunc A ; }                  \
+    FAILACTION ;                                       \
+    return __VA_ARGS__ ;                               \
+}
+
 #else
 
 #define DEFINE_WEAK_CFNETWORK_FUNC(R, N, P, A, ...)
+#define DEFINE_WEAK_CFNETWORK_FUNC_FAIL(R, N, P, A, ...)
 
 #endif
 
@@ -535,11 +642,21 @@ static R __CFNetwork_ ## N P {                            \
 #define DEFINE_WEAK_CARBONCORE_FUNC(R, N, P, A, ...)
 #endif
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+__private_extern__ CFComparisonResult _CFCompareStringsWithLocale(CFStringInlineBuffer *str1, CFRange str1Range, CFStringInlineBuffer *str2, CFRange str2Range, CFOptionFlags options, const void *compareLocale);
+#endif
+
 
 __private_extern__ CFArrayRef _CFBundleCopyUserLanguages(Boolean useBackstops);
 
-/* GC related internal SPIs. */
-extern malloc_zone_t *__CFCollectableZone;
+
+#if DEPLOYMENT_TARGET_WINDOWS
+__private_extern__ const wchar_t *_CFDLLPath(void);
+__private_extern__ void __CFStringCleanup(void);
+__private_extern__ void __CFSocketCleanup(void);
+__private_extern__ void __CFUniCharCleanup(void);
+__private_extern__ void __CFStreamCleanup(void);
+#endif
 
 /* !!! Avoid #importing objc.h; e.g. converting this to a .m file */
 struct __objcFastEnumerationStateEquivalent {
@@ -551,36 +668,7 @@ struct __objcFastEnumerationStateEquivalent {
 
 unsigned long _CFStorageFastEnumeration(CFStorageRef storage, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count);
 
-
-// Allocate an id[count], new slots are nil
-extern void *__CFAllocateObjectArray(unsigned long count);
-extern void *__CFReallocateObjectArray(id *array, unsigned long count);
-extern void __CFFreeObjectArray(id *array);
-
-// check against LONG_MAX to catch negative numbers
-#define new_id_array(N, C) \
-        size_t N ## _count__ = (C); \
-        if (N ## _count__ > LONG_MAX) { \
-           id rr = [objc_lookUpClass("NSString") stringWithFormat:@"*** attempt to create a temporary id buffer which is too large or with a negative count (%lu) -- possibly data is corrupt", N ## _count__]; \
-           @throw [NSException exceptionWithName:NSGenericException reason:rr userInfo:nil]; \
-       } \
-        NSInteger N ## _is_stack__ = (N ## _count__ <= 256); \
-        id N ## _buffer__[N ## _is_stack__ ? N ## _count__ : 0]; \
-        if (N ## _is_stack__) memset(N ## _buffer__, 0, sizeof(N ## _buffer__)); \
-        id * N = N ## _is_stack__ ? N ## _buffer__ : __CFAllocateObjectArray(N ## _count__); \
-        if (! N) { \
-           id rr = [objc_lookUpClass("NSString") stringWithFormat:@"*** attempt to create a temporary id buffer of length (%lu) failed", N ## _count__]; \
-           @throw [NSException exceptionWithName:NSMallocException reason:rr userInfo:nil]; \
-       } \
-        do {} while (0)
-
-#define free_id_array(N) \
-        if (! N ## _is_stack__) __CFFreeObjectArray(N)
-
-extern void *__CFFullMethodName(Class cls, id obj, SEL sel);
-extern void *__CFExceptionProem(id obj, SEL sel);
-extern void __CFRequireConcreteImplementation(Class absClass, id obj, SEL sel);
-
+CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFINTERNAL__ */
 
index cab8fd14bcd1f46ceae20a1963adabbbe006f225..0da713278b52b350719ee2d581a1d173d824a490 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*  CFLocale.c
-    Copyright 2002-2003, Apple Computer, Inc. All rights reserved.
+    Copyright (c) 2002-2009, Apple Inc. All rights reserved.
     Responsibility: Christopher Kane
 */
 
 #include <CoreFoundation/CFCalendar.h>
 #include <CoreFoundation/CFNumber.h>
 #include "CFInternal.h"
+#include "CFLocaleInternal.h"
 #include <unicode/uloc.h>           // ICU locales
 #include <unicode/ulocdata.h>       // ICU locale data
 #include <unicode/ucurr.h>          // ICU currency functions
 #include <unicode/uset.h>           // ICU Unicode sets
 #include <unicode/putil.h>          // ICU low-level utilities
 #include <unicode/umsg.h>           // ICU message formatting
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <CoreFoundation/CFNumberFormatter.h>
+#include <dispatch/dispatch.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unicode/ucol.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#include <stdio.h>
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 CONST_STRING_DECL(kCFLocaleCurrentLocaleDidChangeNotification, "kCFLocaleCurrentLocaleDidChangeNotification")
@@ -56,10 +62,11 @@ static const char *kCollationKeyword = "collation";
 
 typedef struct __CFLocale *CFMutableLocaleRef;
 
-__private_extern__ CONST_STRING_DECL(__kCFLocaleCollatorID, "locale:collator id")
+PE_CONST_STRING_DECL(__kCFLocaleCollatorID, "locale:collator id")
+
 
 enum {
-    __kCFLocaleKeyTableCount = 16
+    __kCFLocaleKeyTableCount = 21
 };
 
 struct key_table {
@@ -94,25 +101,31 @@ static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale, bool user, CFTypeRef
 static bool __CFLocaleCopyNumberFormat2(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context);
 static bool __CFLocaleCurrencyFullName(const char *locale, const char *value, CFStringRef *out);
 static bool __CFLocaleCopyCollatorID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context);
+static bool __CFLocaleCopyDelimiter(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context);
 
 // Note string members start with an extra &, and are fixed up at init time
 static struct key_table __CFLocaleKeyTable[__kCFLocaleKeyTableCount] = {
-    {(CFStringRef)&kCFLocaleIdentifier, __CFLocaleCopyLocaleID, __CFLocaleSetNOP, __CFLocaleFullName, NULL},
-    {(CFStringRef)&kCFLocaleLanguageCode, __CFLocaleCopyCodes, __CFLocaleSetNOP, __CFLocaleLanguageName, (CFStringRef)&kCFLocaleLanguageCode},
-    {(CFStringRef)&kCFLocaleCountryCode, __CFLocaleCopyCodes, __CFLocaleSetNOP, __CFLocaleCountryName, (CFStringRef)&kCFLocaleCountryCode},
-    {(CFStringRef)&kCFLocaleScriptCode, __CFLocaleCopyCodes, __CFLocaleSetNOP, __CFLocaleScriptName, (CFStringRef)&kCFLocaleScriptCode},
-    {(CFStringRef)&kCFLocaleVariantCode, __CFLocaleCopyCodes, __CFLocaleSetNOP, __CFLocaleVariantName, (CFStringRef)&kCFLocaleVariantCode},
-    {(CFStringRef)&kCFLocaleExemplarCharacterSet, __CFLocaleCopyExemplarCharSet, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
-    {(CFStringRef)&kCFLocaleCalendarIdentifier, __CFLocaleCopyCalendarID, __CFLocaleSetNOP, __CFLocaleCalendarName, NULL},
-    {(CFStringRef)&kCFLocaleCalendar, __CFLocaleCopyCalendar, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
-    {(CFStringRef)&kCFLocaleCollationIdentifier, __CFLocaleCopyCollationID, __CFLocaleSetNOP, __CFLocaleCollationName, NULL},
-    {(CFStringRef)&kCFLocaleUsesMetricSystem, __CFLocaleCopyUsesMetric, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
-    {(CFStringRef)&kCFLocaleMeasurementSystem, __CFLocaleCopyMeasurementSystem, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
-    {(CFStringRef)&kCFLocaleDecimalSeparator, __CFLocaleCopyNumberFormat, __CFLocaleSetNOP, __CFLocaleNoName, (CFStringRef)&kCFNumberFormatterDecimalSeparator},
-    {(CFStringRef)&kCFLocaleGroupingSeparator, __CFLocaleCopyNumberFormat, __CFLocaleSetNOP, __CFLocaleNoName, (CFStringRef)&kCFNumberFormatterGroupingSeparator},
-    {(CFStringRef)&kCFLocaleCurrencySymbol, __CFLocaleCopyNumberFormat2, __CFLocaleSetNOP, __CFLocaleCurrencyShortName, (CFStringRef)&kCFNumberFormatterCurrencySymbol},
-    {(CFStringRef)&kCFLocaleCurrencyCode, __CFLocaleCopyNumberFormat2, __CFLocaleSetNOP, __CFLocaleCurrencyFullName, (CFStringRef)&kCFNumberFormatterCurrencyCode},
+    {(CFStringRef)&kCFLocaleIdentifierKey, __CFLocaleCopyLocaleID, __CFLocaleSetNOP, __CFLocaleFullName, NULL},
+    {(CFStringRef)&kCFLocaleLanguageCodeKey, __CFLocaleCopyCodes, __CFLocaleSetNOP, __CFLocaleLanguageName, (CFStringRef)&kCFLocaleLanguageCodeKey},
+    {(CFStringRef)&kCFLocaleCountryCodeKey, __CFLocaleCopyCodes, __CFLocaleSetNOP, __CFLocaleCountryName, (CFStringRef)&kCFLocaleCountryCodeKey},
+    {(CFStringRef)&kCFLocaleScriptCodeKey, __CFLocaleCopyCodes, __CFLocaleSetNOP, __CFLocaleScriptName, (CFStringRef)&kCFLocaleScriptCodeKey},
+    {(CFStringRef)&kCFLocaleVariantCodeKey, __CFLocaleCopyCodes, __CFLocaleSetNOP, __CFLocaleVariantName, (CFStringRef)&kCFLocaleVariantCodeKey},
+    {(CFStringRef)&kCFLocaleExemplarCharacterSetKey, __CFLocaleCopyExemplarCharSet, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
+    {(CFStringRef)&kCFLocaleCalendarIdentifierKey, __CFLocaleCopyCalendarID, __CFLocaleSetNOP, __CFLocaleCalendarName, NULL},
+    {(CFStringRef)&kCFLocaleCalendarKey, __CFLocaleCopyCalendar, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
+    {(CFStringRef)&kCFLocaleCollationIdentifierKey, __CFLocaleCopyCollationID, __CFLocaleSetNOP, __CFLocaleCollationName, NULL},
+    {(CFStringRef)&kCFLocaleUsesMetricSystemKey, __CFLocaleCopyUsesMetric, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
+    {(CFStringRef)&kCFLocaleMeasurementSystemKey, __CFLocaleCopyMeasurementSystem, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
+    {(CFStringRef)&kCFLocaleDecimalSeparatorKey, __CFLocaleCopyNumberFormat, __CFLocaleSetNOP, __CFLocaleNoName, (CFStringRef)&kCFNumberFormatterDecimalSeparatorKey},
+    {(CFStringRef)&kCFLocaleGroupingSeparatorKey, __CFLocaleCopyNumberFormat, __CFLocaleSetNOP, __CFLocaleNoName, (CFStringRef)&kCFNumberFormatterGroupingSeparatorKey},
+    {(CFStringRef)&kCFLocaleCurrencySymbolKey, __CFLocaleCopyNumberFormat2, __CFLocaleSetNOP, __CFLocaleCurrencyShortName, (CFStringRef)&kCFNumberFormatterCurrencySymbolKey},
+    {(CFStringRef)&kCFLocaleCurrencyCodeKey, __CFLocaleCopyNumberFormat2, __CFLocaleSetNOP, __CFLocaleCurrencyFullName, (CFStringRef)&kCFNumberFormatterCurrencyCodeKey},
+    {(CFStringRef)&kCFLocaleCollatorIdentifierKey, __CFLocaleCopyCollatorID, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
     {(CFStringRef)&__kCFLocaleCollatorID, __CFLocaleCopyCollatorID, __CFLocaleSetNOP, __CFLocaleNoName, NULL},
+    {(CFStringRef)&kCFLocaleQuotationBeginDelimiterKey, __CFLocaleCopyDelimiter, __CFLocaleSetNOP, __CFLocaleNoName, (CFStringRef)&kCFLocaleQuotationBeginDelimiterKey},
+    {(CFStringRef)&kCFLocaleQuotationEndDelimiterKey, __CFLocaleCopyDelimiter, __CFLocaleSetNOP, __CFLocaleNoName, (CFStringRef)&kCFLocaleQuotationEndDelimiterKey},
+    {(CFStringRef)&kCFLocaleAlternateQuotationBeginDelimiterKey, __CFLocaleCopyDelimiter, __CFLocaleSetNOP, __CFLocaleNoName, (CFStringRef)&kCFLocaleAlternateQuotationBeginDelimiterKey},
+    {(CFStringRef)&kCFLocaleAlternateQuotationEndDelimiterKey, __CFLocaleCopyDelimiter, __CFLocaleSetNOP, __CFLocaleNoName, (CFStringRef)&kCFLocaleAlternateQuotationEndDelimiterKey},
 };
 
 
@@ -127,7 +140,16 @@ struct __CFLocale {
     CFMutableDictionaryRef _overrides;
     CFDictionaryRef _prefs;
     CFSpinLock_t _lock;
+    Boolean _nullLocale;
 };
+__private_extern__ Boolean __CFLocaleGetNullLocale(struct __CFLocale *locale) {
+    return locale->_nullLocale;
+}
+
+__private_extern__ void __CFLocaleSetNullLocale(struct __CFLocale *locale) {
+    locale->_nullLocale = true;
+}
 
 /* Flag bits */
 enum {      /* Bits 0-1 */
@@ -154,11 +176,11 @@ CF_INLINE void __CFLocaleUnlockGlobal(void) {
 }
 
 CF_INLINE void __CFLocaleLock(CFLocaleRef locale) {
-    __CFSpinLock(&locale->_lock);
+    __CFSpinLock(&((struct __CFLocale *)locale)->_lock);
 }
 
 CF_INLINE void __CFLocaleUnlock(CFLocaleRef locale) {
-    __CFSpinUnlock(&locale->_lock);
+    __CFSpinUnlock(&((struct __CFLocale *)locale)->_lock);
 }
 
 
@@ -253,10 +275,19 @@ CFLocaleRef CFLocaleGetSystem(void) {
     return locale;
 }
 
+extern CFDictionaryRef __CFXPreferencesCopyCurrentApplicationState(void);
+
 static CFLocaleRef __CFLocaleCurrent = NULL;
 
+
 #if DEPLOYMENT_TARGET_MACOSX
 #define FALLBACK_LOCALE_NAME CFSTR("")
+#elif DEPLOYMENT_TARGET_EMBEDDED
+#define FALLBACK_LOCALE_NAME CFSTR("en_US")
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define FALLBACK_LOCALE_NAME CFSTR("en_US")
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 CFLocaleRef CFLocaleCopyCurrent(void) {
@@ -271,7 +302,7 @@ CFLocaleRef CFLocaleCopyCurrent(void) {
 
     CFDictionaryRef prefs = NULL;
     CFStringRef identifier = NULL;
-
+    
     struct __CFLocale *locale;
     uint32_t size = sizeof(struct __CFLocale) - sizeof(CFRuntimeBase);
     locale = (struct __CFLocale *)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault, CFLocaleGetTypeID(), size, NULL);
@@ -279,12 +310,13 @@ CFLocaleRef CFLocaleCopyCurrent(void) {
        return NULL;
     }
     __CFLocaleSetType(locale, __kCFLocaleUser);
-    if (NULL == identifier) identifier = CFRetain(FALLBACK_LOCALE_NAME);
+    if (NULL == identifier) identifier = (CFStringRef)CFRetain(FALLBACK_LOCALE_NAME);
     locale->_identifier = identifier;
     locale->_cache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
     locale->_overrides = NULL;
     locale->_prefs = prefs;
     locale->_lock = CFSpinLockInit;
+    locale->_nullLocale = false;
 
     __CFLocaleLockGlobal();
     if (NULL == __CFLocaleCurrent) {
@@ -360,6 +392,13 @@ CFStringRef CFLocaleGetIdentifier(CFLocaleRef locale) {
 }
 
 CFTypeRef CFLocaleGetValue(CFLocaleRef locale, CFStringRef key) {
+    if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard)) {
+       // Hack for Opera, which is using the hard-coded string value below instead of
+        // the perfectly good public kCFLocaleCountryCode constant, for whatever reason.
+       if (key && CFEqual(key, CFSTR("locale:country code"))) {
+           key = kCFLocaleCountryCodeKey;
+       }
+    }
     CF_OBJC_FUNCDISPATCH1(CFLocaleGetTypeID(), CFTypeRef, locale, "objectForKey:", key);
     CFIndex idx, slot = -1;
     for (idx = 0; idx < __kCFLocaleKeyTableCount; idx++) {
@@ -544,6 +583,57 @@ CFArrayRef CFLocaleCopyCommonISOCurrencyCodes(void) {
     return result;
 }
 
+CFStringRef CFLocaleCreateLocaleIdentifierFromWindowsLocaleCode(CFAllocatorRef allocator, uint32_t lcid) {
+    char buffer[kMaxICUNameSize];
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t ret = uloc_getLocaleForLCID(lcid, buffer, kMaxICUNameSize, &status);
+    if (U_FAILURE(status) || kMaxICUNameSize <= ret) return NULL;
+    CFStringRef str = CFStringCreateWithCString(kCFAllocatorSystemDefault, buffer, kCFStringEncodingASCII);
+    CFStringRef ident = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault, str);
+    CFRelease(str);
+    return ident;
+}
+
+uint32_t CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(CFStringRef localeIdentifier) {
+    CFStringRef ident = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault, localeIdentifier);
+    char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
+    Boolean b = CFStringGetCString(ident, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII);
+    CFRelease(ident);
+    return b ? uloc_getLCID(localeID) : 0;
+}
+
+CFLocaleLanguageDirection CFLocaleGetLanguageCharacterDirection(CFStringRef isoLangCode) {
+    char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
+    Boolean b = CFStringGetCString(isoLangCode, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII);
+    CFLocaleLanguageDirection dir;
+    UErrorCode status = U_ZERO_ERROR;
+    ULayoutType idir = b ? uloc_getCharacterOrientation(localeID, &status) : ULOC_LAYOUT_UNKNOWN;
+    switch (idir) {
+    case ULOC_LAYOUT_LTR: dir = kCFLocaleLanguageDirectionLeftToRight; break;
+    case ULOC_LAYOUT_RTL: dir = kCFLocaleLanguageDirectionRightToLeft; break;
+    case ULOC_LAYOUT_TTB: dir = kCFLocaleLanguageDirectionTopToBottom; break;
+    case ULOC_LAYOUT_BTT: dir = kCFLocaleLanguageDirectionBottomToTop; break;
+    default: dir = kCFLocaleLanguageDirectionUnknown; break;
+    }
+    return dir;
+}
+
+CFLocaleLanguageDirection CFLocaleGetLanguageLineDirection(CFStringRef isoLangCode) {
+    char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
+    Boolean b = CFStringGetCString(isoLangCode, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII);
+    CFLocaleLanguageDirection dir;
+    UErrorCode status = U_ZERO_ERROR;
+    ULayoutType idir = b ? uloc_getLineOrientation(localeID, &status) : ULOC_LAYOUT_UNKNOWN;
+    switch (idir) {
+    case ULOC_LAYOUT_LTR: dir = kCFLocaleLanguageDirectionLeftToRight; break;
+    case ULOC_LAYOUT_RTL: dir = kCFLocaleLanguageDirectionRightToLeft; break;
+    case ULOC_LAYOUT_TTB: dir = kCFLocaleLanguageDirectionTopToBottom; break;
+    case ULOC_LAYOUT_BTT: dir = kCFLocaleLanguageDirectionBottomToTop; break;
+    default: dir = kCFLocaleLanguageDirectionUnknown; break;
+    }
+    return dir;
+}
+
 CFArrayRef CFLocaleCopyPreferredLanguages(void) {
     CFMutableArrayRef newArray = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
     CFArrayRef languagesArray = (CFArrayRef)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication);
@@ -685,30 +775,55 @@ static bool __CFLocaleCopyICUKeyword(CFLocaleRef locale, bool user, CFTypeRef *c
 static bool __CFLocaleCopyCalendarID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
     bool succeeded = __CFLocaleCopyICUKeyword(locale, user, cf, context, kCalendarKeyword);
     if (succeeded) {
-       if (CFEqual(*cf, kCFGregorianCalendar)) {
+       if (CFEqual(*cf, kCFCalendarIdentifierGregorian)) {
+           CFRelease(*cf);
+           *cf = CFRetain(kCFCalendarIdentifierGregorian);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierBuddhist)) {
+           CFRelease(*cf);
+           *cf = CFRetain(kCFCalendarIdentifierBuddhist);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierJapanese)) {
+           CFRelease(*cf);
+           *cf = CFRetain(kCFCalendarIdentifierJapanese);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierIslamic)) {
+           CFRelease(*cf);
+           *cf = CFRetain(kCFCalendarIdentifierIslamic);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierIslamicCivil)) {
+           CFRelease(*cf);
+           *cf = CFRetain(kCFCalendarIdentifierIslamicCivil);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierHebrew)) {
+           CFRelease(*cf);
+           *cf = CFRetain(kCFCalendarIdentifierHebrew);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierChinese)) {
+           CFRelease(*cf);
+           *cf = CFRetain(kCFCalendarIdentifierChinese);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierRepublicOfChina)) {
+           CFRelease(*cf);
+           *cf = CFRetain(kCFCalendarIdentifierRepublicOfChina);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierPersian)) {
            CFRelease(*cf);
-           *cf = CFRetain(kCFGregorianCalendar);
-       } else if (CFEqual(*cf, kCFBuddhistCalendar)) {
+           *cf = CFRetain(kCFCalendarIdentifierPersian);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierIndian)) {
            CFRelease(*cf);
-           *cf = CFRetain(kCFBuddhistCalendar);
-       } else if (CFEqual(*cf, kCFJapaneseCalendar)) {
+           *cf = CFRetain(kCFCalendarIdentifierIndian);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierISO8601)) {
            CFRelease(*cf);
-           *cf = CFRetain(kCFJapaneseCalendar);
-       } else if (CFEqual(*cf, kCFIslamicCalendar)) {
+           *cf = CFRetain(kCFCalendarIdentifierISO8601);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierCoptic)) {
            CFRelease(*cf);
-           *cf = CFRetain(kCFIslamicCalendar);
-       } else if (CFEqual(*cf, kCFIslamicCivilCalendar)) {
+           *cf = CFRetain(kCFCalendarIdentifierCoptic);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierEthiopicAmeteMihret)) {
            CFRelease(*cf);
-           *cf = CFRetain(kCFIslamicCivilCalendar);
-       } else if (CFEqual(*cf, kCFHebrewCalendar)) {
+           *cf = CFRetain(kCFCalendarIdentifierEthiopicAmeteMihret);
+       } else if (CFEqual(*cf, kCFCalendarIdentifierEthiopicAmeteAlem)) {
            CFRelease(*cf);
-           *cf = CFRetain(kCFHebrewCalendar);
-       } else if (CFEqual(*cf, kCFChineseCalendar)) {
+           *cf = CFRetain(kCFCalendarIdentifierEthiopicAmeteAlem);
+       } else {
            CFRelease(*cf);
-           *cf = CFRetain(kCFChineseCalendar);
+           *cf = NULL;
+           return false;
        }
     } else {
-       *cf = CFRetain(kCFGregorianCalendar);
+       *cf = CFRetain(kCFCalendarIdentifierGregorian);
     }
     return true;
 }
@@ -717,6 +832,27 @@ static bool __CFLocaleCopyCalendar(CFLocaleRef locale, bool user, CFTypeRef *cf,
     if (__CFLocaleCopyCalendarID(locale, user, cf, context)) {
        CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, (CFStringRef)*cf);
        CFCalendarSetLocale(calendar, locale);
+        CFDictionaryRef prefs = __CFLocaleGetPrefs(locale);
+        CFPropertyListRef metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleFirstWeekday")) : NULL;
+        if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
+            metapref = (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)metapref, *cf);
+        }
+        if (NULL != metapref && CFGetTypeID(metapref) == CFNumberGetTypeID()) {
+            CFIndex wkdy;
+            if (CFNumberGetValue((CFNumberRef)metapref, kCFNumberCFIndexType, &wkdy)) {
+                CFCalendarSetFirstWeekday(calendar, wkdy);
+            }
+        }
+        metapref = prefs ? CFDictionaryGetValue(prefs, CFSTR("AppleMinDaysInFirstWeek")) : NULL;
+        if (NULL != metapref && CFGetTypeID(metapref) == CFDictionaryGetTypeID()) {
+            metapref = (CFNumberRef)CFDictionaryGetValue((CFDictionaryRef)metapref, *cf);
+        }
+        if (NULL != metapref && CFGetTypeID(metapref) == CFNumberGetTypeID()) {
+            CFIndex mwd;
+            if (CFNumberGetValue((CFNumberRef)metapref, kCFNumberCFIndexType, &mwd)) {
+                CFCalendarSetMinimumDaysInFirstWeek(calendar, mwd);
+            }
+        }
        CFRelease(*cf);
        *cf = calendar;
        return true;
@@ -724,12 +860,61 @@ static bool __CFLocaleCopyCalendar(CFLocaleRef locale, bool user, CFTypeRef *cf,
     return false;
 }
 
+static bool __CFLocaleCopyDelimiter(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
+    ULocaleDataDelimiterType type = (ULocaleDataDelimiterType)0;
+    if (context == kCFLocaleQuotationBeginDelimiterKey) {
+       type = ULOCDATA_QUOTATION_START;
+    } else if (context == kCFLocaleQuotationEndDelimiterKey) {
+       type = ULOCDATA_QUOTATION_END;
+    } else if (context == kCFLocaleAlternateQuotationBeginDelimiterKey) {
+       type = ULOCDATA_ALT_QUOTATION_START;
+    } else if (context == kCFLocaleAlternateQuotationEndDelimiterKey) {
+       type = ULOCDATA_ALT_QUOTATION_END;
+    } else {
+       return false;
+    }
+
+    char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
+    if (!CFStringGetCString(locale->_identifier, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII)) {
+       return false;
+    }
+
+    UChar buffer[130];
+    UErrorCode status = U_ZERO_ERROR;
+    ULocaleData *uld = ulocdata_open(localeID, &status);
+    int32_t len = ulocdata_getDelimiter(uld, type, buffer, sizeof(buffer) / sizeof(buffer[0]), &status);
+    ulocdata_close(uld);
+    if (U_FAILURE(status) || sizeof(buffer) / sizeof(buffer[0]) < len) {
+        return false;
+    }
+
+    *cf = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)buffer, len);
+    return (*cf != NULL);
+}
+
 static bool __CFLocaleCopyCollationID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
     return __CFLocaleCopyICUKeyword(locale, user, cf, context, kCollationKeyword);
 }
 
 static bool __CFLocaleCopyCollatorID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
     CFStringRef canonLocaleCFStr = NULL;
+    if (user) {
+       CFStringRef pref = (CFStringRef)CFDictionaryGetValue(locale->_prefs, CFSTR("AppleCollationOrder"));
+       if (pref) {
+           // Canonicalize pref string in case it's not in the canonical format.
+           canonLocaleCFStr = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault, pref);
+       } else {
+           CFArrayRef languagesArray = (CFArrayRef)CFDictionaryGetValue(locale->_prefs, CFSTR("AppleLanguages"));
+           if (languagesArray && (CFArrayGetTypeID() == CFGetTypeID(languagesArray))) {
+               if (0 < CFArrayGetCount(languagesArray)) {
+                   CFStringRef str = (CFStringRef)CFArrayGetValueAtIndex(languagesArray, 0);
+                   if (str && (CFStringGetTypeID() == CFGetTypeID(str))) {
+                       canonLocaleCFStr = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorSystemDefault, str);
+                   }
+               }
+           }
+       }
+    }
     if (!canonLocaleCFStr) {
        canonLocaleCFStr = CFLocaleGetIdentifier(locale);
        CFRetain(canonLocaleCFStr);
@@ -741,7 +926,24 @@ static bool __CFLocaleCopyCollatorID(CFLocaleRef locale, bool user, CFTypeRef *c
 static bool __CFLocaleCopyUsesMetric(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
     bool us = false;    // Default is Metric
     bool done = false;
-
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    if (user) {
+       CFTypeRef pref = CFDictionaryGetValue(locale->_prefs, CFSTR("AppleMetricUnits"));
+       if (pref) {
+           us = (kCFBooleanFalse == pref);
+           done = true;
+       } else {
+           pref = CFDictionaryGetValue(locale->_prefs, CFSTR("AppleMeasurementUnits"));
+           if (pref) {
+               us = CFEqual(pref, CFSTR("Inches"));
+               done = true;
+           }
+       }
+    }
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
     if (!done) {
         char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
         if (CFStringGetCString(locale->_identifier, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII)) {
@@ -772,10 +974,13 @@ static bool __CFLocaleCopyMeasurementSystem(CFLocaleRef locale, bool user, CFTyp
 
 static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
     CFStringRef str = NULL;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorSystemDefault, locale, kCFNumberFormatterDecimalStyle);
     str = nf ? CFNumberFormatterCopyProperty(nf, context) : NULL;
     if (nf) CFRelease(nf);
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     if (str) {
        *cf = str;
@@ -788,10 +993,13 @@ static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale, bool user, CFTypeRef
 // so we have to have another routine here which creates a Currency number formatter.
 static bool __CFLocaleCopyNumberFormat2(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
     CFStringRef str = NULL;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorSystemDefault, locale, kCFNumberFormatterCurrencyStyle);
     str = nf ? CFNumberFormatterCopyProperty(nf, context) : NULL;
     if (nf) CFRelease(nf);
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     if (str) {
        *cf = str;
@@ -822,7 +1030,10 @@ static bool __CFLocaleICUKeywordValueName(const char *locale, const char *value,
     // Need to make a fake locale ID
     char lid[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
     if (strlen(value) < ULOC_KEYWORD_AND_VALUES_CAPACITY) {
-        snprintf(lid, sizeof(lid), "en_US@%s=%s", keyword, value);
+       strlcpy(lid, "en_US@", sizeof(lid));
+       strlcat(lid, keyword, sizeof(lid));
+       strlcat(lid, "=", sizeof(lid));
+       strlcat(lid, value, sizeof(lid));
         size = uloc_getDisplayKeywordValue(lid, keyword, locale, name, kMaxICUNameSize, &icuStatus);
         if (U_SUCCESS(icuStatus) && size > 0 && icuStatus != U_USING_DEFAULT_WARNING) {
             *out = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)name, size);
@@ -895,17 +1106,15 @@ static bool __CFLocaleFullName(const char *locale, const char *value, CFStringRe
 }
 
 static bool __CFLocaleLanguageName(const char *locale, const char *value, CFStringRef *out) {
-    int len = strlen(value);
-    if (len >= 2 && len <= 3)
-        return __CFLocaleICUName(locale, value, out, uloc_getDisplayLanguage);
-    return false;
+    return __CFLocaleICUName(locale, value, out, uloc_getDisplayLanguage);
 }
 
 static bool __CFLocaleCountryName(const char *locale, const char *value, CFStringRef *out) {
     // Need to make a fake locale ID
     char lid[ULOC_FULLNAME_CAPACITY];
-    if (strlen(value) == 2) {
-        snprintf(lid, sizeof(lid), "en_%s", value);
+    if (strlen(value) < sizeof(lid) - 3) {
+       strlcpy(lid, "en_", sizeof(lid));
+       strlcat(lid, value, sizeof(lid));
         return __CFLocaleICUName(locale, lid, out, uloc_getDisplayCountry);
     }
     return false;
@@ -915,7 +1124,9 @@ static bool __CFLocaleScriptName(const char *locale, const char *value, CFString
     // Need to make a fake locale ID
     char lid[ULOC_FULLNAME_CAPACITY];
     if (strlen(value) == 4) {
-        snprintf(lid, sizeof(lid), "en_%s_US", value);
+       strlcpy(lid, "en_", sizeof(lid));
+       strlcat(lid, value, sizeof(lid));
+       strlcat(lid, "_US", sizeof(lid));
         return __CFLocaleICUName(locale, lid, out, uloc_getDisplayScript);
     }
     return false;
@@ -924,8 +1135,9 @@ static bool __CFLocaleScriptName(const char *locale, const char *value, CFString
 static bool __CFLocaleVariantName(const char *locale, const char *value, CFStringRef *out) {
     // Need to make a fake locale ID
     char lid[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
-    if (strlen(value) < ULOC_FULLNAME_CAPACITY) {
-        snprintf(lid, sizeof(lid), "en_US_%s", value);
+    if (strlen(value) < sizeof(lid) - 6) {
+       strlcpy(lid, "en_US_", sizeof(lid));
+       strlcat(lid, value, sizeof(lid));
         return __CFLocaleICUName(locale, lid, out, uloc_getDisplayVariant);
     }
     return false;
@@ -951,33 +1163,5 @@ static bool __CFLocaleNoName(const char *locale, const char *value, CFStringRef
     return false;
 }
 
-// Remember to keep the names such that they would make sense for the user locale,
-// in addition to the others; for example, it is "Currency", not "DefaultCurrency".
-// (And besides, "Default" is almost always implied.)  Words like "Default" and
-// "Preferred" and so on should be left out of the names.
-CONST_STRING_DECL(kCFLocaleIdentifier, "locale:id")
-CONST_STRING_DECL(kCFLocaleLanguageCode, "locale:language code")
-CONST_STRING_DECL(kCFLocaleCountryCode, "locale:country code")
-CONST_STRING_DECL(kCFLocaleScriptCode, "locale:script code")
-CONST_STRING_DECL(kCFLocaleVariantCode, "locale:variant code")
-CONST_STRING_DECL(kCFLocaleExemplarCharacterSet, "locale:exemplar characters")
-CONST_STRING_DECL(kCFLocaleCalendarIdentifier, "calendar")
-CONST_STRING_DECL(kCFLocaleCalendar, "locale:calendarref")
-CONST_STRING_DECL(kCFLocaleCollationIdentifier, "collation")
-CONST_STRING_DECL(kCFLocaleUsesMetricSystem, "locale:uses metric")
-CONST_STRING_DECL(kCFLocaleMeasurementSystem, "locale:measurement system")
-CONST_STRING_DECL(kCFLocaleDecimalSeparator, "locale:decimal separator")
-CONST_STRING_DECL(kCFLocaleGroupingSeparator, "locale:grouping separator")
-CONST_STRING_DECL(kCFLocaleCurrencySymbol, "locale:currency symbol")
-CONST_STRING_DECL(kCFLocaleCurrencyCode, "currency")
-
-CONST_STRING_DECL(kCFGregorianCalendar, "gregorian")
-CONST_STRING_DECL(kCFBuddhistCalendar, "buddhist")
-CONST_STRING_DECL(kCFJapaneseCalendar, "japanese")
-CONST_STRING_DECL(kCFIslamicCalendar, "islamic")
-CONST_STRING_DECL(kCFIslamicCivilCalendar, "islamic-civil")
-CONST_STRING_DECL(kCFHebrewCalendar, "hebrew")
-CONST_STRING_DECL(kCFChineseCalendar, "chinese")
-
 #undef kMaxICUNameSize
 
index ec73158604dd5affbcc6ded0fba9e43db4146ba3..cc7b5ce3e42c1f6cb3f219f2a3f0dd7fed58dada 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFLocale.h
-       Copyright (c) 2002-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2002-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFLOCALE__)
@@ -101,6 +101,29 @@ CF_EXPORT
 CFStringRef CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(CFAllocatorRef allocator, LangCode lcode, RegionCode rcode) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
        // Map a Mac OS LangCode and RegionCode to the canonical locale identifier.
 
+CF_EXPORT
+CFStringRef CFLocaleCreateLocaleIdentifierFromWindowsLocaleCode(CFAllocatorRef allocator, uint32_t lcid) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+       // Map a Windows LCID to the canonical locale identifier.
+
+CF_EXPORT
+uint32_t CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(CFStringRef localeIdentifier) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+       // Map a locale identifier to a Windows LCID.
+
+enum {
+    kCFLocaleLanguageDirectionUnknown = 0,
+    kCFLocaleLanguageDirectionLeftToRight = 1,
+    kCFLocaleLanguageDirectionRightToLeft = 2,
+    kCFLocaleLanguageDirectionTopToBottom = 3,
+    kCFLocaleLanguageDirectionBottomToTop = 4
+};
+typedef CFIndex CFLocaleLanguageDirection;
+
+CF_EXPORT
+CFLocaleLanguageDirection CFLocaleGetLanguageCharacterDirection(CFStringRef isoLangCode) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+CF_EXPORT
+CFLocaleLanguageDirection CFLocaleGetLanguageLineDirection(CFStringRef isoLangCode) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
 CF_EXPORT
 CFDictionaryRef CFLocaleCreateComponentsFromLocaleIdentifier(CFAllocatorRef allocator, CFStringRef localeID) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
        // Parses a locale ID consisting of language, script, country, variant,
@@ -166,6 +189,11 @@ CF_EXPORT const CFStringRef kCFLocaleDecimalSeparator AVAILABLE_MAC_OS_X_VERSION
 CF_EXPORT const CFStringRef kCFLocaleGroupingSeparator AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
 CF_EXPORT const CFStringRef kCFLocaleCurrencySymbol AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
 CF_EXPORT const CFStringRef kCFLocaleCurrencyCode AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; // ISO 3-letter currency code
+CF_EXPORT const CFStringRef kCFLocaleCollatorIdentifier AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+CF_EXPORT const CFStringRef kCFLocaleQuotationBeginDelimiterKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+CF_EXPORT const CFStringRef kCFLocaleQuotationEndDelimiterKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+CF_EXPORT const CFStringRef kCFLocaleAlternateQuotationBeginDelimiterKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+CF_EXPORT const CFStringRef kCFLocaleAlternateQuotationEndDelimiterKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
 
 // Values for kCFLocaleCalendarIdentifier
 CF_EXPORT const CFStringRef kCFGregorianCalendar AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
@@ -175,7 +203,10 @@ CF_EXPORT const CFStringRef kCFHebrewCalendar AVAILABLE_MAC_OS_X_VERSION_10_4_AN
 CF_EXPORT const CFStringRef kCFIslamicCalendar AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
 CF_EXPORT const CFStringRef kCFIslamicCivilCalendar AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
 CF_EXPORT const CFStringRef kCFJapaneseCalendar AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
-
+CF_EXPORT const CFStringRef kCFRepublicOfChinaCalendar AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+CF_EXPORT const CFStringRef kCFPersianCalendar AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+CF_EXPORT const CFStringRef kCFIndianCalendar AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+CF_EXPORT const CFStringRef kCFISO8601Calendar AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
 
 CF_EXTERN_C_END
 
index 2b5cc357f5dcca954c57944cb5ebbe43f68385b1..1c4d595ed4bfe495951dc2313f6a2b9778967cdf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -22,7 +22,7 @@
  */
 /*
     CFLocaleIdentifier.c
-       Copyright (c) 2002-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2002-2009, Apple Inc. All rights reserved.
     Responsibility: Christopher Kane
     
     CFLocaleIdentifier.c defines
@@ -74,7 +74,8 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unicode/uloc.h>
-
+#include "CFInternal.h"
+#include "CFLocaleInternal.h"
 
 // Max byte length of locale identifier (ASCII) as C string, including terminating null byte
 enum {
@@ -169,7 +170,7 @@ static const char * const regionCodeToLocaleString[] = {
     "uk_UA",        //  62 verUkraine;           45 langUkrainian;
     NULL,           //  63 *unused;              -1 none;           * one-way mapping   # ""
     "el_GR",        //  64 verGreeceAlt;         14 langGreek (modern)-Grek-mono;   * one-way mapping
-    "sr_CS",        //  65 verSerbian;           42 langSerbian -Cyrl;                                                         // <1.18>
+    "sr_RS",        //  65 verSerbian;           42 langSerbian -Cyrl;                                                         // <1.18>
     "sl_SI",        //  66 verSlovenian;         40 langSlovenian;
     "mk_MK",        //  67 verMacedonian;        43 langMacedonian;
     "hr_HR",        //  68 verCroatia;           18 langCroatian;
@@ -527,13 +528,15 @@ static const KeyStringToResultString oldAppleLocaleToCanonical[] = {
     { "ms.La",                  "ms"        },  //                      # from old LocaleRefGetPartString
     { "nl-be",                  "nl-BE"     },  //                      # from old LocaleRefGetPartString
     { "nl-be_BE",               "nl_BE"     },  //                      # from old LocaleRefGetPartString
+    { "no-NO",                                 "nb-NO"     },  //                      # not handled by localeStringPrefixToCanonical
+    { "no-NO_NO",                              "nb-NO_NO"  },  //                      # not handled by localeStringPrefixToCanonical
 //  { "no-bok_NO",              "nb_NO"     },  //                      # from old LocaleRefGetPartString - handled by localeStringPrefixToCanonical
 //  { "no-nyn_NO",              "nn_NO"     },  //                      # from old LocaleRefGetPartString - handled by localeStringPrefixToCanonical
 //  { "nya",                    "ny"        },  //                      # from old LocaleRefGetPartString - handled by localeStringPrefixToCanonical
     { "pa_??",                  "pa"        },  //                      # from old LocaleRefGetPartString
     { "sa.Dv",                  "sa"        },  //                      # from old LocaleRefGetPartString
     { "sl_??",                  "sl_SI"     },  //                      # from old MapScriptInfoAndISOCodes
-    { "sr_??",                  "sr_CS"     },  //                      # from old MapScriptInfoAndISOCodes                                            // <1.18>
+    { "sr_??",                  "sr_RS"     },  //                      # from old MapScriptInfoAndISOCodes                                            // <1.18>
     { "su.La",                  "su"        },  //                      # from old LocaleRefGetPartString
     { "yi.He",                  "yi"        },  //                      # from old LocaleRefGetPartString
     { "zh-simp",                "zh-Hans"   },  //                      # from earlier version of tables in this file!
@@ -719,24 +722,23 @@ static const SpecialCaseUpdates specialCases[] = {
 // Data for special cases
 // a) The 3166 code CS was used for Czechoslovakia until 1993, when that country split and the code was
 // replaced by CZ and SK. Then in 2003-07, the code YU (formerly designating all of Yugoslavia, then after
-// the 1990s breakup just designating what is now Serbia and Montenegro) was changed to CS! However, ICU
-// and RFC 3066bis will continue to use YU for this. So now CS is ambiguous. We guess as follows: If we
-// see CS but a language of cs or sk, we change CS to CZ or SK. Otherwise, we change CS to YU.
+// the 1990s breakup just designating what is now Serbia and Montenegro) was changed to CS! Then after
+// Serbia and Montenegro split, the code CS was replaced in 2006-09 with separate codes RS and ME. If we
+// see CS but a language of cs or sk, we change CS to CZ or SK. Otherwise, we change CS (and old YU) to RS.
 // b) The 639 code sh for Serbo-Croatian was also replaced in the 1990s by separate codes hr and sr, and
 // deprecated in 2000. We guess which one to map it to as follows: If there is a region tag of HR we use
-// hr; if there is a region tag of (now) YU we use sr; else we do not change it (not enough info).
+// hr; if there is a region tag of (now) RS we use sr; else we do not change it (not enough info).
 // c) There are other codes that have been updated without these issues (eg. TP to TL), plus among the
 // "exceptionally reserved" codes some are just alternates for standard codes (eg. UK for GB).
     {   NULL,   "-UK",  "GB",   NULL,   NULL    },  // always change UK to GB (UK is "exceptionally reserved" to mean GB)
     {   NULL,   "-TP",  "TL",   NULL,   NULL    },  // always change TP to TL (East Timor, code changed 2002-05)
     {   "cs",   "-CS",  "CZ",   NULL,   NULL    },  // if language is cs, change CS (pre-1993 Czechoslovakia) to CZ (Czech Republic)
     {   "sk",   "-CS",  "SK",   NULL,   NULL    },  // if language is sk, change CS (pre-1993 Czechoslovakia) to SK (Slovakia)
-    {   NULL,   "-YU",  "CS",   NULL,   NULL    },  // then always change YU to CS (map old Yugoslavia code to new 2003-07 ISO code
-                                                                                               // for Serbia & Montenegro per RFC3066bis & ICU)                                                                // <1.18>
-                                                    // Note: do this after fixing CS for cs/sk as above.
-    {   "sh",   "-HR",  "hr",   "-CS",  "sr"    },  // if language is old 'sh' (SerboCroatian), change it to 'hr' (Croatian) if we find
-                                                    // HR (Croatia) or to 'sr' (Serbian) if we find CS (Serbia & Montenegro, Yugoslavia).      // <1.18>
-                                                    // Note: Do this after changing YU to CS as above.
+    {   NULL,   "-CS",  "RS",   NULL,   NULL    },  // otherwise map CS (assume Serbia+Montenegro) to RS (Serbia)
+    {   NULL,   "-YU",  "RS",   NULL,   NULL    },  // also map old YU (assume Serbia+Montenegro) to RS (Serbia)
+    {   "sh",   "-HR",  "hr",   "-RS",  "sr"    },  // then if language is old 'sh' (SerboCroatian), change it to 'hr' (Croatian)
+                                                    // if we find HR (Croatia) or to 'sr' (Serbian) if we find RS (Serbia).
+                                                    // Note: Do this after changing YU/CS toRS as above.
     {   NULL,   NULL,   NULL,   NULL,   NULL    }   // terminator
 };
 
@@ -1509,72 +1511,7 @@ static void _AppendKeyValueString(char inLocaleString[], int locStringMaxLen, ch
        }
 }
 
-__private_extern__ CFStringRef _CFLocaleCreateCanonicalLanguageIdentifierForCFBundle(CFAllocatorRef allocator, CFStringRef localeIdentifier) {
-    char            inLocaleString[kLocaleIdentifierCStringMax];
-    CFStringRef     outStringRef = NULL;
-    
-    if ( localeIdentifier && CFStringGetCString(localeIdentifier, inLocaleString,  sizeof(inLocaleString), kCFStringEncodingASCII) ) {
-        KeyStringToResultString     testEntry;
-        KeyStringToResultString *   foundEntry;
-        char                        keyValueString[sizeof(inLocaleString)];                            // <1.10>
-        char                                           varKeyValueString[sizeof(inLocaleString)];                      // <1.17>
-
-        _GetKeyValueString(inLocaleString, keyValueString);                                                            // <1.10>
-        testEntry.result = NULL;
-        
-        // A. First check if input string matches an old-style string that has a replacement
-        // (do this before case normalization)
-        testEntry.key = inLocaleString;
-        foundEntry = (KeyStringToResultString *)bsearch( &testEntry, oldAppleLocaleToCanonical, kNumOldAppleLocaleToCanonical,
-                                                        sizeof(KeyStringToResultString), _CompareTestEntryToTableEntryKey );
-        if (foundEntry) {
-            // It does match, so replace old string with new
-            strlcpy(inLocaleString, foundEntry->result, sizeof(inLocaleString));
-             varKeyValueString[0] = 0;
-        } else {
-            // B. No match with an old-style string, use input string but update codes, normalize case, etc.
-            _UpdateFullLocaleString(inLocaleString, sizeof(inLocaleString), NULL, NULL, varKeyValueString);   // <1.10><1.17>
-        }
-        
-        // C. Now we have an up-to-date locale string, but we need to strip defaults and turn it into a language string
-        
-        // 1. Strip defaults in input string based on initial part of locale string
-        // (mainly to strip default script tag for a language)
-        testEntry.key = inLocaleString;
-        foundEntry = (KeyStringToResultString *)bsearch( &testEntry, localeStringPrefixToDefaults, kNumLocaleStringPrefixToDefaults,
-                                                        sizeof(KeyStringToResultString), _CompareTestEntryPrefixToTableEntryKey );
-        if (foundEntry) {
-            // The input string begins with a character sequence for which
-            // there are default substrings which should be stripped if present
-            _RemoveSubstringsIfPresent(inLocaleString, foundEntry->result);         
-        }
-        
-        // 2. If the string matches a locale string used by Apple as a language string, turn it into a language string
-        testEntry.key = inLocaleString;
-        foundEntry = (KeyStringToResultString *)bsearch( &testEntry, appleLocaleToLanguageStringForCFBundle, kNumAppleLocaleToLanguageStringForCFBundle,
-                                                        sizeof(KeyStringToResultString), _CompareTestEntryToTableEntryKey );
-        if (foundEntry) {
-            // it does match
-            strlcpy(inLocaleString, foundEntry->result, sizeof(inLocaleString));
-        } else {
-            // just delete the region tag and anything after
-            char *  inLocalePtr = inLocaleString;
-            while (*inLocalePtr != 0 && *inLocalePtr != '_') {
-                inLocalePtr++;
-            }
-            *inLocalePtr = 0;
-        }
-        
-        // D. Re-append any key-value strings, now canonical                                                                           // <1.10><1.17>
-               _AppendKeyValueString( inLocaleString, sizeof(inLocaleString), varKeyValueString );
-               _AppendKeyValueString( inLocaleString, sizeof(inLocaleString), keyValueString );
-        
-        // All done, return what we came up with.
-        outStringRef = CFStringCreateWithCString(allocator, inLocaleString, kCFStringEncodingASCII);
-    }
-
-    return outStringRef;
-}
+// __private_extern__ CFStringRef _CFLocaleCreateCanonicalLanguageIdentifierForCFBundle(CFAllocatorRef allocator, CFStringRef localeIdentifier) {}
 
 CFStringRef CFLocaleCreateCanonicalLanguageIdentifierFromString(CFAllocatorRef allocator, CFStringRef localeIdentifier) {
     char            inLocaleString[kLocaleIdentifierCStringMax];
@@ -1760,6 +1697,101 @@ CFStringRef CFLocaleCreateCanonicalLocaleIdentifierFromScriptManagerCodes(CFAllo
 }
 
 
+/*
+SPI:  CFLocaleGetLanguageRegionEncodingForLocaleIdentifier gets the appropriate language and region codes,
+ and the default legacy script code and encoding, for the specified locale (or language) string.
+ Returns false if CFLocale has no information about the given locale (in which case none of the by-reference return values are set);
+ otherwise may set *langCode and/or *regCode to -1 if there is no appropriate legacy value for the locale.
+ This is a replacement for the CFBundle SPI CFBundleGetLocalizationInfoForLocalization (which was intended to be temporary and transitional);
+ this function is more up-to-date in its handling of locale strings, and is in CFLocale where this functionality should belong. Compared
+ to CFBundleGetLocalizationInfoForLocalization, this function does not spcially interpret a NULL localeIdentifier to mean use the single most
+ preferred localization in the current context (this function returns NO for a NULL localeIdentifier); and in this function
+ langCode, regCode, and scriptCode are all SInt16* (not SInt32* like the equivalent parameters in CFBundleGetLocalizationInfoForLocalization).
+*/
+static int CompareLocaleToLegacyCodesEntries( const void *entry1, const void *entry2 );
+
+Boolean CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(CFStringRef localeIdentifier, LangCode *langCode, RegionCode *regCode, ScriptCode *scriptCode, CFStringEncoding *stringEncoding) {
+       Boolean         returnValue = false;
+       CFStringRef     canonicalIdentifier = CFLocaleCreateCanonicalLocaleIdentifierFromString(NULL, localeIdentifier);
+       if (canonicalIdentifier) {
+       char    localeCString[kLocaleIdentifierCStringMax];
+               if ( CFStringGetCString(canonicalIdentifier, localeCString,  sizeof(localeCString), kCFStringEncodingASCII) ) {
+                       UErrorCode      icuStatus = U_ZERO_ERROR;
+                       int32_t         languagelength;
+                       char            searchString[ULOC_LANG_CAPACITY + ULOC_FULLNAME_CAPACITY];
+                       
+                       languagelength = uloc_getLanguage( localeCString, searchString, ULOC_LANG_CAPACITY, &icuStatus );
+                       if ( U_SUCCESS(icuStatus) && languagelength > 0 ) {
+                               // OK, here we have at least a language code, check for other components in order
+                               LocaleToLegacyCodes                     searchEntry = { (const char *)searchString, 0, 0, 0 };
+                               const LocaleToLegacyCodes *     foundEntryPtr;
+                               int32_t                                         componentLength;
+                               char                                            componentString[ULOC_FULLNAME_CAPACITY];
+                               
+                               languagelength = strlen(searchString);  // in case it got truncated
+                               icuStatus = U_ZERO_ERROR;
+                               componentLength = uloc_getScript( localeCString, componentString, sizeof(componentString), &icuStatus );
+                               if ( U_FAILURE(icuStatus) || componentLength == 0 ) {
+                                       icuStatus = U_ZERO_ERROR;
+                                       componentLength = uloc_getCountry( localeCString, componentString, sizeof(componentString), &icuStatus );
+                                       if ( U_FAILURE(icuStatus) || componentLength == 0 ) {
+                                               icuStatus = U_ZERO_ERROR;
+                                               componentLength = uloc_getVariant( localeCString, componentString, sizeof(componentString), &icuStatus );
+                                               if ( U_FAILURE(icuStatus) ) {
+                                                       componentLength = 0;
+                                               }
+                                       }
+                               }
+                               
+                               // Append whichever other component we first found
+                               if (componentLength > 0) {
+                                       strlcat(searchString, "_", sizeof(searchString));
+                                       strlcat(searchString, componentString, sizeof(searchString));
+                               }
+                               
+                               // Search
+                               foundEntryPtr = (const LocaleToLegacyCodes *)bsearch( &searchEntry, localeToLegacyCodes, kNumLocaleToLegacyCodes, sizeof(LocaleToLegacyCodes), CompareLocaleToLegacyCodesEntries );
+                               if (foundEntryPtr == NULL && (int32_t) strlen(searchString) > languagelength) {
+                                       // truncate to language al;one and try again
+                                       searchString[languagelength] = 0;
+                                       foundEntryPtr = (const LocaleToLegacyCodes *)bsearch( &searchEntry, localeToLegacyCodes, kNumLocaleToLegacyCodes, sizeof(LocaleToLegacyCodes), CompareLocaleToLegacyCodesEntries );
+                               }
+
+                               // If found a matching entry, return requested values
+                               if (foundEntryPtr) {
+                                       returnValue = true;
+                                       if (langCode)           *langCode               = foundEntryPtr->langCode;
+                                       if (regCode)            *regCode                = foundEntryPtr->regCode;
+                                       if (stringEncoding)     *stringEncoding = foundEntryPtr->encoding;
+                                       if (scriptCode) {
+                                               // map CFStringEncoding to ScriptCode
+                                               if (foundEntryPtr->encoding < 33/*kCFStringEncodingMacSymbol*/) {
+                                                       *scriptCode     = foundEntryPtr->encoding;
+                                               } else {
+                                                       switch (foundEntryPtr->encoding) {
+                                                               case 0x8C/*kCFStringEncodingMacFarsi*/:         *scriptCode     = 4/*smArabic*/; break;
+                                                               case 0x98/*kCFStringEncodingMacUkrainian*/:     *scriptCode     = 7/*smCyrillic*/; break;
+                                                               case 0xEC/*kCFStringEncodingMacInuit*/:         *scriptCode     = 28/*smEthiopic*/; break;
+                                                               case 0xFC/*kCFStringEncodingMacVT100*/:         *scriptCode     = 32/*smUninterp*/; break;
+                                                               default:                                                                        *scriptCode     = 0/*smRoman*/; break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               CFRelease(canonicalIdentifier);
+       }
+       return returnValue;
+}
+
+static int CompareLocaleToLegacyCodesEntries( const void *entry1, const void *entry2 ) {
+       const char *    localeString1 = ((const LocaleToLegacyCodes *)entry1)->locale;
+       const char *    localeString2 = ((const LocaleToLegacyCodes *)entry2)->locale;
+       return strcmp(localeString1, localeString2);
+}
+
+
 CFDictionaryRef CFLocaleCreateComponentsFromLocaleIdentifier(CFAllocatorRef allocator, CFStringRef localeID) {
     char cLocaleID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
     char buffer[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
@@ -1778,7 +1810,7 @@ CFDictionaryRef CFLocaleCreateComponentsFromLocaleIdentifier(CFAllocatorRef allo
     if (U_SUCCESS(icuStatus) && length > 0)
     {
         CFStringRef string = CFStringCreateWithBytes(allocator, (UInt8 *)buffer, length, kCFStringEncodingASCII, true);
-        CFDictionaryAddValue(working, kCFLocaleLanguageCode, string);
+        CFDictionaryAddValue(working, kCFLocaleLanguageCodeKey, string);
         CFRelease(string);
     }
     icuStatus = U_ZERO_ERROR;
@@ -1787,7 +1819,7 @@ CFDictionaryRef CFLocaleCreateComponentsFromLocaleIdentifier(CFAllocatorRef allo
     if (U_SUCCESS(icuStatus) && length > 0)
     {
         CFStringRef string = CFStringCreateWithBytes(allocator, (UInt8 *)buffer, length, kCFStringEncodingASCII, true);
-        CFDictionaryAddValue(working, kCFLocaleScriptCode, string);
+        CFDictionaryAddValue(working, kCFLocaleScriptCodeKey, string);
         CFRelease(string);
     }
     icuStatus = U_ZERO_ERROR;
@@ -1796,7 +1828,7 @@ CFDictionaryRef CFLocaleCreateComponentsFromLocaleIdentifier(CFAllocatorRef allo
     if (U_SUCCESS(icuStatus) && length > 0)
     {
         CFStringRef string = CFStringCreateWithBytes(allocator, (UInt8 *)buffer, length, kCFStringEncodingASCII, true);
-        CFDictionaryAddValue(working, kCFLocaleCountryCode, string);
+        CFDictionaryAddValue(working, kCFLocaleCountryCodeKey, string);
         CFRelease(string);
     }
     icuStatus = U_ZERO_ERROR;
@@ -1805,7 +1837,7 @@ CFDictionaryRef CFLocaleCreateComponentsFromLocaleIdentifier(CFAllocatorRef allo
     if (U_SUCCESS(icuStatus) && length > 0)
     {
         CFStringRef string = CFStringCreateWithBytes(allocator, (UInt8 *)buffer, length, kCFStringEncodingASCII, true);
-        CFDictionaryAddValue(working, kCFLocaleVariantCode, string);
+        CFDictionaryAddValue(working, kCFLocaleVariantCodeKey, string);
         CFRelease(string);
     }
     icuStatus = U_ZERO_ERROR;
@@ -1840,58 +1872,62 @@ CFDictionaryRef CFLocaleCreateComponentsFromLocaleIdentifier(CFAllocatorRef allo
     return result;
 }
 
-typedef struct __AppendContext
-{
-    char                separator;
-    CFMutableStringRef  working;
-} __AppendContext;
-
-static void __AppendKeywords(const void *k, const void *v, void *c)
-{
-    __AppendContext *context = (__AppendContext *) c;
-    CFStringRef key = (CFStringRef) k;
-    CFStringRef value = (CFStringRef) v;
-    if (CFEqual(key, kCFLocaleLanguageCode) || CFEqual(key, kCFLocaleScriptCode) || CFEqual(key, kCFLocaleCountryCode) || CFEqual(key, kCFLocaleVariantCode))
-        return;
-    CFStringAppendFormat(context->working, NULL, CFSTR("%c%@%c%@"), context->separator, key, ULOC_KEYWORD_ASSIGN, value);
-    context->separator = ULOC_KEYWORD_ITEM_SEPARATOR;
+static char *__CStringFromString(CFStringRef str) {
+    if (!str) return NULL;
+    CFRange rg = CFRangeMake(0, CFStringGetLength(str));
+    CFIndex neededLength = 0;
+    CFStringGetBytes(str, rg, kCFStringEncodingASCII, (UInt8)'?', false, NULL, 0, &neededLength);
+    char *buf = (char *)malloc(neededLength + 1);
+    CFStringGetBytes(str, rg, kCFStringEncodingASCII, (UInt8)'?', false, (uint8_t *)buf, neededLength, &neededLength);
+    buf[neededLength] = '\0';
+    return buf;
 }
 
 CFStringRef CFLocaleCreateLocaleIdentifierFromComponents(CFAllocatorRef allocator, CFDictionaryRef dictionary) {
-    CFMutableStringRef working = CFStringCreateMutable(allocator, 0);
-    CFStringRef value = NULL;
-    bool country = false;
-    __AppendContext context = {ULOC_KEYWORD_SEPARATOR, working};
-    
-    if ((value = (CFStringRef) CFDictionaryGetValue(dictionary, kCFLocaleLanguageCode)))
-    {
-        CFStringAppend(working, value);
+    CFIndex cnt = CFDictionaryGetCount(dictionary);
+    STACK_BUFFER_DECL(CFStringRef, values, cnt);
+    STACK_BUFFER_DECL(CFStringRef, keys, cnt);
+    CFDictionaryGetKeysAndValues(dictionary, (const void **)keys, (const void **)values);
+
+    char *language = NULL, *script = NULL, *country = NULL, *variant = NULL;
+    for (CFIndex idx = 0; idx < cnt; idx++) {
+       if (CFEqual(kCFLocaleLanguageCodeKey, keys[idx])) {
+           language = __CStringFromString(values[idx]);
+           keys[idx] = NULL;
+       } else if (CFEqual(kCFLocaleScriptCodeKey, keys[idx])) {
+           script = __CStringFromString(values[idx]);
+           keys[idx] = NULL;
+       } else if (CFEqual(kCFLocaleCountryCodeKey, keys[idx])) {
+           country = __CStringFromString(values[idx]);
+           keys[idx] = NULL;
+       } else if (CFEqual(kCFLocaleVariantCodeKey, keys[idx])) {
+           variant = __CStringFromString(values[idx]);
+           keys[idx] = NULL;
+       }
     }
 
-    if ((value = (CFStringRef) CFDictionaryGetValue(dictionary, kCFLocaleScriptCode)))
-    {
-        CFStringAppendFormat(working, NULL, CFSTR("_%@"), value);
-    }
-    
-    if ((value = (CFStringRef) CFDictionaryGetValue(dictionary, kCFLocaleCountryCode)))
-    {
-        CFStringAppendFormat(working, NULL, CFSTR("_%@"), value);
-        country = true;
-    }
-    
-    if ((value = (CFStringRef) CFDictionaryGetValue(dictionary, kCFLocaleVariantCode)))
-    {
-        if (!country)
-            CFStringAppend(working, CFSTR("_"));
-        CFStringAppendFormat(working, NULL, CFSTR("_%@"), value);
+    char *buf1 = NULL; // (|L)(|_S)(|_C|_C_V|__V)
+    asprintf(&buf1, "%s%s%s%s%s%s%s", language ? language : "", script ? "_" : "", script ? script : "", (country || variant ? "_" : ""), country ? country : "", variant ? "_" : "", variant ? variant : "");
+
+    char cLocaleID[2 * ULOC_FULLNAME_CAPACITY + 2 * ULOC_KEYWORD_AND_VALUES_CAPACITY];
+    strlcpy(cLocaleID, buf1, sizeof(cLocaleID));
+    free(language);
+    free(script);
+    free(country);
+    free(variant);
+    free(buf1);
+
+    for (CFIndex idx = 0; idx < cnt; idx++) {
+       if (keys[idx]) {
+           char *key = __CStringFromString(keys[idx]);
+           char *value = __CStringFromString(values[idx]);
+           UErrorCode status = U_ZERO_ERROR;
+           uloc_setKeywordValue(key, value, cLocaleID, sizeof(cLocaleID), &status);
+           free(key);
+           free(value);
+       }
     }
-    
-    // Now iterate through any remaining entries and append as keywords
-    CFDictionaryApplyFunction(dictionary, __AppendKeywords, &context);
-    
-    // Convert to immutable string and return
-    CFStringRef result = (CFStringRef)CFStringCreateCopy(allocator, working);
-    CFRelease(working);
-    return result;
+
+    return CFStringCreateWithCString(allocator, cLocaleID, kCFStringEncodingASCII);
 }
 
diff --git a/CFLocaleInternal.h b/CFLocaleInternal.h
new file mode 100644 (file)
index 0000000..ec9ba42
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*     
+ CFLocaleInternal.h
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+ */
+
+/*
+ This file is for the use of the CoreFoundation project only.
+ */
+
+#include <CoreFoundation/CFString.h>
+
+CF_EXPORT CFStringRef const kCFLocaleAlternateQuotationBeginDelimiterKey;
+CF_EXPORT CFStringRef const kCFLocaleAlternateQuotationEndDelimiterKey;
+CF_EXPORT CFStringRef const kCFLocaleQuotationBeginDelimiterKey;
+CF_EXPORT CFStringRef const kCFLocaleQuotationEndDelimiterKey;
+CF_EXPORT CFStringRef const kCFLocaleCalendarIdentifierKey; // ***
+CF_EXPORT CFStringRef const kCFLocaleCalendarKey;
+CF_EXPORT CFStringRef const kCFLocaleCollationIdentifierKey; // ***
+CF_EXPORT CFStringRef const kCFLocaleCollatorIdentifierKey;
+CF_EXPORT CFStringRef const kCFLocaleCountryCodeKey;
+CF_EXPORT CFStringRef const kCFLocaleCurrencyCodeKey; // ***
+CF_EXPORT CFStringRef const kCFLocaleCurrencySymbolKey;
+CF_EXPORT CFStringRef const kCFLocaleDecimalSeparatorKey;
+CF_EXPORT CFStringRef const kCFLocaleExemplarCharacterSetKey;
+CF_EXPORT CFStringRef const kCFLocaleGroupingSeparatorKey;
+CF_EXPORT CFStringRef const kCFLocaleIdentifierKey;
+CF_EXPORT CFStringRef const kCFLocaleLanguageCodeKey;
+CF_EXPORT CFStringRef const kCFLocaleMeasurementSystemKey;
+CF_EXPORT CFStringRef const kCFLocaleScriptCodeKey;
+CF_EXPORT CFStringRef const kCFLocaleUsesMetricSystemKey;
+CF_EXPORT CFStringRef const kCFLocaleVariantCodeKey;
+
+CF_EXPORT CFStringRef const kCFDateFormatterAMSymbolKey;
+CF_EXPORT CFStringRef const kCFDateFormatterCalendarKey;
+CF_EXPORT CFStringRef const kCFDateFormatterCalendarIdentifierKey;
+CF_EXPORT CFStringRef const kCFDateFormatterDefaultDateKey;
+CF_EXPORT CFStringRef const kCFDateFormatterDefaultFormatKey;
+CF_EXPORT CFStringRef const kCFDateFormatterDoesRelativeDateFormattingKey;
+CF_EXPORT CFStringRef const kCFDateFormatterEraSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterGregorianStartDateKey;
+CF_EXPORT CFStringRef const kCFDateFormatterIsLenientKey;
+CF_EXPORT CFStringRef const kCFDateFormatterLongEraSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterMonthSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterPMSymbolKey;
+CF_EXPORT CFStringRef const kCFDateFormatterQuarterSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterShortMonthSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterShortQuarterSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterShortStandaloneMonthSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterShortStandaloneQuarterSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterShortStandaloneWeekdaySymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterShortWeekdaySymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterStandaloneMonthSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterStandaloneQuarterSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterStandaloneWeekdaySymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterTimeZoneKey;
+CF_EXPORT CFStringRef const kCFDateFormatterTwoDigitStartDateKey;
+CF_EXPORT CFStringRef const kCFDateFormatterVeryShortMonthSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterVeryShortStandaloneMonthSymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterVeryShortWeekdaySymbolsKey;
+CF_EXPORT CFStringRef const kCFDateFormatterWeekdaySymbolsKey;
+
+CF_EXPORT CFStringRef const kCFNumberFormatterAlwaysShowDecimalSeparatorKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterCurrencyCodeKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterCurrencyDecimalSeparatorKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterCurrencyGroupingSeparatorKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterCurrencySymbolKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterDecimalSeparatorKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterDefaultFormatKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterExponentSymbolKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterFormatWidthKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterGroupingSeparatorKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterGroupingSizeKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterInfinitySymbolKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterInternationalCurrencySymbolKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterIsLenientKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterMaxFractionDigitsKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterMaxIntegerDigitsKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterMaxSignificantDigitsKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterMinFractionDigitsKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterMinIntegerDigitsKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterMinSignificantDigitsKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterMinusSignKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterMultiplierKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterNaNSymbolKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterNegativePrefixKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterNegativeSuffixKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterPaddingCharacterKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterPaddingPositionKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterPerMillSymbolKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterPercentSymbolKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterPlusSignKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterPositivePrefixKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterPositiveSuffixKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterRoundingIncrementKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterRoundingModeKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterSecondaryGroupingSizeKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterUseGroupingSeparatorKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterUseSignificantDigitsKey;
+CF_EXPORT CFStringRef const kCFNumberFormatterZeroSymbolKey;
+
+CF_EXPORT CFStringRef const kCFCalendarIdentifierGregorian;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierBuddhist;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierJapanese;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierIslamic;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierIslamicCivil;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierHebrew;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierChinese;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierRepublicOfChina;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierPersian;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierIndian;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierISO8601;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierCoptic;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierEthiopicAmeteMihret;
+CF_EXPORT CFStringRef const kCFCalendarIdentifierEthiopicAmeteAlem;
+
+
diff --git a/CFLocaleKeys.m b/CFLocaleKeys.m
new file mode 100644 (file)
index 0000000..7d6c8a3
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+
+@class NSString;
+
+NSString * const kCFLocaleAlternateQuotationBeginDelimiterKey = @"kCFLocaleAlternateQuotationBeginDelimiterKey";
+NSString * const kCFLocaleAlternateQuotationEndDelimiterKey = @"kCFLocaleAlternateQuotationEndDelimiterKey";
+NSString * const kCFLocaleQuotationBeginDelimiterKey = @"kCFLocaleQuotationBeginDelimiterKey";
+NSString * const kCFLocaleQuotationEndDelimiterKey = @"kCFLocaleQuotationEndDelimiterKey";
+NSString * const kCFLocaleCalendarIdentifierKey = @"calendar"; // ***
+NSString * const kCFLocaleCalendarKey = @"kCFLocaleCalendarKey";
+NSString * const kCFLocaleCollationIdentifierKey = @"collation"; // ***
+NSString * const kCFLocaleCollatorIdentifierKey = @"kCFLocaleCollatorIdentifierKey";
+NSString * const kCFLocaleCountryCodeKey = @"kCFLocaleCountryCodeKey";
+NSString * const kCFLocaleCurrencyCodeKey = @"currency"; // ***
+NSString * const kCFLocaleCurrencySymbolKey = @"kCFLocaleCurrencySymbolKey";
+NSString * const kCFLocaleDecimalSeparatorKey = @"kCFLocaleDecimalSeparatorKey";
+NSString * const kCFLocaleExemplarCharacterSetKey = @"kCFLocaleExemplarCharacterSetKey";
+NSString * const kCFLocaleGroupingSeparatorKey = @"kCFLocaleGroupingSeparatorKey";
+NSString * const kCFLocaleIdentifierKey = @"kCFLocaleIdentifierKey";
+NSString * const kCFLocaleLanguageCodeKey = @"kCFLocaleLanguageCodeKey";
+NSString * const kCFLocaleMeasurementSystemKey = @"kCFLocaleMeasurementSystemKey";
+NSString * const kCFLocaleScriptCodeKey = @"kCFLocaleScriptCodeKey";
+NSString * const kCFLocaleUsesMetricSystemKey = @"kCFLocaleUsesMetricSystemKey";
+NSString * const kCFLocaleVariantCodeKey = @"kCFLocaleVariantCodeKey";
+
+NSString * const kCFDateFormatterAMSymbolKey = @"kCFDateFormatterAMSymbolKey";
+NSString * const kCFDateFormatterCalendarKey = @"kCFDateFormatterCalendarKey";
+NSString * const kCFDateFormatterCalendarIdentifierKey = @"kCFDateFormatterCalendarIdentifierKey";
+NSString * const kCFDateFormatterDefaultDateKey = @"kCFDateFormatterDefaultDateKey";
+NSString * const kCFDateFormatterDefaultFormatKey = @"kCFDateFormatterDefaultFormatKey";
+NSString * const kCFDateFormatterDoesRelativeDateFormattingKey = @"kCFDateFormatterDoesRelativeDateFormattingKey";
+NSString * const kCFDateFormatterEraSymbolsKey = @"kCFDateFormatterEraSymbolsKey";
+NSString * const kCFDateFormatterGregorianStartDateKey = @"kCFDateFormatterGregorianStartDateKey";
+NSString * const kCFDateFormatterIsLenientKey = @"kCFDateFormatterIsLenientKey";
+NSString * const kCFDateFormatterLongEraSymbolsKey = @"kCFDateFormatterLongEraSymbolsKey";
+NSString * const kCFDateFormatterMonthSymbolsKey = @"kCFDateFormatterMonthSymbolsKey";
+NSString * const kCFDateFormatterPMSymbolKey = @"kCFDateFormatterPMSymbolKey";
+NSString * const kCFDateFormatterQuarterSymbolsKey = @"kCFDateFormatterQuarterSymbolsKey";
+NSString * const kCFDateFormatterShortMonthSymbolsKey = @"kCFDateFormatterShortMonthSymbolsKey";
+NSString * const kCFDateFormatterShortQuarterSymbolsKey = @"kCFDateFormatterShortQuarterSymbolsKey";
+NSString * const kCFDateFormatterShortStandaloneMonthSymbolsKey = @"kCFDateFormatterShortStandaloneMonthSymbolsKey";
+NSString * const kCFDateFormatterShortStandaloneQuarterSymbolsKey = @"kCFDateFormatterShortStandaloneQuarterSymbolsKey";
+NSString * const kCFDateFormatterShortStandaloneWeekdaySymbolsKey = @"kCFDateFormatterShortStandaloneWeekdaySymbolsKey";
+NSString * const kCFDateFormatterShortWeekdaySymbolsKey = @"kCFDateFormatterShortWeekdaySymbolsKey";
+NSString * const kCFDateFormatterStandaloneMonthSymbolsKey = @"kCFDateFormatterStandaloneMonthSymbolsKey";
+NSString * const kCFDateFormatterStandaloneQuarterSymbolsKey = @"kCFDateFormatterStandaloneQuarterSymbolsKey";
+NSString * const kCFDateFormatterStandaloneWeekdaySymbolsKey = @"kCFDateFormatterStandaloneWeekdaySymbolsKey";
+NSString * const kCFDateFormatterTimeZoneKey = @"kCFDateFormatterTimeZoneKey";
+NSString * const kCFDateFormatterTwoDigitStartDateKey = @"kCFDateFormatterTwoDigitStartDateKey";
+NSString * const kCFDateFormatterVeryShortMonthSymbolsKey = @"kCFDateFormatterVeryShortMonthSymbolsKey";
+NSString * const kCFDateFormatterVeryShortStandaloneMonthSymbolsKey = @"kCFDateFormatterVeryShortStandaloneMonthSymbolsKey";
+NSString * const kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey = @"kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey";
+NSString * const kCFDateFormatterVeryShortWeekdaySymbolsKey = @"kCFDateFormatterVeryShortWeekdaySymbolsKey";
+NSString * const kCFDateFormatterWeekdaySymbolsKey = @"kCFDateFormatterWeekdaySymbolsKey";
+
+NSString * const kCFNumberFormatterAlwaysShowDecimalSeparatorKey = @"kCFNumberFormatterAlwaysShowDecimalSeparatorKey";
+NSString * const kCFNumberFormatterCurrencyCodeKey = @"kCFNumberFormatterCurrencyCodeKey";
+NSString * const kCFNumberFormatterCurrencyDecimalSeparatorKey = @"kCFNumberFormatterCurrencyDecimalSeparatorKey";
+NSString * const kCFNumberFormatterCurrencyGroupingSeparatorKey = @"kCFNumberFormatterCurrencyGroupingSeparatorKey";
+NSString * const kCFNumberFormatterCurrencySymbolKey = @"kCFNumberFormatterCurrencySymbolKey";
+NSString * const kCFNumberFormatterDecimalSeparatorKey = @"kCFNumberFormatterDecimalSeparatorKey";
+NSString * const kCFNumberFormatterDefaultFormatKey = @"kCFNumberFormatterDefaultFormatKey";
+NSString * const kCFNumberFormatterExponentSymbolKey = @"kCFNumberFormatterExponentSymbolKey";
+NSString * const kCFNumberFormatterFormatWidthKey = @"kCFNumberFormatterFormatWidthKey";
+NSString * const kCFNumberFormatterGroupingSeparatorKey = @"kCFNumberFormatterGroupingSeparatorKey";
+NSString * const kCFNumberFormatterGroupingSizeKey = @"kCFNumberFormatterGroupingSizeKey";
+NSString * const kCFNumberFormatterInfinitySymbolKey = @"kCFNumberFormatterInfinitySymbolKey";
+NSString * const kCFNumberFormatterInternationalCurrencySymbolKey = @"kCFNumberFormatterInternationalCurrencySymbolKey";
+NSString * const kCFNumberFormatterIsLenientKey = @"kCFNumberFormatterIsLenientKey";
+NSString * const kCFNumberFormatterMaxFractionDigitsKey = @"kCFNumberFormatterMaxFractionDigitsKey";
+NSString * const kCFNumberFormatterMaxIntegerDigitsKey = @"kCFNumberFormatterMaxIntegerDigitsKey";
+NSString * const kCFNumberFormatterMaxSignificantDigitsKey = @"kCFNumberFormatterMaxSignificantDigitsKey";
+NSString * const kCFNumberFormatterMinFractionDigitsKey = @"kCFNumberFormatterMinFractionDigitsKey";
+NSString * const kCFNumberFormatterMinIntegerDigitsKey = @"kCFNumberFormatterMinIntegerDigitsKey";
+NSString * const kCFNumberFormatterMinSignificantDigitsKey = @"kCFNumberFormatterMinSignificantDigitsKey";
+NSString * const kCFNumberFormatterMinusSignKey = @"kCFNumberFormatterMinusSignKey";
+NSString * const kCFNumberFormatterMultiplierKey = @"kCFNumberFormatterMultiplierKey";
+NSString * const kCFNumberFormatterNaNSymbolKey = @"kCFNumberFormatterNaNSymbolKey";
+NSString * const kCFNumberFormatterNegativePrefixKey = @"kCFNumberFormatterNegativePrefixKey";
+NSString * const kCFNumberFormatterNegativeSuffixKey = @"kCFNumberFormatterNegativeSuffixKey";
+NSString * const kCFNumberFormatterPaddingCharacterKey = @"kCFNumberFormatterPaddingCharacterKey";
+NSString * const kCFNumberFormatterPaddingPositionKey = @"kCFNumberFormatterPaddingPositionKey";
+NSString * const kCFNumberFormatterPerMillSymbolKey = @"kCFNumberFormatterPerMillSymbolKey";
+NSString * const kCFNumberFormatterPercentSymbolKey = @"kCFNumberFormatterPercentSymbolKey";
+NSString * const kCFNumberFormatterPlusSignKey = @"kCFNumberFormatterPlusSignKey";
+NSString * const kCFNumberFormatterPositivePrefixKey = @"kCFNumberFormatterPositivePrefixKey";
+NSString * const kCFNumberFormatterPositiveSuffixKey = @"kCFNumberFormatterPositiveSuffixKey";
+NSString * const kCFNumberFormatterRoundingIncrementKey = @"kCFNumberFormatterRoundingIncrementKey";
+NSString * const kCFNumberFormatterRoundingModeKey = @"kCFNumberFormatterRoundingModeKey";
+NSString * const kCFNumberFormatterSecondaryGroupingSizeKey = @"kCFNumberFormatterSecondaryGroupingSizeKey";
+NSString * const kCFNumberFormatterUseGroupingSeparatorKey = @"kCFNumberFormatterUseGroupingSeparatorKey";
+NSString * const kCFNumberFormatterUseSignificantDigitsKey = @"kCFNumberFormatterUseSignificantDigitsKey";
+NSString * const kCFNumberFormatterZeroSymbolKey = @"kCFNumberFormatterZeroSymbolKey";
+
+NSString * const kCFCalendarIdentifierGregorian = @"gregorian";
+NSString * const kCFCalendarIdentifierBuddhist = @"buddhist";
+NSString * const kCFCalendarIdentifierJapanese = @"japanese";
+NSString * const kCFCalendarIdentifierIslamic = @"islamic";
+NSString * const kCFCalendarIdentifierIslamicCivil = @"islamic-civil";
+NSString * const kCFCalendarIdentifierHebrew = @"hebrew";
+NSString * const kCFCalendarIdentifierChinese = @"chinese";
+NSString * const kCFCalendarIdentifierRepublicOfChina = @"roc";
+NSString * const kCFCalendarIdentifierPersian = @"persian";
+NSString * const kCFCalendarIdentifierIndian = @"indian";
+NSString * const kCFCalendarIdentifierISO8601 = @"";
+NSString * const kCFCalendarIdentifierCoptic = @"coptic";
+NSString * const kCFCalendarIdentifierEthiopicAmeteMihret = @"ethiopic";
+NSString * const kCFCalendarIdentifierEthiopicAmeteAlem = @"ethiopic-amete-alem";
index 07004b95e04c67353a55d1c6d82507c4c4833aab..a9537f22c38daef53af046bfd80934147f86eaf2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFLogUtilities.h
-       Copyright (c) 2004-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2004-2009, Apple Inc. All rights reserved.
 */
 
 /*
index dfde9dd8b2b9fd2c1a9c525181ef25552167330c..c16a76471ea48c5a93f5d21a62d00d6082c152ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFMachPort.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
-/* 
-   [The following dissertation was written mostly for the
-   benefit of open source developers.]
-
-   Writing a run loop source can be a tricky business, but
-   for CFMachPort that part is relatively straightforward.
-   Thus, it makes a good example for study.  Particularly
-   interesting for examination is the process of caching
-   the objects in a non-retaining cache, the invalidation
-   and deallocation sequences, locking for thread-safety,
-   and how the invalidation callback is used.
-
-   CFMachPort is a version 1 CFRunLoopSource, implemented
-   by a few functions.  See CFMachPortCreateRunLoopSource()
-   for details on how the run loop source is setup.  Note
-   how the source is kept track of by the CFMachPort, so
-   that it can be returned again and again from that function.
-   This helps not only reduce the amount of memory expended
-   in run loop source objects, but eliminates redundant
-   registrations with the run loop and the excess time and
-   memory that would consume.  It also allows the CFMachPort
-   to propogate its own invalidation to the run loop source
-   representing it.
-
-   CFMachPortCreateWithPort() is the funnel point for the
-   creation of CFMachPort instances.  The cache is first
-   probed to see if an instance with that port is already
-   available, and return that.  The object is next allocated
-   and mostly initialized, before it is registered for death
-   notification.  This is because cleaning up the memory is
-   simpler than trying to get rid of the registration if
-   memory allocation later fails.  The new object must be at
-   least partially initialized (into a harmless state) so
-   that it can be safely invalidated/deallocated if something
-   fails later in creation.  Any object allocated with
-   _CFRuntimeCreateInstance() may only be disposed by using
-   CFRelease() (never CFAllocatorDeallocate!) so the class
-   deallocation function __CFMachPortDeallocate() must be
-   able to handle that, and initializing the object to have
-   NULL fields and whatnot makes that possible.  The creation
-   eventually inserts the new object in the cache.
-
-   A CFMachPort may be explicitly invalidated, autoinvalidated
-   due to the death of the port (that process is not discussed
-   further here), or invalidated as part of the deallocation
-   process when the last reference is released.  For
-   convenience, in all cases this is done through
-   CFMachPortInvalidate().  To prevent the CFMachPort from
-   being freed in mid-function due to the callouts, the object
-   is retained at the beginning of the function.  But if this
-   invalidation is due to the object being deallocated, a
-   retain and then release at the end of the function would
-   cause a recursive call to __CFMachPortDeallocate().  The
-   retain protection should be immaterial though at that stage.
-   Invalidation also removes the object from the cache; though
-   the object itself is not yet destroyed, invalidation makes
-   it "useless".
-   
-   The best way to learn about the locking is to look through
-   the code -- it's fairly straightforward.  The one thing
-   worth calling attention to is how locks must be unlocked
-   before invoking any user-defined callout function, and
-   usually retaken after it returns.  This supports reentrancy
-   (which is distinct from thread-safety).
-
-   The invalidation callback, if one has been set, is called
-   at invalidation time, but before the object has been torn
-   down so that the port and other properties may be retrieved
-   from the object in the callback.  Note that if the callback
-   is attempted to be set after the CFMachPort is invalid,
-   the function is simply called.  This helps with certain
-   race conditions where the invalidation notification might
-   be lost.  Only the owner/creator of a CFMachPort should
-   really be setting the invalidation callback.
-
-   Now, the CFMachPort is not retained/released around all
-   callouts, but the callout may release the last reference.
-   Also, sometimes it is friendly to retain/release the
-   user-defined "info" around callouts, so that clients
-   don't have to worry about that.  These may be some things
-   to think about in the future, but is usually overkill.
-
-   In general, with higher level functionalities in the system,
-   it isn't even possible for a process to fork() and the child
-   not exec(), but continue running, since the higher levels
-   have done one-time initializations that aren't going to
-   happen again.
-
-       - Chris Kane
-
-*/
-
 #include <CoreFoundation/CFMachPort.h>
 #include <CoreFoundation/CFRunLoop.h>
-#include <CoreFoundation/CFDictionary.h>
-#include <CoreFoundation/CFByteOrder.h>
+#include <CoreFoundation/CFArray.h>
+#include <dispatch/dispatch.h>
+#include <libkern/OSAtomic.h>
 #include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <mach/notify.h>
-#include <unistd.h>
-#include "CFInternal.h"
 #include <dlfcn.h>
+#include "CFInternal.h"
+
+#define AVOID_WEAK_COLLECTIONS 1
 
-static CFSpinLock_t __CFAllMachPortsLock = CFSpinLockInit;
-static CFMutableDictionaryRef __CFAllMachPorts = NULL;
-static mach_port_t __CFNotifyRawMachPort = MACH_PORT_NULL;
-static CFMachPortRef __CFNotifyMachPort = NULL;
+#if !defined(AVOID_WEAK_COLLECTIONS)
+#import "CFPointerArray.h"
+#endif
+
+DISPATCH_HELPER_FUNCTIONS(port, CFMachPort)
+
+
+enum {
+    kCFMachPortStateReady = 0,
+    kCFMachPortStateInvalidating = 1,
+    kCFMachPortStateInvalid = 2,
+    kCFMachPortStateDeallocating = 3
+};
 
 struct __CFMachPort {
     CFRuntimeBase _base;
-    CFSpinLock_t _lock;
-    mach_port_t _port;                 /* immutable; invalidated */
-    mach_port_t _oldnotify;            /* immutable; invalidated */
-    CFRunLoopSourceRef _source;                /* immutable, once created; invalidated */
+    int32_t _state;
+    mach_port_t _port;            /* immutable */
+    dispatch_source_t _dsrc;
+    dispatch_source_t _dsrc2;
+    dispatch_semaphore_t _dsrc_sem;
+    dispatch_semaphore_t _dsrc2_sem;
     CFMachPortInvalidationCallBack _icallout;
-    CFMachPortCallBack _callout;       /* immutable */
-    CFMachPortContext _context;                /* immutable; invalidated */
+    CFRunLoopSourceRef _source;   /* immutable, once created */
+    CFMachPortCallBack _callout;  /* immutable */
+    CFMachPortContext _context;   /* immutable */
 };
 
-/* Bit 0 in the base reserved bits is used for invalid state */
 /* Bit 1 in the base reserved bits is used for has-receive-ref state */
 /* Bit 2 in the base reserved bits is used for has-send-ref state */
-/* Bit 3 in the base reserved bits is used for is-deallocing state */
-
-CF_INLINE Boolean __CFMachPortIsValid(CFMachPortRef mp) {
-    return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 0, 0);
-}
-
-CF_INLINE void __CFMachPortSetValid(CFMachPortRef mp) {
-    __CFBitfieldSetValue(((CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 0, 0, 1);
-}
-
-CF_INLINE void __CFMachPortUnsetValid(CFMachPortRef mp) {
-    __CFBitfieldSetValue(((CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 0, 0, 0);
-}
+/* Bit 3 in the base reserved bits is used for has-send-ref2 state */
 
 CF_INLINE Boolean __CFMachPortHasReceive(CFMachPortRef mp) {
     return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 1, 1);
@@ -177,74 +84,20 @@ CF_INLINE void __CFMachPortSetHasSend(CFMachPortRef mp) {
     __CFBitfieldSetValue(((CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 2, 2, 1);
 }
 
-CF_INLINE Boolean __CFMachPortIsDeallocing(CFMachPortRef mp) {
+CF_INLINE Boolean __CFMachPortHasSend2(CFMachPortRef mp) {
     return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 3, 3);
 }
 
-CF_INLINE void __CFMachPortSetIsDeallocing(CFMachPortRef mp) {
+CF_INLINE void __CFMachPortSetHasSend2(CFMachPortRef mp) {
     __CFBitfieldSetValue(((CFRuntimeBase *)mp)->_cfinfo[CF_INFO_BITS], 3, 3, 1);
 }
 
-CF_INLINE void __CFMachPortLock(CFMachPortRef mp) {
-    __CFSpinLock(&(mp->_lock));
+CF_INLINE Boolean __CFMachPortIsValid(CFMachPortRef mp) {
+    return kCFMachPortStateReady == mp->_state;
 }
 
-CF_INLINE void __CFMachPortUnlock(CFMachPortRef mp) {
-    __CFSpinUnlock(&(mp->_lock));
-}
 
 void _CFMachPortInstallNotifyPort(CFRunLoopRef rl, CFStringRef mode) {
-    CFRunLoopSourceRef source;
-    if (NULL == __CFNotifyMachPort) return;
-    source = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, __CFNotifyMachPort, -1000);
-    CFRunLoopAddSource(rl, source, mode);
-    CFRelease(source);
-}
-
-static void __CFNotifyDeadMachPort(CFMachPortRef port, void *msg, CFIndex size, void *info) {
-    mach_msg_header_t *header = (mach_msg_header_t *)msg;
-    mach_port_t dead_port = MACH_PORT_NULL;
-    if (header && header->msgh_id == MACH_NOTIFY_DEAD_NAME) {
-       dead_port = ((mach_dead_name_notification_t *)msg)->not_port;
-       if (((mach_dead_name_notification_t *)msg)->NDR.int_rep != NDR_record.int_rep) {
-           dead_port = CFSwapInt32(dead_port); 
-       }
-    } else if (header && header->msgh_id == MACH_NOTIFY_PORT_DELETED) {
-       dead_port = ((mach_port_deleted_notification_t *)msg)->not_port;
-       if (((mach_port_deleted_notification_t *)msg)->NDR.int_rep != NDR_record.int_rep) {
-           dead_port = CFSwapInt32(dead_port); 
-       }
-    } else {
-       return;
-    }
-
-    CFMachPortRef existing;
-    /* If the CFMachPort has already been invalidated, it won't be found here. */
-    __CFSpinLock(&__CFAllMachPortsLock);
-    if (NULL != __CFAllMachPorts && CFDictionaryGetValueIfPresent(__CFAllMachPorts, (void *)(uintptr_t)dead_port, (const void **)&existing)) {
-       CFDictionaryRemoveValue(__CFAllMachPorts, (void *)(uintptr_t)dead_port);
-       CFRetain(existing);
-       __CFSpinUnlock(&__CFAllMachPortsLock);
-       __CFMachPortLock(existing);
-       mach_port_t old_port = existing->_oldnotify;
-       existing->_oldnotify = MACH_PORT_NULL;
-       __CFMachPortUnlock(existing);
-       if (MACH_PORT_NULL != old_port) {
-           header->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0) | MACH_MSGH_BITS_COMPLEX;
-           header->msgh_local_port = MACH_PORT_NULL;
-           header->msgh_remote_port = old_port;
-           mach_msg(header, MACH_SEND_MSG, header->msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-       }
-       CFMachPortInvalidate(existing);
-       CFRelease(existing);
-    } else {
-       __CFSpinUnlock(&__CFAllMachPortsLock);
-    }
-
-    if (header && header->msgh_id == MACH_NOTIFY_DEAD_NAME) {
-       /* Delete port reference we got for this notification */
-       mach_port_deallocate(mach_task_self(), dead_port);
-    }
 }
 
 static Boolean __CFMachPortEqual(CFTypeRef cf1, CFTypeRef cf2) {
@@ -254,49 +107,184 @@ static Boolean __CFMachPortEqual(CFTypeRef cf1, CFTypeRef cf2) {
 }
 
 static CFHashCode __CFMachPortHash(CFTypeRef cf) {
-    CHECK_FOR_FORK();
     CFMachPortRef mp = (CFMachPortRef)cf;
     return (CFHashCode)mp->_port;
 }
 
 static CFStringRef __CFMachPortCopyDescription(CFTypeRef cf) {
     CFMachPortRef mp = (CFMachPortRef)cf;
-    CFStringRef result;
-    const char *locked;
     CFStringRef contextDesc = NULL;
-    locked = mp->_lock ? "Yes" : "No";
     if (NULL != mp->_context.info && NULL != mp->_context.copyDescription) {
-       contextDesc = mp->_context.copyDescription(mp->_context.info);
+        contextDesc = mp->_context.copyDescription(mp->_context.info);
     }
     if (NULL == contextDesc) {
-       contextDesc = CFStringCreateWithFormat(CFGetAllocator(mp), NULL, CFSTR("<CFMachPort context %p>"), mp->_context.info);
+        contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFMachPort context %p>"), mp->_context.info);
     }
-    void *addr = mp->_callout;
     Dl_info info;
+    void *addr = mp->_callout;
     const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
-    result = CFStringCreateWithFormat(CFGetAllocator(mp), NULL, CFSTR("<CFMachPort %p [%p]>{locked = %s, valid = %s, port = %p, source = %p, callout = %s (%p), context = %@}"), cf, CFGetAllocator(mp), locked, (__CFMachPortIsValid(mp) ? "Yes" : "No"), mp->_port, mp->_source, name, addr, (NULL != contextDesc ? contextDesc : CFSTR("<no description>")));
+    CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFMachPort %p [%p]>{valid = %s, port = %p, source = %p, callout = %s (%p), context = %@}"), cf, CFGetAllocator(mp), (__CFMachPortIsValid(mp) ? "Yes" : "No"), mp->_port, mp->_source, name, addr, contextDesc);
     if (NULL != contextDesc) {
-       CFRelease(contextDesc);
+        CFRelease(contextDesc);
     }
     return result;
 }
 
 static void __CFMachPortDeallocate(CFTypeRef cf) {
-    CHECK_FOR_FORK();
+    CHECK_FOR_FORK_RET();
     CFMachPortRef mp = (CFMachPortRef)cf;
-    __CFMachPortSetIsDeallocing(mp);
-    CFMachPortInvalidate(mp);
-    // MUST deallocate the send right FIRST if necessary,
-    // then the receive right if necessary.  Don't ask me why;
-    // if it's done in the other order the port will leak.
-    if (__CFMachPortHasSend(mp)) {
-       mach_port_mod_refs(mach_task_self(), mp->_port, MACH_PORT_RIGHT_SEND, -1);
+
+    // CFMachPortRef is invalid before we get here, except under GC
+    __block CFRunLoopSourceRef source = NULL;
+    __block Boolean wasReady = false;
+    void (^block)(void) = ^{
+            wasReady = (mp->_state == kCFMachPortStateReady);
+            if (wasReady) {
+                mp->_state = kCFMachPortStateInvalidating;
+                OSMemoryBarrier();
+                if (mp->_dsrc) {
+                    dispatch_source_cancel(mp->_dsrc);
+                    mp->_dsrc = NULL;
+                }
+                if (mp->_dsrc2) {
+                    dispatch_source_cancel(mp->_dsrc2);
+                    mp->_dsrc2 = NULL;
+                }
+                source = mp->_source;
+                mp->_source = NULL;
+            }
+        };
+    if (!__portSyncDispatchIsSafe(__portQueue())) {
+        block();
+    } else {
+        dispatch_sync(__portQueue(), block);
     }
-    if (__CFMachPortHasReceive(mp)) {
-       mach_port_mod_refs(mach_task_self(), mp->_port, MACH_PORT_RIGHT_RECEIVE, -1);
+    if (wasReady) {
+        CFMachPortInvalidationCallBack cb = mp->_icallout;
+        if (cb) {
+            cb(mp, mp->_context.info);
+        }
+        if (NULL != source) {
+            CFRunLoopSourceInvalidate(source);
+            CFRelease(source);
+        }
+        void *info = mp->_context.info;
+        mp->_context.info = NULL;
+        if (mp->_context.release) {
+            mp->_context.release(info);
+        }
+        mp->_state = kCFMachPortStateInvalid;
+        OSMemoryBarrier();
     }
+    mp->_state = kCFMachPortStateDeallocating;
+
+    // hand ownership of the port and semaphores to the block below
+    mach_port_t port = mp->_port;
+    dispatch_semaphore_t sem1 = mp->_dsrc_sem;
+    dispatch_semaphore_t sem2 = mp->_dsrc2_sem;
+    Boolean doSend2 = __CFMachPortHasSend2(mp), doSend = __CFMachPortHasSend(mp), doReceive = __CFMachPortHasReceive(mp);
+
+    dispatch_async(dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_LOW), ^{
+            if (sem1) {
+                dispatch_semaphore_wait(sem1, DISPATCH_TIME_FOREVER);
+                // immediate release is only safe if dispatch_semaphore_signal() does not touch the semaphore after doing the signal bit
+                dispatch_release(sem1);
+            }
+            if (sem2) {
+                dispatch_semaphore_wait(sem2, DISPATCH_TIME_FOREVER);
+                // immediate release is only safe if dispatch_semaphore_signal() does not touch the semaphore after doing the signal bit
+                dispatch_release(sem2);
+            }
+
+            // MUST deallocate the send right FIRST if necessary,
+            // then the receive right if necessary.  Don't ask me why;
+            // if it's done in the other order the port will leak.
+            if (doSend2) {
+                mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, -1);
+            }
+            if (doSend) {
+                mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, -1);
+            }
+            if (doReceive) {
+                mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
+            }
+        });
 }
 
+#if defined(AVOID_WEAK_COLLECTIONS)
+static CFMutableArrayRef __CFAllMachPorts = NULL;
+#else
+static __CFPointerArray *__CFAllMachPorts = nil;
+#endif
+
+static Boolean __CFMachPortCheck(mach_port_t port) {
+    mach_port_type_t type = 0;
+    kern_return_t ret = mach_port_type(mach_task_self(), port, &type);
+    return (KERN_SUCCESS != ret || (type & MACH_PORT_TYPE_DEAD_NAME)) ? false : true;
+}
+
+static void __CFMachPortChecker(Boolean fromTimer) { // only call on __portQueue()
+#if defined(AVOID_WEAK_COLLECTIONS)
+    for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) {
+        CFMachPortRef mp = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx);
+#else
+    for (CFIndex idx = 0, cnt = __CFAllMachPorts ? [__CFAllMachPorts count] : 0; idx < cnt; idx++) {
+        CFMachPortRef mp = (CFMachPortRef)[__CFAllMachPorts pointerAtIndex:idx];
+#endif
+        if (!mp) continue;
+        // second clause cleans no-longer-wanted CFMachPorts out of our strong table
+        if (!__CFMachPortCheck(mp->_port) || (!kCFUseCollectableAllocator && 1 == CFGetRetainCount(mp))) {
+            CFRunLoopSourceRef source = NULL;
+            Boolean wasReady = (mp->_state == kCFMachPortStateReady);
+            if (wasReady) {
+                mp->_state = kCFMachPortStateInvalidating;
+                OSMemoryBarrier();
+                if (mp->_dsrc) {
+                    dispatch_source_cancel(mp->_dsrc);
+                    mp->_dsrc = NULL;
+                }
+                if (mp->_dsrc2) {
+                    dispatch_source_cancel(mp->_dsrc2);
+                    mp->_dsrc2 = NULL;
+                }
+                source = mp->_source;
+                mp->_source = NULL;
+                CFRetain(mp);
+                dispatch_async(dispatch_get_main_queue(), ^{
+                        CFMachPortInvalidationCallBack cb = mp->_icallout;
+                        if (cb) {
+                            cb(mp, mp->_context.info);
+                        }
+                        if (NULL != source) {
+                            CFRunLoopSourceInvalidate(source);
+                            CFRelease(source);
+                        }
+                        void *info = mp->_context.info;
+                        mp->_context.info = NULL;
+                        if (mp->_context.release) {
+                            mp->_context.release(info);
+                        }
+                        // For hashing and equality purposes, cannot get rid of _port here
+                        mp->_state = kCFMachPortStateInvalid;
+                        OSMemoryBarrier();
+                        CFRelease(mp);
+                    });
+            }
+#if defined(AVOID_WEAK_COLLECTIONS)
+            CFArrayRemoveValueAtIndex(__CFAllMachPorts, idx);
+#else
+            [__CFAllMachPorts removePointerAtIndex:idx];
+#endif
+            idx--;
+            cnt--;
+        }
+    }
+#if !defined(AVOID_WEAK_COLLECTIONS)
+    [__CFAllMachPorts compact];
+#endif
+};
+
+
 static CFTypeID __kCFMachPortTypeID = _kCFRuntimeNotATypeID;
 
 static const CFRuntimeClass __CFMachPortClass = {
@@ -319,265 +307,330 @@ CFTypeID CFMachPortGetTypeID(void) {
     return __kCFMachPortTypeID;
 }
 
-CFMachPortRef CFMachPortCreate(CFAllocatorRef allocator, CFMachPortCallBack callout, CFMachPortContext *context, Boolean *shouldFreeInfo) {
-    CFMachPortRef result;
-    mach_port_t port;
-    kern_return_t ret;
-    if (shouldFreeInfo) *shouldFreeInfo = true;
-    ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
-    if (KERN_SUCCESS != ret) {
-       return NULL;
-    }
-    ret = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
-    if (KERN_SUCCESS != ret) {
-       mach_port_destroy(mach_task_self(), port);
-       return NULL;
-    }
-    result = CFMachPortCreateWithPort(allocator, port, callout, context, shouldFreeInfo);
-    if (NULL != result) {
-       __CFMachPortSetHasReceive(result);
-       __CFMachPortSetHasSend(result);
-    }
-    return result;
-}
-
 /* Note: any receive or send rights that the port contains coming in will
  * not be cleaned up by CFMachPort; it will increment and decrement
  * references on the port if the kernel ever allows that in the future,
  * but will not cleanup any references you got when you got the port. */
-CFMachPortRef CFMachPortCreateWithPort(CFAllocatorRef allocator, mach_port_t port, CFMachPortCallBack callout, CFMachPortContext *context, Boolean *shouldFreeInfo) {
-    CHECK_FOR_FORK();
-    CFMachPortRef memory;
-    SInt32 size;
-    Boolean didCreateNotifyPort = false;
-    CFRunLoopSourceRef source;
+CFMachPortRef _CFMachPortCreateWithPort2(CFAllocatorRef allocator, mach_port_t port, CFMachPortCallBack callout, CFMachPortContext *context, Boolean *shouldFreeInfo, Boolean deathWatch) {
     if (shouldFreeInfo) *shouldFreeInfo = true;
-    __CFSpinLock(&__CFAllMachPortsLock);
-    if (NULL != __CFAllMachPorts && CFDictionaryGetValueIfPresent(__CFAllMachPorts, (void *)(uintptr_t)port, (const void **)&memory)) {
-       CFRetain(memory);
-       __CFSpinUnlock(&__CFAllMachPortsLock);
-       return (CFMachPortRef)(memory);
-    }
-    size = sizeof(struct __CFMachPort) - sizeof(CFRuntimeBase);
-    memory = (CFMachPortRef)_CFRuntimeCreateInstance(allocator, __kCFMachPortTypeID, size, NULL);
-    if (NULL == memory) {
-       __CFSpinUnlock(&__CFAllMachPortsLock);
-       return NULL;
-    }
-    __CFMachPortUnsetValid(memory);
-    memory->_lock = CFSpinLockInit;
-    memory->_port = port;
-    memory->_source = NULL;
-    memory->_icallout = NULL;
-    memory->_context.info = NULL;
-    memory->_context.retain = NULL;
-    memory->_context.release = NULL;
-    memory->_context.copyDescription = NULL;
-    if (MACH_PORT_NULL == __CFNotifyRawMachPort) {
-       kern_return_t ret;
-       ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &__CFNotifyRawMachPort);
-       if (KERN_SUCCESS != ret) {
-           __CFSpinUnlock(&__CFAllMachPortsLock);
-           CFRelease(memory);
-           return NULL;
-       }
-       didCreateNotifyPort = true;
-    }
-    // Do not register for notifications on the notify port
-    if (MACH_PORT_NULL != __CFNotifyRawMachPort && port != __CFNotifyRawMachPort) {
-       mach_port_t old_port;
-       kern_return_t ret;
-       old_port = MACH_PORT_NULL;
-       ret = mach_port_request_notification(mach_task_self(), port, MACH_NOTIFY_DEAD_NAME, 0, __CFNotifyRawMachPort, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_port);
-       if (ret != KERN_SUCCESS) {
-           __CFSpinUnlock(&__CFAllMachPortsLock);
-           CFRelease(memory);
-           return NULL;
-       }
-       memory->_oldnotify = old_port;
+    CHECK_FOR_FORK_RET(NULL);
+
+    mach_port_type_t type = 0;
+    kern_return_t ret = mach_port_type(mach_task_self(), port, &type);
+    if (KERN_SUCCESS != ret || (type & ~(MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_SEND_ONCE|MACH_PORT_TYPE_RECEIVE|MACH_PORT_TYPE_DNREQUEST))) {
+        if (type & ~MACH_PORT_TYPE_DEAD_NAME) {
+            CFLog(kCFLogLevelError, CFSTR("*** CFMachPortCreateWithPort(): bad Mach port parameter (0x%lx) or unsupported mysterious kind of Mach port (%d, %ld)"), (unsigned long)port, ret, (unsigned long)type);
+        }
+        return NULL;
     }
-    __CFMachPortSetValid(memory);
-    memory->_callout = callout;
-    if (NULL != context) {
-       CF_WRITE_BARRIER_MEMMOVE(&memory->_context, context, sizeof(CFMachPortContext));
-       memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info;
+
+    __block CFMachPortRef mp = NULL;
+    dispatch_sync(__portQueue(), ^{
+            static Boolean portCheckerGoing = false;
+            if (!portCheckerGoing) {
+                uint64_t nanos = 63 * 1000 * 1000 * 1000ULL;
+                uint64_t leeway = 9;
+                (void)dispatch_source_timer_create(DISPATCH_TIMER_INTERVAL, nanos, leeway, NULL, __portQueue(), ^(dispatch_source_t source) {
+                        long e = 0, d = dispatch_source_get_error(source, &e);
+                        if (DISPATCH_ERROR_DOMAIN_POSIX == d && ECANCELED == e) {
+                            dispatch_release(source);
+                            return;
+                        }
+                        if (DISPATCH_ERROR_DOMAIN_NO_ERROR != d) {
+                            HALT;
+                        }
+                        __CFMachPortChecker(true);
+                    });
+                portCheckerGoing = true;
+            }
+
+#if defined(AVOID_WEAK_COLLECTIONS)
+            for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) {
+                CFMachPortRef p = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx);
+                if (p && p->_port == port) {
+                    CFRetain(p);
+                    mp = p;
+                    return;
+                }
+            }
+#else                
+            for (CFIndex idx = 0, cnt = __CFAllMachPorts ? [__CFAllMachPorts count] : 0; idx < cnt; idx++) {
+                CFMachPortRef p = (CFMachPortRef)[__CFAllMachPorts pointerAtIndex:idx];
+                if (p && p->_port == port) {
+                    CFRetain(p);
+                    mp = p;
+                    return;
+                }
+            }
+#endif
+
+            CFIndex size = sizeof(struct __CFMachPort) - sizeof(CFRuntimeBase);
+            CFMachPortRef memory = (CFMachPortRef)_CFRuntimeCreateInstance(allocator, CFMachPortGetTypeID(), size, NULL);
+            if (NULL == memory) {
+                return;
+            }
+            memory->_port = port;
+            memory->_dsrc = NULL;
+            memory->_dsrc2 = NULL;
+            memory->_dsrc_sem = NULL;
+            memory->_dsrc2_sem = NULL;
+            memory->_icallout = NULL;
+            memory->_source = NULL;
+            memory->_context.info = NULL;
+            memory->_context.retain = NULL;
+            memory->_context.release = NULL;
+            memory->_context.copyDescription = NULL;
+            memory->_callout = callout;
+            if (NULL != context) {
+                objc_memmove_collectable(&memory->_context, context, sizeof(CFMachPortContext));
+                memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info;
+            }
+            memory->_state = kCFMachPortStateReady;
+#if defined(AVOID_WEAK_COLLECTIONS)
+            if (!__CFAllMachPorts) __CFAllMachPorts = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+            CFArrayAppendValue(__CFAllMachPorts, memory);
+#else
+            if (!__CFAllMachPorts) __CFAllMachPorts = [[__CFPointerArray alloc] initWithOptions:(kCFUseCollectableAllocator ? CFPointerFunctionsZeroingWeakMemory : CFPointerFunctionsStrongMemory)];
+            [__CFAllMachPorts addPointer:memory];
+#endif
+            mp = memory;
+            if (shouldFreeInfo) *shouldFreeInfo = false;
+
+            if (type & MACH_PORT_TYPE_SEND_RIGHTS) {
+                memory->_dsrc = dispatch_source_machport_create(port, DISPATCH_MACHPORT_DEAD, NULL, __portQueue(), ^(dispatch_source_t source) {
+                        long e = 0, d = dispatch_source_get_error(source, &e);
+                        if (DISPATCH_ERROR_DOMAIN_MACH == d) {
+                            CFLog(kCFLogLevelError, CFSTR("*** ALERT: CFMachPort machport-dead dispatch source provided error (%d, %d)"), d, e);
+                            dispatch_release(source);
+                            return;
+                        }
+                        if (DISPATCH_ERROR_DOMAIN_NO_ERROR != d) {
+                            CFLog(kCFLogLevelError, CFSTR("*** ALERT: CFMachPort machport-dead dispatch source provided error (%d, %d)"), d, e);
+                            HALT;
+                        }
+                        __CFMachPortChecker(false);
+                    });
+            }
+            if ((type & MACH_PORT_TYPE_RECEIVE) && !(type & MACH_PORT_TYPE_SEND_RIGHTS)) {
+                memory->_dsrc2 = dispatch_source_machport_create(port, DISPATCH_MACHPORT_DELETED, NULL, __portQueue(), ^(dispatch_source_t source) {
+                        long e = 0, d = dispatch_source_get_error(source, &e);
+                        if (DISPATCH_ERROR_DOMAIN_MACH == d) {
+                            CFLog(kCFLogLevelError, CFSTR("*** ALERT: CFMachPort machport-deleted dispatch source provided error (%d, %d)"), d, e);
+                            dispatch_release(source);
+                            return;
+                        }
+                        if (DISPATCH_ERROR_DOMAIN_NO_ERROR != d) {
+                            CFLog(kCFLogLevelError, CFSTR("*** ALERT: CFMachPort machport-deleted dispatch source provided error (%d, %d)"), d, e);
+                            HALT;
+                        }
+                        __CFMachPortChecker(false);
+                    });
+            }
+            if (memory->_dsrc) {
+                dispatch_source_t source = memory->_dsrc; // put these in locals so they are fully copied into the block
+                dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+                memory->_dsrc_sem = sem;
+                dispatch_source_set_cancel_handler(memory->_dsrc, ^{ dispatch_semaphore_signal(sem); dispatch_release(source); });
+            }
+            if (memory->_dsrc2) {
+                dispatch_source_t source = memory->_dsrc2;
+                dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+                memory->_dsrc2_sem = sem;
+                dispatch_source_set_cancel_handler(memory->_dsrc2, ^{ dispatch_semaphore_signal(sem); dispatch_release(source); });
+            }
+        });
+    return mp;
+}
+
+CFMachPortRef CFMachPortCreateWithPort(CFAllocatorRef allocator, mach_port_t port, CFMachPortCallBack callout, CFMachPortContext *context, Boolean *shouldFreeInfo) {
+    return _CFMachPortCreateWithPort2(allocator, port, callout, context, shouldFreeInfo, true);
+}
+
+CFMachPortRef CFMachPortCreate(CFAllocatorRef allocator, CFMachPortCallBack callout, CFMachPortContext *context, Boolean *shouldFreeInfo) {
+    if (shouldFreeInfo) *shouldFreeInfo = true;
+    CHECK_FOR_FORK_RET(NULL);
+    mach_port_t port = MACH_PORT_NULL;
+    kern_return_t ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
+    if (KERN_SUCCESS == ret) {
+        ret = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
     }
-    if (NULL == __CFAllMachPorts) {
-       __CFAllMachPorts = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, NULL);
-       _CFDictionarySetCapacity(__CFAllMachPorts, 20);
+    if (KERN_SUCCESS != ret) {
+        if (MACH_PORT_NULL != port) mach_port_destroy(mach_task_self(), port);
+        return NULL;
     }
-    CFDictionaryAddValue(__CFAllMachPorts, (void *)(uintptr_t)port, memory);
-    __CFSpinUnlock(&__CFAllMachPortsLock);
-    if (didCreateNotifyPort) {
-       // __CFNotifyMachPort ends up in cache
-       CFMachPortRef mp = CFMachPortCreateWithPort(kCFAllocatorSystemDefault, __CFNotifyRawMachPort, __CFNotifyDeadMachPort, NULL, NULL);
-       __CFMachPortSetHasReceive(mp);
-       __CFNotifyMachPort = mp;
+    CFMachPortRef result = _CFMachPortCreateWithPort2(allocator, port, callout, context, shouldFreeInfo, true);
+    if (NULL == result) {
+        if (MACH_PORT_NULL != port) mach_port_destroy(mach_task_self(), port);
+        return NULL;
     }
-    if (NULL != __CFNotifyMachPort) {
-       // We do this so that it gets into each thread's run loop, since
-       // we don't know which run loop is the main thread's, and that's
-       // not necessarily the "right" one anyway.  This won't happen for
-       // the call which creates the __CFNotifyMachPort itself, but that's
-       // OK since it will happen in the invocation of this function
-       // from which that call was triggered.
-       source = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, __CFNotifyMachPort, -1000);
-       CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);
-       CFRelease(source);
+    __CFMachPortSetHasReceive(result);
+    __CFMachPortSetHasSend(result);
+    return result;
+}
+
+void CFMachPortInvalidate(CFMachPortRef mp) {
+    CHECK_FOR_FORK_RET();
+    CF_OBJC_FUNCDISPATCH0(CFMachPortGetTypeID(), void, mp, "invalidate");
+    __CFGenericValidateType(mp, CFMachPortGetTypeID());
+    CFRetain(mp);
+    __block CFRunLoopSourceRef source = NULL;
+    __block Boolean wasReady = false;
+    dispatch_sync(__portQueue(), ^{
+            wasReady = (mp->_state == kCFMachPortStateReady);
+            if (wasReady) {
+                mp->_state = kCFMachPortStateInvalidating;
+                OSMemoryBarrier();
+#if defined(AVOID_WEAK_COLLECTIONS)
+                for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) {
+                    CFMachPortRef p = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx);
+                    if (p == mp) {
+                        CFArrayRemoveValueAtIndex(__CFAllMachPorts, idx);
+                        break;
+                    }
+                }
+#else
+                for (CFIndex idx = 0, cnt = __CFAllMachPorts ? [__CFAllMachPorts count] : 0; idx < cnt; idx++) {
+                    CFMachPortRef p = (CFMachPortRef)[__CFAllMachPorts pointerAtIndex:idx];
+                    if (p == mp) {
+                        [__CFAllMachPorts removePointerAtIndex:idx];
+                        break;
+                    }
+                }
+#endif
+                if (mp->_dsrc) {
+                    dispatch_source_cancel(mp->_dsrc);
+                    mp->_dsrc = NULL;
+                }
+                if (mp->_dsrc2) {
+                    dispatch_source_cancel(mp->_dsrc2);
+                    mp->_dsrc2 = NULL;
+                }
+                source = mp->_source;
+                mp->_source = NULL;
+            }
+        });
+    if (wasReady) {
+        CFMachPortInvalidationCallBack cb = mp->_icallout;
+        if (cb) {
+            cb(mp, mp->_context.info);
+        }
+        if (NULL != source) {
+            CFRunLoopSourceInvalidate(source);
+            CFRelease(source);
+        }
+        void *info = mp->_context.info;
+        mp->_context.info = NULL;
+        if (mp->_context.release) {
+            mp->_context.release(info);
+        }
+        // For hashing and equality purposes, cannot get rid of _port here
+        mp->_state = kCFMachPortStateInvalid;
+        OSMemoryBarrier();
     }
-    if (shouldFreeInfo) *shouldFreeInfo = false;
-    return memory;
+    CFRelease(mp);
 }
 
 mach_port_t CFMachPortGetPort(CFMachPortRef mp) {
-    CHECK_FOR_FORK();
-    CF_OBJC_FUNCDISPATCH0(__kCFMachPortTypeID, mach_port_t, mp, "machPort");
-    __CFGenericValidateType(mp, __kCFMachPortTypeID);
+    CHECK_FOR_FORK_RET(0);
+    CF_OBJC_FUNCDISPATCH0(CFMachPortGetTypeID(), mach_port_t, mp, "machPort");
+    __CFGenericValidateType(mp, CFMachPortGetTypeID());
     return mp->_port;
 }
 
 void CFMachPortGetContext(CFMachPortRef mp, CFMachPortContext *context) {
-    __CFGenericValidateType(mp, __kCFMachPortTypeID);
+    __CFGenericValidateType(mp, CFMachPortGetTypeID());
     CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
-    CF_WRITE_BARRIER_MEMMOVE(context, &mp->_context, sizeof(CFMachPortContext));
-}
-
-void CFMachPortInvalidate(CFMachPortRef mp) {
-    CHECK_FOR_FORK();
-    CF_OBJC_FUNCDISPATCH0(__kCFMachPortTypeID, void, mp, "invalidate");
-    __CFGenericValidateType(mp, __kCFMachPortTypeID);
-    if (!__CFMachPortIsDeallocing(mp)) {
-       CFRetain(mp);
-    }
-    __CFSpinLock(&__CFAllMachPortsLock);
-    if (NULL != __CFAllMachPorts) {
-       CFDictionaryRemoveValue(__CFAllMachPorts, (void *)(uintptr_t)(mp->_port));
-    }
-    __CFSpinUnlock(&__CFAllMachPortsLock);
-    __CFMachPortLock(mp);
-    if (__CFMachPortIsValid(mp)) {
-       CFRunLoopSourceRef source;
-       void *info;
-       mach_port_t old_port = mp->_oldnotify;
-       CFMachPortInvalidationCallBack callout = mp->_icallout;
-       __CFMachPortUnsetValid(mp);
-       __CFMachPortUnlock(mp);
-       if (NULL != callout) {
-           callout(mp, mp->_context.info);
-       }
-       __CFMachPortLock(mp);
-       // For hashing and equality purposes, cannot get rid of _port here
-       source = mp->_source;
-       mp->_source = NULL;
-       info = mp->_context.info;
-       mp->_context.info = NULL;
-       __CFMachPortUnlock(mp);
-       if (NULL != mp->_context.release) {
-           mp->_context.release(info);
-       }
-       if (NULL != source) {
-           CFRunLoopSourceInvalidate(source);
-           CFRelease(source);
-       }
-       if (MACH_PORT_NULL != old_port) {
-           mach_port_deallocate(mach_task_self(), old_port);
-       }
-    } else {
-       __CFMachPortUnlock(mp);
-    }
-    if (!__CFMachPortIsDeallocing(mp)) {
-       CFRelease(mp);
-    }
+    objc_memmove_collectable(context, &mp->_context, sizeof(CFMachPortContext));
 }
 
 Boolean CFMachPortIsValid(CFMachPortRef mp) {
-    CF_OBJC_FUNCDISPATCH0(__kCFMachPortTypeID, Boolean, mp, "isValid");
-    __CFGenericValidateType(mp, __kCFMachPortTypeID);
+    CF_OBJC_FUNCDISPATCH0(CFMachPortGetTypeID(), Boolean, mp, "isValid");
+    __CFGenericValidateType(mp, CFMachPortGetTypeID());
     return __CFMachPortIsValid(mp);
 }
 
 CFMachPortInvalidationCallBack CFMachPortGetInvalidationCallBack(CFMachPortRef mp) {
-    __CFGenericValidateType(mp, __kCFMachPortTypeID);
+    __CFGenericValidateType(mp, CFMachPortGetTypeID());
     return mp->_icallout;
 }
 
+/* After the CFMachPort has started going invalid, or done invalid, you can't change this, and
+   we'll only do the callout directly on a transition from NULL to non-NULL. */
 void CFMachPortSetInvalidationCallBack(CFMachPortRef mp, CFMachPortInvalidationCallBack callout) {
-    __CFGenericValidateType(mp, __kCFMachPortTypeID);
-    if (!__CFMachPortIsValid(mp) && NULL != callout) {
-       callout(mp, mp->_context.info);
+    CHECK_FOR_FORK_RET();
+    __CFGenericValidateType(mp, CFMachPortGetTypeID());
+    if (__CFMachPortIsValid(mp) || !callout) {
+        mp->_icallout = callout;
+    } else if (!mp->_icallout && callout) {
+        callout(mp, mp->_context.info);
     } else {
-       mp->_icallout = callout;
+        CFLog(kCFLogLevelWarning, CFSTR("CFMachPortSetInvalidationCallBack(): attempt to set invalidation callback (%p) on invalid CFMachPort (%p) thwarted"), callout, mp);
     }
 }
 
-/* Returns the number of messages queued for a receive port.  */
+/* Returns the number of messages queued for a receive port. */
 CFIndex CFMachPortGetQueuedMessageCount(CFMachPortRef mp) {  
-    CHECK_FOR_FORK();
+    CHECK_FOR_FORK_RET(0);
+    __CFGenericValidateType(mp, CFMachPortGetTypeID());
     mach_port_status_t status;
     mach_msg_type_number_t num = MACH_PORT_RECEIVE_STATUS_COUNT;
-    kern_return_t ret;
-    ret = mach_port_get_attributes(mach_task_self(), mp->_port, MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &num);
+    kern_return_t ret = mach_port_get_attributes(mach_task_self(), mp->_port, MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &num);
     return (KERN_SUCCESS != ret) ? 0 : status.mps_msgcount;
 }
 
 static mach_port_t __CFMachPortGetPort(void *info) {
-    CFMachPortRef mp = info;
+    CFMachPortRef mp = (CFMachPortRef)info;
     return mp->_port;
 }
 
 static void *__CFMachPortPerform(void *msg, CFIndex size, CFAllocatorRef allocator, void *info) {
-    CHECK_FOR_FORK();
-    CFMachPortRef mp = info;
-    void *context_info;
-    void (*context_release)(const void *);
-    __CFMachPortLock(mp);
-    if (!__CFMachPortIsValid(mp)) {
-       __CFMachPortUnlock(mp);
-       return NULL;
-    }
-    if (NULL != mp->_context.retain) {
-       context_info = (void *)mp->_context.retain(mp->_context.info);
-       context_release = mp->_context.release;
+    CHECK_FOR_FORK_RET(NULL);
+    CFMachPortRef mp = (CFMachPortRef)info;
+    __block Boolean isValid = false;
+    dispatch_sync(__portQueue(), ^{
+            isValid = __CFMachPortIsValid(mp);
+        });
+    if (!isValid) return NULL;
+
+    void *context_info = NULL;
+    void (*context_release)(const void *) = NULL;
+    if (mp->_context.retain) {
+        context_info = (void *)mp->_context.retain(mp->_context.info);
+        context_release = mp->_context.release;
     } else {
-       context_info = mp->_context.info;
-       context_release = NULL;
+        context_info = mp->_context.info;
     }
-    __CFMachPortUnlock(mp);
-    mp->_callout(mp, msg, size, mp->_context.info);
-    CHECK_FOR_FORK();
+
+    mp->_callout(mp, msg, size, context_info);
+
     if (context_release) {
-       context_release(context_info);
+        context_release(context_info);
     }
+    CHECK_FOR_FORK_RET(NULL);
     return NULL;
 }
 
 CFRunLoopSourceRef CFMachPortCreateRunLoopSource(CFAllocatorRef allocator, CFMachPortRef mp, CFIndex order) {
-    CHECK_FOR_FORK();
-    CFRunLoopSourceRef result = NULL;
-    __CFGenericValidateType(mp, __kCFMachPortTypeID);
-    __CFMachPortLock(mp);
-    if (!__CFMachPortIsValid(mp)) {
-        __CFMachPortUnlock(mp);
-        return NULL;
-    }
-    if (NULL == mp->_source) {
-       CFRunLoopSourceContext1 context;
-       context.version = 1;
-       context.info = (void *)mp;
-       context.retain = (const void *(*)(const void *))CFRetain;
-       context.release = (void (*)(const void *))CFRelease;
-       context.copyDescription = (CFStringRef (*)(const void *))__CFMachPortCopyDescription;
-       context.equal = (Boolean (*)(const void *, const void *))__CFMachPortEqual;
-       context.hash = (CFHashCode (*)(const void *))__CFMachPortHash;
-       context.getPort = __CFMachPortGetPort;
-       context.perform = __CFMachPortPerform;
-       mp->_source = CFRunLoopSourceCreate(allocator, order, (CFRunLoopSourceContext *)&context);
-    }
-    if (NULL != mp->_source) {
-       result = (CFRunLoopSourceRef)CFRetain(mp->_source);
-    }
-    __CFMachPortUnlock(mp);
+    CHECK_FOR_FORK_RET(NULL);
+    __CFGenericValidateType(mp, CFMachPortGetTypeID());
+    __block CFRunLoopSourceRef result = NULL;
+    dispatch_sync(__portQueue(), ^{
+            if (!__CFMachPortIsValid(mp)) return;
+            if (NULL == mp->_source) {
+                CFRunLoopSourceContext1 context;
+                context.version = 1;
+                context.info = (void *)mp;
+                context.retain = (const void *(*)(const void *))CFRetain;
+                context.release = (void (*)(const void *))CFRelease;
+                context.copyDescription = (CFStringRef (*)(const void *))__CFMachPortCopyDescription;
+                context.equal = (Boolean (*)(const void *, const void *))__CFMachPortEqual;
+                context.hash = (CFHashCode (*)(const void *))__CFMachPortHash;
+                context.getPort = __CFMachPortGetPort;
+                context.perform = __CFMachPortPerform;
+                mp->_source = CFRunLoopSourceCreate(allocator, order, (CFRunLoopSourceContext *)&context);
+            }
+            result = mp->_source ? (CFRunLoopSourceRef)CFRetain(mp->_source) : NULL;
+        });
     return result;
 }
 
-
index 067a609ceb6592405371270e55806cde15f44e04..4b4193daf187b3dd4aabcfa1eca2566e54426e3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFMachPort.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFMACHPORT__)
index 0e9b79b818f88b67eaefce2e8544565185c20fc3..f9c0964abde1107e3a6dac989eb3c9fc46cc9f1f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFMessagePort.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
@@ -39,6 +39,9 @@
 #include <math.h>
 #include <mach/mach_time.h>
 #include <dlfcn.h>
+#include <dispatch/dispatch.h>
+
+extern pid_t getpid(void);
 
 
 #define __kCFMessagePortMaxNameLengthMax 255
     #define __kCFMessagePortMaxNameLength __kCFMessagePortMaxNameLengthMax
 #endif
 
+#define __CFMessagePortMaxDataSize 0x60000000L
+
+
+DISPATCH_HELPER_FUNCTIONS(mport, CFMessagePort)
+
+
 static CFSpinLock_t __CFAllMessagePortsLock = CFSpinLockInit;
 static CFMutableDictionaryRef __CFAllLocalMessagePorts = NULL;
 static CFMutableDictionaryRef __CFAllRemoteMessagePorts = NULL;
@@ -68,6 +77,8 @@ struct __CFMessagePort {
     int32_t _perPID;                   /* zero if not per-pid, else pid */
     CFMachPortRef _replyPort;          /* only used by remote port; immutable once created; invalidated */
     CFRunLoopSourceRef _source;                /* only used by local port; immutable once created; invalidated */
+    dispatch_source_t _dispatchSource;  /* only used by local port; invalidated */
+    dispatch_queue_t _dispatchQ;       /* only used by local port */
     CFMessagePortInvalidationCallBack _icallout;
     CFMessagePortCallBack _callout;    /* only used by local port; immutable */
     CFMessagePortContext _context;     /* not part of remote port; immutable; invalidated */
@@ -133,35 +144,30 @@ CF_INLINE void __CFMessagePortUnlock(CFMessagePortRef ms) {
 // Just a heuristic
 #define __CFMessagePortMaxInlineBytes 4096*10
 
-struct __CFMessagePortMachMsg0 {
-    int32_t msgid;
-    int32_t byteslen;
-    uint8_t bytes[__CFMessagePortMaxInlineBytes];
-};
-
-struct __CFMessagePortMachMsg1 {
-    mach_msg_descriptor_t desc;
-    int32_t msgid;
-};
-
 struct __CFMessagePortMachMessage {
     mach_msg_header_t head;
     mach_msg_body_t body;
     union {
-       struct __CFMessagePortMachMsg0 msg0;
-       struct __CFMessagePortMachMsg1 msg1;
-    } contents;
+        mach_msg_ool_descriptor32_t _0;
+        mach_msg_ool_descriptor64_t _1;
+        mach_msg_ool_descriptor_t out_of_line;
+    } desc; // ignored for inline bytes messages
+    int32_t msgid;
+    int32_t byteslen;
+    uint8_t bytes[0];
 };
 
-static struct __CFMessagePortMachMessage *__CFMessagePortCreateMessage(CFAllocatorRef allocator, bool reply, mach_port_t port, mach_port_t replyPort, int32_t convid, int32_t msgid, const uint8_t *bytes, int32_t byteslen) {
+static struct __CFMessagePortMachMessage *__CFMessagePortCreateMessage(bool reply, mach_port_t port, mach_port_t replyPort, int32_t convid, int32_t msgid, const uint8_t *bytes, int32_t byteslen) {
+    if (__CFMessagePortMaxDataSize < byteslen) return NULL;
     struct __CFMessagePortMachMessage *msg;
-    int32_t size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t);
-    if (byteslen < __CFMessagePortMaxInlineBytes) {
-       size += 2 * sizeof(int32_t) + ((byteslen + 3) & ~0x3);
-    } else {
-       size += sizeof(struct __CFMessagePortMachMsg1);
+    int32_t size = sizeof(struct __CFMessagePortMachMessage);
+    int32_t rounded_byteslen = ((byteslen + 3) & ~0x3);
+    if (rounded_byteslen <= __CFMessagePortMaxInlineBytes) {
+       size += rounded_byteslen;
     }
-    msg = CFAllocatorAllocate(allocator, size, 0);
+    msg = CFAllocatorAllocate(kCFAllocatorSystemDefault, size, 0);
+    if (!msg) return NULL;
+    memset(msg, 0, size);
     msg->head.msgh_id = convid;
     msg->head.msgh_size = size;
     msg->head.msgh_remote_port = port;
@@ -169,23 +175,21 @@ static struct __CFMessagePortMachMessage *__CFMessagePortCreateMessage(CFAllocat
     msg->head.msgh_reserved = 0;
 //    msg->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, (replyPort ? MACH_MSG_TYPE_MAKE_SEND : 0));
     msg->head.msgh_bits = MACH_MSGH_BITS((reply ? MACH_MSG_TYPE_MOVE_SEND_ONCE : MACH_MSG_TYPE_COPY_SEND), (MACH_PORT_NULL != replyPort ? MACH_MSG_TYPE_MAKE_SEND_ONCE : 0));
-    if (byteslen < __CFMessagePortMaxInlineBytes) {
+    msg->msgid = CFSwapInt32HostToLittle(msgid);
+    msg->byteslen = CFSwapInt32HostToLittle(byteslen);
+    if (rounded_byteslen <= __CFMessagePortMaxInlineBytes) {
        msg->body.msgh_descriptor_count = 0;
-       msg->contents.msg0.msgid = CFSwapInt32HostToLittle(msgid);
-       msg->contents.msg0.byteslen = CFSwapInt32HostToLittle(byteslen);
        if (NULL != bytes && 0 < byteslen) {
-           memmove(msg->contents.msg0.bytes, bytes, byteslen);
+           memmove(msg->bytes, bytes, byteslen);
        }
-       memset(msg->contents.msg0.bytes + byteslen, 0, ((byteslen + 3) & ~0x3) - byteslen);
     } else {
        msg->head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
        msg->body.msgh_descriptor_count = 1;
-       msg->contents.msg1.desc.out_of_line.deallocate = false;
-       msg->contents.msg1.desc.out_of_line.copy = MACH_MSG_VIRTUAL_COPY;
-       msg->contents.msg1.desc.out_of_line.address = (void *)bytes;
-       msg->contents.msg1.desc.out_of_line.size = byteslen;
-       msg->contents.msg1.desc.out_of_line.type = MACH_MSG_OOL_DESCRIPTOR;
-       msg->contents.msg1.msgid = CFSwapInt32HostToLittle(msgid);
+       msg->desc.out_of_line.deallocate = false;
+       msg->desc.out_of_line.copy = MACH_MSG_VIRTUAL_COPY;
+       msg->desc.out_of_line.address = (void *)bytes;
+       msg->desc.out_of_line.size = byteslen;
+       msg->desc.out_of_line.type = MACH_MSG_OOL_DESCRIPTOR;
     }
     return msg;
 }
@@ -196,15 +200,15 @@ static CFStringRef __CFMessagePortCopyDescription(CFTypeRef cf) {
     const char *locked;
     CFStringRef contextDesc = NULL;
     locked = ms->_lock ? "Yes" : "No";
-    if (!__CFMessagePortIsRemote(ms)) {
+    if (__CFMessagePortIsRemote(ms)) {
+       result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFMessagePort %p [%p]>{locked = %s, valid = %s, remote = %s, name = %@}"), cf, CFGetAllocator(ms), locked, (__CFMessagePortIsValid(ms) ? "Yes" : "No"), (__CFMessagePortIsRemote(ms) ? "Yes" : "No"), ms->_name);
+    } else {
        if (NULL != ms->_context.info && NULL != ms->_context.copyDescription) {
            contextDesc = ms->_context.copyDescription(ms->_context.info);
        }
        if (NULL == contextDesc) {
            contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFMessagePort context %p>"), ms->_context.info);
        }
-       result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFMessagePort %p [%p]>{locked = %s, valid = %s, remote = %s, name = %@}"), cf, CFGetAllocator(ms), locked, (__CFMessagePortIsValid(ms) ? "Yes" : "No"), (__CFMessagePortIsRemote(ms) ? "Yes" : "No"), ms->_name);
-    } else {
        void *addr = ms->_callout;
        Dl_info info;
        const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
@@ -287,22 +291,22 @@ CFTypeID CFMessagePortGetTypeID(void) {
     return __kCFMessagePortTypeID;
 }
 
-static CFStringRef __CFMessagePortSanitizeStringName(CFAllocatorRef allocator, CFStringRef name, uint8_t **utfnamep, CFIndex *utfnamelenp) {
+static CFStringRef __CFMessagePortSanitizeStringName(CFStringRef name, uint8_t **utfnamep, CFIndex *utfnamelenp) {
     uint8_t *utfname;
     CFIndex utflen;
     CFStringRef result;
-    utfname = CFAllocatorAllocate(allocator, __kCFMessagePortMaxNameLength + 1, 0);
+    utfname = CFAllocatorAllocate(kCFAllocatorSystemDefault, __kCFMessagePortMaxNameLength + 1, 0);
     CFStringGetBytes(name, CFRangeMake(0, CFStringGetLength(name)), kCFStringEncodingUTF8, 0, false, utfname, __kCFMessagePortMaxNameLength, &utflen);
     utfname[utflen] = '\0';
     /* A new string is created, because the original string may have been
        truncated to the max length, and we want the string name to definitely
        match the raw UTF-8 chunk that has been created. Also, this is useful
        to get a constant string in case the original name string was mutable. */
-    result = CFStringCreateWithBytes(allocator, utfname, utflen, kCFStringEncodingUTF8, false);
+    result = CFStringCreateWithBytes(kCFAllocatorSystemDefault, utfname, utflen, kCFStringEncodingUTF8, false);
     if (NULL != utfnamep) {
        *utfnamep = utfname;
     } else {
-       CFAllocatorDeallocate(allocator, utfname);
+       CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
     }
     if (NULL != utfnamelenp) {
        *utfnamelenp = utflen;
@@ -316,7 +320,7 @@ static void __CFMessagePortDummyCallback(CFMachPortRef port, void *msg, CFIndex
 
 static void __CFMessagePortInvalidationCallBack(CFMachPortRef port, void *info) {
     // info has been setup as the CFMessagePort owning the CFMachPort
-    CFMessagePortInvalidate(info);
+    if (info) CFMessagePortInvalidate(info);
 }
 
 static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFStringRef name, CFMessagePortCallBack callout, CFMessagePortContext *context, Boolean *shouldFreeInfo, Boolean perPID) {
@@ -325,7 +329,7 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS
 
     if (shouldFreeInfo) *shouldFreeInfo = true;
     if (NULL != name) {
-       name = __CFMessagePortSanitizeStringName(allocator, name, &utfname, NULL);
+       name = __CFMessagePortSanitizeStringName(name, &utfname, NULL);
     }
     __CFSpinLock(&__CFAllMessagePortsLock);
     if (!perPID && NULL != name) {
@@ -334,7 +338,7 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS
            CFRetain(existing);
            __CFSpinUnlock(&__CFAllMessagePortsLock);
            CFRelease(name);
-           CFAllocatorDeallocate(allocator, utfname);
+           CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
            return (CFMessagePortRef)(existing);
        }
     }
@@ -345,7 +349,7 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS
        if (NULL != name) {
            CFRelease(name);
        }
-       CFAllocatorDeallocate(allocator, utfname);
+       CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
        return NULL;
     }
     __CFMessagePortUnsetValid(memory);
@@ -359,6 +363,8 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS
     memory->_perPID = perPID ? getpid() : 0;   // actual value not terribly useful for local ports
     memory->_replyPort = NULL;
     memory->_source = NULL;
+    memory->_dispatchSource = NULL;
+    memory->_dispatchQ = NULL;
     memory->_icallout = NULL;
     memory->_callout = callout;
     memory->_context.info = NULL;
@@ -380,9 +386,9 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS
                    native = CFMachPortCreateWithPort(allocator, mp, __CFMessagePortDummyCallback, &ctx, NULL);
                    __CFMessagePortSetExtraMachRef(memory);
                } else {
-                   CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort: mach_port_insert_member() after bootstrap_check_in(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'"), ret, ret, bootstrap_strerror(ret), mp, utfname);
+                   CFLog(kCFLogLevelDebug, CFSTR("*** CFMessagePort: mach_port_insert_member() after bootstrap_check_in(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'"), ret, ret, bootstrap_strerror(ret), mp, utfname);
                    mach_port_destroy(mach_task_self(), mp);
-                   CFAllocatorDeallocate(allocator, utfname);
+                   CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
                    // name is released by deallocation
                    CFRelease(memory);
                    return NULL;
@@ -392,13 +398,19 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS
        if (!native) {
            CFMachPortContext ctx = {0, memory, NULL, NULL, NULL};
            native = CFMachPortCreate(allocator, __CFMessagePortDummyCallback, &ctx, NULL);
+           if (!native) {
+               CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
+               // name is released by deallocation
+               CFRelease(memory);
+               return NULL;
+           }
            mp = CFMachPortGetPort(native);
            ret = bootstrap_register2(bs, (char *)utfname, mp, perPID ? BOOTSTRAP_PER_PID_SERVICE : 0);
            if (ret != KERN_SUCCESS) {
-               CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort: bootstrap_register(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'\nSee /usr/include/servers/bootstrap_defs.h for the error codes."), ret, ret, bootstrap_strerror(ret), mp, utfname);
+               CFLog(kCFLogLevelDebug, CFSTR("*** CFMessagePort: bootstrap_register(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'\nSee /usr/include/servers/bootstrap_defs.h for the error codes."), ret, ret, bootstrap_strerror(ret), mp, utfname);
                CFMachPortInvalidate(native);
                CFRelease(native);
-               CFAllocatorDeallocate(allocator, utfname);
+               CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
                // name is released by deallocation
                CFRelease(memory);
                return NULL;
@@ -408,7 +420,7 @@ static CFMessagePortRef __CFMessagePortCreateLocal(CFAllocatorRef allocator, CFS
        memory->_port = native;
     }
 
-    CFAllocatorDeallocate(allocator, utfname);
+    CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
     __CFMessagePortSetValid(memory);
     if (NULL != context) {
        memmove(&memory->_context, context, sizeof(CFMessagePortContext));
@@ -450,7 +462,7 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF
     mach_port_t bp, port;
     kern_return_t ret;
 
-    name = __CFMessagePortSanitizeStringName(allocator, name, &utfname, NULL);
+    name = __CFMessagePortSanitizeStringName(name, &utfname, NULL);
     if (NULL == name) {
        return NULL;
     }
@@ -461,7 +473,7 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF
            CFRetain(existing);
            __CFSpinUnlock(&__CFAllMessagePortsLock);
            CFRelease(name);
-           CFAllocatorDeallocate(allocator, utfname);
+           CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
            return (CFMessagePortRef)(existing);
        }
     }
@@ -472,7 +484,7 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF
        if (NULL != name) {
            CFRelease(name);
        }
-       CFAllocatorDeallocate(allocator, utfname);
+       CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
        return NULL;
     }
     __CFMessagePortUnsetValid(memory);
@@ -486,6 +498,8 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF
     memory->_perPID = perPID ? pid : 0;
     memory->_replyPort = NULL;
     memory->_source = NULL;
+    memory->_dispatchSource = NULL;
+    memory->_dispatchQ = NULL;
     memory->_icallout = NULL;
     memory->_callout = NULL;
     ctx.version = 0;
@@ -496,14 +510,13 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF
     task_get_bootstrap_port(mach_task_self(), &bp);
     ret = bootstrap_look_up2(bp, (char *)utfname, &port, perPID ? (pid_t)pid : 0, perPID ? BOOTSTRAP_PER_PID_SERVICE : 0);
     native = (KERN_SUCCESS == ret) ? CFMachPortCreateWithPort(allocator, port, __CFMessagePortDummyCallback, &ctx, NULL) : NULL;
-    CFAllocatorDeallocate(allocator, utfname);
+    CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
     if (NULL == native) {
        // name is released by deallocation
        CFRelease(memory);
        return NULL;
     }
     memory->_port = native;
-    CFMachPortSetInvalidationCallBack(native, __CFMessagePortInvalidationCallBack);
     __CFMessagePortSetValid(memory);
     __CFSpinLock(&__CFAllMessagePortsLock);
     if (!perPID && NULL != name) {
@@ -520,6 +533,15 @@ static CFMessagePortRef __CFMessagePortCreateRemote(CFAllocatorRef allocator, CF
        CFDictionaryAddValue(__CFAllRemoteMessagePorts, name, memory);
     }
     __CFSpinUnlock(&__CFAllMessagePortsLock);
+    CFMachPortSetInvalidationCallBack(native, __CFMessagePortInvalidationCallBack);
+    // that set-invalidation-callback might have called back into us
+    // if the CFMachPort is already bad, but that was a no-op since
+    // there was no callback setup at the (previous) time the CFMachPort
+    // went invalid; so check for validity manually and react
+    if (!CFMachPortIsValid(native)) {
+        CFRelease(memory); // does the invalidate
+        return NULL;
+    }
     return (CFMessagePortRef)memory;
 }
 
@@ -547,7 +569,7 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) {
 
     __CFGenericValidateType(ms, __kCFMessagePortTypeID);
     if (ms->_perPID || __CFMessagePortIsRemote(ms)) return false;
-    name = __CFMessagePortSanitizeStringName(allocator, name, &utfname, NULL);
+    name = __CFMessagePortSanitizeStringName(name, &utfname, NULL);
     if (NULL == name) {
        return false;
     }
@@ -557,7 +579,7 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) {
        if (NULL != __CFAllLocalMessagePorts && CFDictionaryGetValueIfPresent(__CFAllLocalMessagePorts, name, (const void **)&existing)) {
            __CFSpinUnlock(&__CFAllMessagePortsLock);
            CFRelease(name);
-           CFAllocatorDeallocate(allocator, utfname);
+           CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
            return false;
        }
     }
@@ -578,7 +600,7 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) {
                __CFMessagePortSetExtraMachRef(ms);
             } else {
                 mach_port_destroy(mach_task_self(), mp);
-                CFAllocatorDeallocate(allocator, utfname);
+                CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
                CFRelease(name);
                 return false;
             }
@@ -586,13 +608,18 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) {
         if (!native) {
             CFMachPortContext ctx = {0, ms, NULL, NULL, NULL};
             native = CFMachPortCreate(allocator, __CFMessagePortDummyCallback, &ctx, NULL);
+           if (!native) {
+                CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
+                CFRelease(name);
+                return false;
+           }
             mp = CFMachPortGetPort(native);
             ret = bootstrap_register2(bs, (char *)utfname, mp, 0);
             if (ret != KERN_SUCCESS) {
-                CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort: bootstrap_register(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'\nSee /usr/include/servers/bootstrap_defs.h for the error codes."), ret, ret, bootstrap_strerror(ret), mp, utfname);
+                CFLog(kCFLogLevelDebug, CFSTR("*** CFMessagePort: bootstrap_register(): failed %d (0x%x) '%s', port = 0x%x, name = '%s'\nSee /usr/include/servers/bootstrap_defs.h for the error codes."), ret, ret, bootstrap_strerror(ret), mp, utfname);
                 CFMachPortInvalidate(native);
                 CFRelease(native);
-                CFAllocatorDeallocate(allocator, utfname);
+                CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
                 CFRelease(name);
                 return false;
             }
@@ -627,7 +654,7 @@ Boolean CFMessagePortSetName(CFMessagePortRef ms, CFStringRef name) {
        __CFSpinUnlock(&__CFAllMessagePortsLock);
     }
 
-    CFAllocatorDeallocate(allocator, utfname);
+    CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
     return true;
 }
 
@@ -645,6 +672,12 @@ void CFMessagePortInvalidate(CFMessagePortRef ms) {
     }
     __CFMessagePortLock(ms);
     if (__CFMessagePortIsValid(ms)) {
+        if (ms->_dispatchSource) {
+            dispatch_cancel(ms->_dispatchSource);
+            ms->_dispatchSource = NULL;
+           ms->_dispatchQ = NULL;
+        }
+
        CFMessagePortInvalidationCallBack callout = ms->_icallout;
        CFRunLoopSourceRef source = ms->_source;
        CFMachPortRef replyPort = ms->_replyPort;
@@ -740,26 +773,51 @@ static void __CFMessagePortReplyCallBack(CFMachPortRef port, void *msg, CFIndex
        __CFMessagePortUnlock(ms);
        return;
     }
-// assert: (int32_t)msgp->head.msgh_id < 0
+
+    int32_t byteslen = 0;
+
+    Boolean invalidComplex = (0 != msgp->body.msgh_descriptor_count) && !(msgp->head.msgh_bits & MACH_MSGH_BITS_COMPLEX);
+    invalidComplex = invalidComplex || ((msgp->head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (0 == msgp->body.msgh_descriptor_count));
+    Boolean wayTooBig = sizeof(struct __CFMessagePortMachMessage) + __CFMessagePortMaxInlineBytes < msgp->head.msgh_size;
+    Boolean wayTooSmall = msgp->head.msgh_size < sizeof(struct __CFMessagePortMachMessage);
+    Boolean wrongSize = false;
+    if (!(invalidComplex || wayTooBig || wayTooSmall)) {
+        byteslen = CFSwapInt32LittleToHost(msgp->byteslen);
+        wrongSize = (byteslen < 0) || (__CFMessagePortMaxDataSize < byteslen);
+        if (msgp->head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
+            wrongSize = wrongSize || (msgp->desc.out_of_line.size != byteslen);
+        } else {
+            wrongSize = wrongSize || (msgp->head.msgh_size - sizeof(struct __CFMessagePortMachMessage) < byteslen);
+        }
+    }
+    Boolean invalidMsgID = (0 <= msgp->head.msgh_id) && (msgp->head.msgh_id <= INT32_MAX); // conversation id
+    if (invalidComplex || wayTooBig || wayTooSmall || wrongSize || invalidMsgID) {
+        CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort: dropping corrupt reply Mach message (0b%d%d%d%d%d)"), invalidComplex, wayTooBig, wayTooSmall, wrongSize, invalidMsgID);
+        mach_msg_destroy((mach_msg_header_t *)msgp);
+        __CFMessagePortUnlock(ms);
+        return;
+    }
+
     if (CFDictionaryContainsKey(ms->_replies, (void *)(uintptr_t)msgp->head.msgh_id)) {
        CFDataRef reply = NULL;
        replymsg = (struct __CFMessagePortMachMessage *)msg;
        if (0 == replymsg->body.msgh_descriptor_count) {
-           int32_t byteslen = CFSwapInt32LittleToHost(replymsg->contents.msg0.byteslen);
-           if (0 <= byteslen) {
-               reply = CFDataCreate(kCFAllocatorSystemDefault, replymsg->contents.msg0.bytes, byteslen);
+           uintptr_t msgp_extent = (uintptr_t)((uint8_t *)msgp + msgp->head.msgh_size);
+           uintptr_t data_extent = (uintptr_t)((uint8_t *)&(replymsg->bytes) + byteslen);
+           if (0 <= byteslen && data_extent <= msgp_extent) {
+               reply = CFDataCreate(kCFAllocatorSystemDefault, replymsg->bytes, byteslen);
            } else {
                reply = (void *)~0;     // means NULL data
            }
        } else {
 //#warning CF: should create a no-copy data here that has a custom VM-freeing allocator, and not vm_dealloc here
-           reply = CFDataCreate(kCFAllocatorSystemDefault, replymsg->contents.msg1.desc.out_of_line.address, replymsg->contents.msg1.desc.out_of_line.size);
-           vm_deallocate(mach_task_self(), (vm_address_t)replymsg->contents.msg1.desc.out_of_line.address, replymsg->contents.msg1.desc.out_of_line.size);
+           reply = CFDataCreate(kCFAllocatorSystemDefault, replymsg->desc.out_of_line.address, replymsg->desc.out_of_line.size);
+           vm_deallocate(mach_task_self(), (vm_address_t)replymsg->desc.out_of_line.address, replymsg->desc.out_of_line.size);
        }
        CFDictionarySetValue(ms->_replies, (void *)(uintptr_t)msgp->head.msgh_id, (void *)reply);
     } else {   /* discard message */
        if (1 == msgp->body.msgh_descriptor_count) {
-           vm_deallocate(mach_task_self(), (vm_address_t)msgp->contents.msg1.desc.out_of_line.address, msgp->contents.msg1.desc.out_of_line.size);
+           vm_deallocate(mach_task_self(), (vm_address_t)msgp->desc.out_of_line.address, msgp->desc.out_of_line.size);
        }
     }
     __CFMessagePortUnlock(ms);
@@ -778,8 +836,16 @@ SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef
 
     //#warning CF: This should be an assert
     // if (!__CFMessagePortIsRemote(remote)) return -999;
-    if (!__CFMessagePortIsValid(remote)) return kCFMessagePortIsInvalid;
+    if (data && __CFMessagePortMaxDataSize < CFDataGetLength(data)) {
+        CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePortSendRequest: CFMessagePort cannot send more than %lu bytes of data"), __CFMessagePortMaxDataSize);
+        return kCFMessagePortTransportError;
+    }
     __CFMessagePortLock(remote);
+    if (!__CFMessagePortIsValid(remote)) {
+        __CFMessagePortUnlock(remote);
+        return kCFMessagePortIsInvalid;
+    }
+    CFRetain(remote); // retain during run loop to avoid invalidation causing freeing
     if (NULL == remote->_replyPort) {
        CFMachPortContext context;
        context.version = 0;
@@ -791,8 +857,12 @@ SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef
     }
     remote->_convCounter++;
     desiredReply = -remote->_convCounter;
-    sendmsg = __CFMessagePortCreateMessage(kCFAllocatorSystemDefault, false, CFMachPortGetPort(remote->_port), (replyMode != NULL ? CFMachPortGetPort(remote->_replyPort) : MACH_PORT_NULL), -desiredReply, msgid, (data ? CFDataGetBytePtr(data) : NULL), (data ? CFDataGetLength(data) : 0));
-    __CFMessagePortUnlock(remote);
+    sendmsg = __CFMessagePortCreateMessage(false, CFMachPortGetPort(remote->_port), (replyMode != NULL ? CFMachPortGetPort(remote->_replyPort) : MACH_PORT_NULL), -desiredReply, msgid, (data ? CFDataGetBytePtr(data) : NULL), (data ? CFDataGetLength(data) : 0));
+    if (!sendmsg) {
+        __CFMessagePortUnlock(remote);
+        CFRelease(remote);
+        return kCFMessagePortTransportError;
+    }
     if (replyMode != NULL) {
         CFDictionarySetValue(remote->_replies, (void *)(uintptr_t)desiredReply, NULL);
         source = CFMachPortCreateRunLoopSource(CFGetAllocator(remote), remote->_replyPort, -100);
@@ -816,14 +886,17 @@ SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef
            CFRunLoopRemoveSource(currentRL, source, replyMode);
        }
        if (source) CFRelease(source);
+        __CFMessagePortUnlock(remote);
         CFAllocatorDeallocate(kCFAllocatorSystemDefault, sendmsg);
+        CFRelease(remote);
        return (MACH_SEND_TIMED_OUT == ret) ? kCFMessagePortSendTimeout : kCFMessagePortTransportError;
     }
+    __CFMessagePortUnlock(remote);
     CFAllocatorDeallocate(kCFAllocatorSystemDefault, sendmsg);
     if (replyMode == NULL) {
+        CFRelease(remote);
        return kCFMessagePortSuccess;
     }
-    CFRetain(remote); // retain during run loop to avoid invalidation causing freeing
     _CFMachPortInstallNotifyPort(currentRL, replyMode);
     termTSR = mach_absolute_time() + __CFTimeIntervalToTSR(rcvTimeout);
     for (;;) {
@@ -846,7 +919,7 @@ SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef
     if (NULL == reply) {
        CFDictionaryRemoveValue(remote->_replies, (void *)(uintptr_t)desiredReply);
        CFRelease(remote);
-       return CFMessagePortIsValid(remote) ? kCFMessagePortReceiveTimeout : -5;
+       return CFMessagePortIsValid(remote) ? kCFMessagePortReceiveTimeout : kCFMessagePortBecameInvalidError;
     }
     if (NULL != returnDatap) {
        *returnDatap = ((void *)~0 == reply) ? NULL : reply;
@@ -860,7 +933,7 @@ SInt32 CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid, CFDataRef
 
 static mach_port_t __CFMessagePortGetPort(void *info) {
     CFMessagePortRef ms = info;
-    if (!ms->_port) CFLog(kCFLogLevelWarning, CFSTR("*** Warning: A local CFMessagePort (%p) is being put in a run loop, but it has not been named yet, so this will be a no-op and no messages are going to be received, even if named later."), info);
+    if (!ms->_port) CFLog(kCFLogLevelWarning, CFSTR("*** Warning: A local CFMessagePort (%p) is being put in a run loop or dispatch queue, but it has not been named yet, so this will be a no-op and no messages are going to be received, even if named later."), info);
     return ms->_port ? CFMachPortGetPort(ms->_port) : MACH_PORT_NULL;
 }
 
@@ -880,7 +953,6 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo
        __CFMessagePortUnlock(ms);
        return NULL;
     }
-// assert: 0 < (int32_t)msgp->head.msgh_id
     if (NULL != ms->_context.retain) {
        context_info = (void *)ms->_context.retain(ms->_context.info);
        context_release = ms->_context.release;
@@ -889,16 +961,42 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo
        context_release = NULL;
     }
     __CFMessagePortUnlock(ms);
+
+    int32_t byteslen = 0;
+
+    Boolean invalidComplex = (0 != msgp->body.msgh_descriptor_count) && !(msgp->head.msgh_bits & MACH_MSGH_BITS_COMPLEX);
+    invalidComplex = invalidComplex || ((msgp->head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && (0 == msgp->body.msgh_descriptor_count));
+    Boolean wayTooBig = sizeof(struct __CFMessagePortMachMessage) + __CFMessagePortMaxInlineBytes < msgp->head.msgh_size;
+    Boolean wayTooSmall = msgp->head.msgh_size < sizeof(struct __CFMessagePortMachMessage);
+    Boolean wrongSize = false;
+    if (!(invalidComplex || wayTooBig || wayTooSmall)) {
+        byteslen = CFSwapInt32LittleToHost(msgp->byteslen);
+        wrongSize = (byteslen < 0) || (__CFMessagePortMaxDataSize < byteslen);
+        if (msgp->head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
+            wrongSize = wrongSize || (msgp->desc.out_of_line.size != byteslen);
+        } else {
+            wrongSize = wrongSize || (msgp->head.msgh_size - sizeof(struct __CFMessagePortMachMessage) < byteslen);
+        }
+    }
+    Boolean invalidMsgID = (msgp->head.msgh_id <= 0) || (INT32_MAX < msgp->head.msgh_id); // conversation id
+    if (invalidComplex || wayTooBig || wayTooSmall || wrongSize || invalidMsgID) {
+        mach_msg_security_trailer_t *trailer = (void *)msgp + msgp->head.msgh_size;
+       CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort: dropping corrupt request Mach message (0b%d%d%d%d%d)"), invalidComplex, wayTooBig, wayTooSmall, wrongSize, invalidMsgID);
+        mach_msg_destroy((mach_msg_header_t *)msgp);
+        return NULL;
+    }
+
     /* Create no-copy, no-free-bytes wrapper CFData */
     if (0 == msgp->body.msgh_descriptor_count) {
-       int32_t byteslen = CFSwapInt32LittleToHost(msgp->contents.msg0.byteslen);
-       msgid = CFSwapInt32LittleToHost(msgp->contents.msg0.msgid);
-       if (0 <= byteslen) {
-           data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, msgp->contents.msg0.bytes, byteslen, kCFAllocatorNull);
+       uintptr_t msgp_extent = (uintptr_t)((uint8_t *)msgp + msgp->head.msgh_size);
+       uintptr_t data_extent = (uintptr_t)((uint8_t *)&(msgp->bytes) + byteslen);
+       msgid = CFSwapInt32LittleToHost(msgp->msgid);
+       if (0 <= byteslen && data_extent <= msgp_extent) {
+           data = CFDataCreateWithBytesNoCopy(allocator, msgp->bytes, byteslen, kCFAllocatorNull);
        }
     } else {
-       msgid = CFSwapInt32LittleToHost(msgp->contents.msg1.msgid);
-       data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, msgp->contents.msg1.desc.out_of_line.address, msgp->contents.msg1.desc.out_of_line.size, kCFAllocatorNull);
+       msgid = CFSwapInt32LittleToHost(msgp->msgid);
+       data = CFDataCreateWithBytesNoCopy(allocator, msgp->desc.out_of_line.address, msgp->desc.out_of_line.size, kCFAllocatorNull);
     }
     returnData = ms->_callout(ms, msgid, data, context_info);
     /* Now, returnData could be (1) NULL, (2) an ordinary data < MAX_INLINE,
@@ -913,9 +1011,14 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo
     wad until the message was sent either, if we didn't make the copy. */
     if (NULL != returnData) {
        return_len = CFDataGetLength(returnData);
-       if (return_len < __CFMessagePortMaxInlineBytes) {
+        if (__CFMessagePortMaxDataSize < return_len) {
+            CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePort reply: CFMessagePort cannot send more than %lu bytes of data"), __CFMessagePortMaxDataSize);
+            return_len = 0;
+            returnData = NULL;
+        }
+       if (returnData && return_len < __CFMessagePortMaxInlineBytes) {
            return_bytes = (void *)CFDataGetBytePtr(returnData);
-       } else {
+       } else if (returnData) {
            return_bytes = NULL;
            vm_allocate(mach_task_self(), (vm_address_t *)&return_bytes, return_len, VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_MEMORY_MACH_MSG));
            /* vm_copy would only be a win here if the source address
@@ -925,13 +1028,13 @@ static void *__CFMessagePortPerform(void *msg, CFIndex size, CFAllocatorRef allo
            memmove(return_bytes, CFDataGetBytePtr(returnData), return_len);
        }
     }
-    replymsg = __CFMessagePortCreateMessage(allocator, true, msgp->head.msgh_remote_port, MACH_PORT_NULL, -1 * (int32_t)msgp->head.msgh_id, msgid, return_bytes, return_len);
+    replymsg = __CFMessagePortCreateMessage(true, msgp->head.msgh_remote_port, MACH_PORT_NULL, -1 * (int32_t)msgp->head.msgh_id, msgid, return_bytes, return_len);
     if (1 == replymsg->body.msgh_descriptor_count) {
-       replymsg->contents.msg1.desc.out_of_line.deallocate = true;
+       replymsg->desc.out_of_line.deallocate = true;
     }
     if (data) CFRelease(data);
     if (1 == msgp->body.msgh_descriptor_count) {
-       vm_deallocate(mach_task_self(), (vm_address_t)msgp->contents.msg1.desc.out_of_line.address, msgp->contents.msg1.desc.out_of_line.size);
+       vm_deallocate(mach_task_self(), (vm_address_t)msgp->desc.out_of_line.address, msgp->desc.out_of_line.size);
     }
     if (returnData) CFRelease(returnData);
     if (context_release) {
@@ -946,7 +1049,7 @@ CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CF
 //#warning CF: This should be an assert
    // if (__CFMessagePortIsRemote(ms)) return NULL;
     __CFMessagePortLock(ms);
-    if (NULL == ms->_source && __CFMessagePortIsValid(ms)) {
+    if (NULL == ms->_source && NULL == ms->_dispatchSource && __CFMessagePortIsValid(ms)) {
        CFRunLoopSourceContext1 context;
        context.version = 1;
        context.info = (void *)ms;
@@ -966,4 +1069,85 @@ CFRunLoopSourceRef CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CF
     return result;
 }
 
+void CFMessagePortSetDispatchQueue(CFMessagePortRef ms, dispatch_queue_t queue) {
+    __CFGenericValidateType(ms, __kCFMessagePortTypeID);
+    __CFMessagePortLock(ms);
+    if (!__CFMessagePortIsValid(ms)) {
+       __CFMessagePortUnlock(ms);
+       CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePortSetDispatchQueue(): CFMessagePort is invalid"));
+       return;
+    }
+    if (__CFMessagePortIsRemote(ms)) {
+       __CFMessagePortUnlock(ms);
+       CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePortSetDispatchQueue(): CFMessagePort is not a local port, queue cannot be set"));
+       return;
+    }
+    if (NULL != ms->_source) {
+       __CFMessagePortUnlock(ms);
+       CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePortSetDispatchQueue(): CFMessagePort already has a CFRunLoopSourceRef, queue cannot be set"));
+       return;
+    }
+
+    if (ms->_dispatchSource) {
+        dispatch_cancel(ms->_dispatchSource);
+        ms->_dispatchSource = NULL;
+        ms->_dispatchQ = NULL;
+    }
+
+    if (queue) {
+        mach_port_t port = __CFMessagePortGetPort(ms);
+        if (MACH_PORT_NULL != port) {
+           ms->_dispatchSource = dispatch_source_machport_create(port, DISPATCH_MACHPORT_RECV, DISPATCH_SOURCE_CREATE_SUSPENDED, __mportQueue(), ^(dispatch_source_t source) {
+                    long e = 0, d = dispatch_source_get_error(source, &e);
+                    if (DISPATCH_ERROR_DOMAIN_POSIX == d && ECANCELED == e) {
+                        dispatch_release(queue);
+                        dispatch_release(source);
+                        return;
+                    }
+                    if (DISPATCH_ERROR_DOMAIN_NO_ERROR != d) {
+                        HALT;
+                    }
+
+                    CFRetain(ms);
+                   mach_port_t port = dispatch_source_get_handle(source);
+                    mach_msg_header_t *msg = (mach_msg_header_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2048, 0);
+                    msg->msgh_size = 2048;
+
+                    for (;;) {
+                        msg->msgh_bits = 0;
+                        msg->msgh_local_port = port;
+                        msg->msgh_remote_port = MACH_PORT_NULL;
+                        msg->msgh_id = 0;
+
+                        kern_return_t ret = mach_msg(msg, MACH_RCV_MSG|MACH_RCV_LARGE|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV), 0, msg->msgh_size, port, 0, MACH_PORT_NULL);
+                        if (MACH_MSG_SUCCESS == ret) break;
+                        if (MACH_RCV_TOO_LARGE != ret) HALT;
+
+                        uint32_t newSize = round_msg(msg->msgh_size + MAX_TRAILER_SIZE);
+                        msg = CFAllocatorReallocate(kCFAllocatorSystemDefault, msg, newSize, 0);
+                        msg->msgh_size = newSize;
+                    }
+
+                    dispatch_async(queue, ^{
+                            mach_msg_header_t *reply = __CFMessagePortPerform(msg, msg->msgh_size, kCFAllocatorSystemDefault, ms);
+                            if (NULL != reply) {
+                                kern_return_t ret = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
+                                if (KERN_SUCCESS != ret) mach_msg_destroy(reply);
+                                CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);
+                            }
+                            CFAllocatorDeallocate(kCFAllocatorSystemDefault, msg);
+                            CFRelease(ms);
+                        });
+                });
+       }
+        if (ms->_dispatchSource) {
+            dispatch_retain(queue);
+            ms->_dispatchQ = queue;
+            dispatch_resume(ms->_dispatchSource);
+        } else {
+            CFLog(kCFLogLevelWarning, CFSTR("*** CFMessagePortSetDispatchQueue(): dispatch source could not be created"));
+        }
+    }
+    __CFMessagePortUnlock(ms);
+}
 
index 367b4012d50f45d199e66570780a01e14bc10ec1..c2974f6c4fa3efe8729a014df49ca4e83e7f58d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFMessagePort.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFMESSAGEPORT__)
@@ -30,6 +30,9 @@
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFRunLoop.h>
 #include <CoreFoundation/CFData.h>
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+#include <dispatch/dispatch.h>
+#endif
 
 CF_EXTERN_C_BEGIN
 
@@ -40,7 +43,8 @@ enum {
     kCFMessagePortSendTimeout = -1,
     kCFMessagePortReceiveTimeout = -2,
     kCFMessagePortIsInvalid = -3,
-    kCFMessagePortTransportError = -4
+    kCFMessagePortTransportError = -4,
+    kCFMessagePortBecameInvalidError = -5
 };
 
 typedef struct {
@@ -74,6 +78,10 @@ CF_EXPORT SInt32     CFMessagePortSendRequest(CFMessagePortRef remote, SInt32 msgid,
 
 CF_EXPORT CFRunLoopSourceRef   CFMessagePortCreateRunLoopSource(CFAllocatorRef allocator, CFMessagePortRef local, CFIndex order);
 
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+CF_EXPORT void CFMessagePortSetDispatchQueue(CFMessagePortRef ms, dispatch_queue_t queue) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+#endif
+
 CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFMESSAGEPORT__ */
index b185dc48e5795b60e5992b3668d972b586c8e3c5..46a61948a445ee319264f682d2b0441e06f9b2af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFNumber.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Ali Ozer
 */
 
 #include <CoreFoundation/CFNumber.h>
 #include "CFInternal.h"
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include <math.h>
 #include <float.h>
 
+#if DEPLOYMENT_TARGET_WINDOWS
+#define isnan(A) _isnan(A)
+#define isinf(A) !_finite(A)
+#define copysign(A, B) _copysign(A, B)
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
 #define __CFAssertIsBoolean(cf) __CFGenericValidateType(cf, __kCFBooleanTypeID)
 
 struct __CFBoolean {
@@ -57,6 +66,11 @@ static CFStringRef __CFBooleanCopyFormattingDescription(CFTypeRef cf, CFDictiona
     return (CFStringRef)CFRetain((boolean == kCFBooleanTrue) ? CFSTR("true") : CFSTR("false"));
 }
 
+static CFHashCode __CFBooleanHash(CFTypeRef cf) {
+    CFBooleanRef boolean = (CFBooleanRef)cf;
+    return (boolean == kCFBooleanTrue) ? _CFHashInt(1) : _CFHashInt(0);
+}
+
 static void __CFBooleanDeallocate(CFTypeRef cf) {
     CFAssert(false, __kCFLogAssertion, "Deallocated CFBoolean!");
 }
@@ -70,7 +84,7 @@ static const CFRuntimeClass __CFBooleanClass = {
     NULL,      // copy
     __CFBooleanDeallocate,
     NULL,
-    NULL,
+    __CFBooleanHash,
     __CFBooleanCopyFormattingDescription,
     __CFBooleanCopyDescription
 };
@@ -95,6 +109,37 @@ Boolean CFBooleanGetValue(CFBooleanRef boolean) {
 
 /*** CFNumber ***/
 
+#define OLD_CRAP_TOO 0
+
+#if OLD_CRAP_TOO
+
+typedef union {
+    SInt32 valSInt32;
+    int64_t valSInt64;
+    Float32 valFloat32;
+    Float64 valFloat64;
+} __CFNumberValue_old;
+
+struct __CFNumber_old {             /* Only as many bytes as necessary are allocated */
+    CFRuntimeBase _base;
+    __CFNumberValue_old value;
+};
+
+static Boolean __CFNumberEqual_old(CFTypeRef cf1, CFTypeRef cf2);
+static CFHashCode __CFNumberHash_old(CFTypeRef cf);
+static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf);
+__private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf);
+static CFStringRef __CFNumberCopyFormattingDescription_old(CFTypeRef cf, CFDictionaryRef formatOptions);
+static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr);
+static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number);
+static CFIndex CFNumberGetByteSize_old(struct __CFNumber_old * number);
+static Boolean CFNumberIsFloatType_old(struct __CFNumber_old * number);
+static Boolean CFNumberGetValue_old(struct __CFNumber_old * number, CFNumberType type, void *valuePtr);
+static CFComparisonResult CFNumberCompare_old(struct __CFNumber_old * number1, struct __CFNumber_old * number2, void *context);
+
+#endif
+
+
 #define __CFAssertIsNumber(cf) __CFGenericValidateType(cf, __kCFNumberTypeID)
 #define __CFAssertIsValidNumberType(type) CFAssert2((0 < type && type <= kCFNumberMaxType) || (type == kCFNumberSInt128Type), __kCFLogAssertion, "%s(): bad CFNumber type %d", __PRETTY_FUNCTION__, type);
 
@@ -107,10 +152,16 @@ Boolean CFBooleanGetValue(CFBooleanRef boolean) {
 #define BITSFORDOUBLEPOSINF    ((uint64_t)0x7ff0000000000000ULL)
 #define BITSFORDOUBLENEGINF    ((uint64_t)0xfff0000000000000ULL)
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define FLOAT_POSITIVE_2_TO_THE_64     0x1.0p+64L
 #define FLOAT_NEGATIVE_2_TO_THE_127    -0x1.0p+127L
 #define FLOAT_POSITIVE_2_TO_THE_127    0x1.0p+127L
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define FLOAT_POSITIVE_2_TO_THE_64     18446744073709551616.0
+#define FLOAT_NEGATIVE_2_TO_THE_127    -170141183460469231731687303715884105728.0
+#define FLOAT_POSITIVE_2_TO_THE_127    170141183460469231731687303715884105728.0
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 typedef struct {       // NOTE WELL: these two fields may switch position someday, do not use '= {high, low}' -style initialization
@@ -304,6 +355,10 @@ static void cvtFloat64ToSInt128(CFSInt128Struct *out, const Float64 *in) {
 
 struct __CFNumber {
     CFRuntimeBase _base;
+#if OLD_CRAP_TOO
+    struct __CFNumber_old *__old__;
+    void * __dummy__;
+#endif
     uint64_t _pad; // need this space here for the constant objects
     /* 0 or 8 more bytes allocated here */
 };
@@ -601,7 +656,12 @@ static Boolean __CFNumberGetValueCompat(CFNumberRef number, CFNumberType type, v
            }
        } else {
            if (0 == __CFNumberTypeTable[ntype].storageBit) {
-                CVT_COMPAT(int64_t, int8_t, 1);
+               // Leopard's implemenation of this always returned true. We should only return true when the conversion is lossless. However, there are some clients who use CFNumber with small unsigned values disguised as signed values. Since there is no CFNumber API yet for unsigned values, we need to accomodate those clients for now. <rdar://problem/6471866>
+               // This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
+               int64_t sv; memmove(&sv, data, sizeof(int64_t));
+               int8_t dv = (int8_t)(sv);
+               memmove(valuePtr, &dv, sizeof(int8_t));
+               int64_t vv = (int64_t)dv; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard) || ((sv >> 8LL) == 0LL) || (vv == sv);
            } else {
                CVT128ToInt_COMPAT(CFSInt128Struct, int8_t);
            }
@@ -616,7 +676,12 @@ static Boolean __CFNumberGetValueCompat(CFNumberRef number, CFNumberType type, v
            }
        } else {
            if (0 == __CFNumberTypeTable[ntype].storageBit) {
-                CVT_COMPAT(int64_t, int16_t, 1);
+               // Leopard's implemenation of this always returned true. We should only return true when the conversion is lossless. However, there are some clients who use CFNumber with small unsigned values disguised as signed values. Since there is no CFNumber API yet for unsigned values, we need to accomodate those clients for now. <rdar://problem/6471866>
+               // This accomodation should be removed if CFNumber ever provides API for unsigned values. <rdar://problem/6473890>
+               int64_t sv; memmove(&sv, data, sizeof(int64_t));
+               int16_t dv = (int16_t)(sv);
+               memmove(valuePtr, &dv, sizeof(int16_t));
+               int64_t vv = (int64_t)dv; return !_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard) || ((sv >> 16LL) == 0LL) || (vv == sv);
            } else {
                CVT128ToInt_COMPAT(CFSInt128Struct, int16_t);
            }
@@ -738,6 +803,10 @@ static Boolean __CFNumberGetValueCompat(CFNumberRef number, CFNumberType type, v
     return false;
 }
 
+#if OLD_CRAP_TOO
+static void FAIL(void) {}
+#endif
+
 static CFStringRef __CFNumberCopyDescription(CFTypeRef cf) {
     CFNumberRef number = (CFNumberRef)cf;
     CFNumberType type = __CFNumberGetType(number);
@@ -776,6 +845,17 @@ static CFStringRef __CFNumberCopyDescription(CFTypeRef cf) {
        }
        CFStringAppendFormat(mstr, NULL, CFSTR("%s, type = %s}"), buffer, typeName);
     }
+#if OLD_CRAP_TOO
+if (! number->__old__) {
+
+printf("*** Test skipped in __CFNumberCopyDescription for number %p\n", cf);
+} else {
+CFStringRef test = __CFNumberCopyDescription_old(number->__old__);
+if (!CFEqual(test, mstr)) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyDescription: '%@' '%@'"), test, mstr);  FAIL();
+}
+}
+#endif
     return mstr;
 }
 
@@ -799,6 +879,17 @@ static CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_new(CFTypeRef cf
 
 __private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64(CFTypeRef cf) {
     CFStringRef result = __CFNumberCopyFormattingDescriptionAsFloat64_new(cf);
+#if OLD_CRAP_TOO
+CFNumberRef number = (CFNumberRef)cf;
+if (! number->__old__) {
+printf("*** Test skipped in __CFNumberCopyFormattingDescriptionAsFloat64 for number %p\n", cf);
+} else {
+CFStringRef test = __CFNumberCopyFormattingDescriptionAsFloat64_old(number->__old__);
+if (!CFEqual(test, result)) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescriptionAsFloat64: '%@' '%@'"), test, result);  FAIL();
+}
+}
+#endif
     return result;
 }
 
@@ -817,12 +908,35 @@ static CFStringRef __CFNumberCopyFormattingDescription_new(CFTypeRef cf, CFDicti
 
 static CFStringRef __CFNumberCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
     CFStringRef result = __CFNumberCopyFormattingDescription_new(cf, formatOptions);
+#if OLD_CRAP_TOO
+CFNumberRef number = (CFNumberRef)cf;
+if (! number->__old__) {
+printf("*** Test skipped in __CFNumberCopyFormattingDescription for number %p\n", cf);
+} else {
+CFStringRef test = __CFNumberCopyFormattingDescription_old(number->__old__, formatOptions);
+if (!CFEqual(test, result)) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberCopyFormattingDescription: '%@' '%@'"), test, result);  FAIL();
+}
+}
+#endif
     return result;
 }
 
 
 static Boolean __CFNumberEqual(CFTypeRef cf1, CFTypeRef cf2) {
     Boolean b = CFNumberCompare((CFNumberRef)cf1, (CFNumberRef)cf2, 0) == kCFCompareEqualTo;
+#if OLD_CRAP_TOO
+CFNumberRef number1 = (CFNumberRef)cf1;
+CFNumberRef number2 = (CFNumberRef)cf2;
+if (! number1->__old__ || !number2->__old__) {
+printf("*** Test skipped in __CFNumberEqual for numbers %p %p\n", cf1, cf2);
+} else {
+Boolean b2 = __CFNumberEqual_old(number1->__old__, number2->__old__);
+if (b2 != b) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberEqual: '%d' '%d'"), b2, b);  FAIL();
+}
+}
+#endif
     return b;
 }
 
@@ -845,6 +959,17 @@ static CFHashCode __CFNumberHash(CFTypeRef cf) {
            break;
        }
     }
+#if OLD_CRAP_TOO
+CFNumberRef number1 = (CFNumberRef)cf;
+if (! number1->__old__) {
+printf("*** Test skipped in __CFNumberHash for number %p\n", cf);
+} else {
+CFHashCode h2 = __CFNumberHash_old(number1->__old__);
+if (h2 != h) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in __CFNumberHash: '%d' '%d'"), h2, h);  FAIL();
+}
+}
+#endif
     return h;
 }
 
@@ -929,12 +1054,20 @@ CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType type, const vo
     }
 
     CFIndex size = 8 + ((!__CFNumberTypeTable[type].floatBit && __CFNumberTypeTable[type].storageBit) ? 8 : 0);
+#if OLD_CRAP_TOO
+    size += 2 * sizeof(void *);
+#endif
     CFNumberRef result = (CFNumberRef)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, size, NULL);
     if (NULL == result) {
        return NULL;
     }
     __CFBitfieldSetValue(((struct __CFNumber *)result)->_base._cfinfo[CF_INFO_BITS], 4, 0, (uint8_t)__CFNumberTypeTable[type].canonicalType);
 
+#if OLD_CRAP_TOO
+    ((struct __CFNumber *)result)->__old__ = CFNumberCreate_old(allocator, type, valuePtr);
+CFLog(kCFLogLevelWarning, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDescription_old(result->__old__));
+
+#endif
 
     // for a value to be cached, we already have the value handy
     if (NotToBeCached != valToBeCached) {
@@ -979,10 +1112,20 @@ CFNumberType CFNumberGetType(CFNumberRef number) {
     CFNumberType type = __CFNumberGetType(number);
     if (kCFNumberSInt128Type == type) type = kCFNumberSInt64Type; // must hide this type, since it is not public
 //printf("  => %d\n", type);
+#if OLD_CRAP_TOO
+if (! number->__old__) {
+printf("*** Test skipped in CFNumberGetType for number %p\n", number);
+} else {
+CFNumberType t2 = CFNumberGetType_old(number->__old__);
+if (t2 != type) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"), t2, type);  FAIL();
+}
+}
+#endif
     return type;
 }
 
-CFNumberType _CFNumberGetType2(CFNumberRef number) {
+CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number) {
     __CFAssertIsNumber(number);
     return __CFNumberGetType(number);
 }
@@ -992,6 +1135,16 @@ CFIndex CFNumberGetByteSize(CFNumberRef number) {
     __CFAssertIsNumber(number);
     CFIndex r = 1 << __CFNumberTypeTable[CFNumberGetType(number)].lgByteSize;
 //printf("  => %d\n", r);
+#if OLD_CRAP_TOO
+if (! number->__old__) {
+printf("*** Test skipped in CFNumberGetByteSize for number %p\n", number);
+} else {
+CFIndex r2 = CFNumberGetByteSize_old(number->__old__);
+if (r2 != r) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetByteSize: '%d' '%d'"), r2, r);  FAIL();
+}
+}
+#endif
     return r;
 }
 
@@ -1000,6 +1153,16 @@ Boolean CFNumberIsFloatType(CFNumberRef number) {
     __CFAssertIsNumber(number);
     Boolean r = __CFNumberTypeTable[CFNumberGetType(number)].floatBit;
 //printf("  => %d\n", r);
+#if OLD_CRAP_TOO
+if (! number->__old__) {
+printf("*** Test skipped in CFNumberIsFloatType for number %p\n", number);
+} else {
+Boolean r2 = CFNumberIsFloatType_old(number->__old__);
+if (r2 != r) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberIsFloatType: '%d' '%d'"), r2, r);  FAIL();
+}
+}
+#endif
     return r;
 }
 
@@ -1011,6 +1174,20 @@ Boolean  CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr)
     uint8_t localMemory[128];
     Boolean r = __CFNumberGetValueCompat(number, type, valuePtr ? valuePtr : localMemory);
 //printf("  => %d\n", r);
+#if OLD_CRAP_TOO
+if (! number->__old__) {
+printf("*** Test skipped in CFNumberGetValue for number %p\n", number);
+} else {
+    uint8_t localMemory2[128];
+Boolean r2 = CFNumberGetValue_old(number->__old__, type, localMemory2);
+if (r2 != r) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 1 in CFNumberGetValue: '%d' '%d'"), r2, r);  FAIL();
+}
+if (0 != memcmp(localMemory2, valuePtr, CFNumberGetByteSize(number))) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL 2 in CFNumberGetValue: BYTES NOT SAME"));  FAIL();
+}
+}
+#endif
     return r;
 }
 
@@ -1100,9 +1277,371 @@ CFComparisonResult CFNumberCompare(CFNumberRef number1, CFNumberRef number2, voi
 //printf("+ [%p] CFNumberCompare(%p, %p, %p)\n", pthread_self(), number1, number2, context);
     CFComparisonResult r = CFNumberCompare_new(number1, number2, context);
 //printf("  => %d\n", r);
+#if OLD_CRAP_TOO
+if (! number1->__old__ || !number2->__old__) {
+printf("*** Test skipped in CFNumberCompare for numbers %p %p\n", number1, number2);
+} else {
+CFComparisonResult r2 = CFNumberCompare_old(number1->__old__, number2->__old__, context);
+if (r2 != r) {
+CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberCompare: '%d' '%d'"), r2, r);  FAIL();
+}
+}
+#endif
     return r;
 }
 
+#if OLD_CRAP_TOO
+
+static const unsigned char __CFNumberCanonicalType[kCFNumberMaxType + 1] = {
+    0, kCFNumberSInt8Type, kCFNumberSInt16Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
+    kCFNumberSInt8Type, kCFNumberSInt16Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
+    kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberFloat32Type
+};
+
+static const unsigned char __CFNumberStorageType[kCFNumberMaxType + 1] = {
+    0, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
+    kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberSInt64Type, kCFNumberFloat32Type, kCFNumberFloat64Type,
+    kCFNumberSInt32Type, kCFNumberSInt32Type, kCFNumberFloat32Type
+};
+
+
+
+// Returns the type that is used to store the specified type
+static CFNumberType __CFNumberGetStorageTypeForType_old(CFNumberType type) {
+    return __CFNumberStorageType[type];
+}
+
+// Returns the canonical type used to represent the specified type
+static CFNumberType __CFNumberGetCanonicalTypeForType_old(CFNumberType type) {
+    return __CFNumberCanonicalType[type];
+}
+
+// Extracts and returns the type out of the CFNumber
+static CFNumberType __CFNumberGetType_old(struct __CFNumber_old * num) {
+    return __CFBitfieldGetValue(num->_base._cfinfo[CF_INFO_BITS], 4, 0);
+}
+
+// Returns true if the argument type is float or double
+static Boolean __CFNumberTypeIsFloat_old(CFNumberType type) {
+    return (type == kCFNumberFloat64Type) || (type == kCFNumberFloat32Type) || (type == kCFNumberDoubleType) || (type == kCFNumberFloatType);
+}
+
+// Returns the number of bytes necessary to store the specified type
+// Needs to handle all canonical types
+static CFIndex __CFNumberSizeOfType_old(CFNumberType type) {
+    switch (type) {
+        case kCFNumberSInt8Type:        return sizeof(int8_t);
+        case kCFNumberSInt16Type:       return sizeof(int16_t);
+        case kCFNumberSInt32Type:       return sizeof(SInt32);
+        case kCFNumberSInt64Type:       return sizeof(int64_t);
+        case kCFNumberFloat32Type:      return sizeof(Float32);
+        case kCFNumberFloat64Type:      return sizeof(Float64);
+        default:                        printf("*** WARNING: 0 size from __CFNumberSizeOfType_old \n"); return 0;
+    }
+}
+
+// Copies an external value of a given type into the appropriate slot in the union (does no type conversion)
+// Needs to handle all canonical types
+#define SET_VALUE(valueUnion, type, valuePtr)   \
+    switch (type) {                             \
+        case kCFNumberSInt8Type:        (valueUnion)->valSInt32 = *(int8_t *)(valuePtr); break; \
+        case kCFNumberSInt16Type:       (valueUnion)->valSInt32 = *(int16_t *)(valuePtr); break;        \
+        case kCFNumberSInt32Type:       (valueUnion)->valSInt32 = *(SInt32 *)(valuePtr); break; \
+        case kCFNumberSInt64Type:       (valueUnion)->valSInt64 = *(int64_t *)(valuePtr); break;        \
+        case kCFNumberFloat32Type:      (valueUnion)->valFloat32 = *(Float32 *)(valuePtr); break;       \
+        case kCFNumberFloat64Type:      (valueUnion)->valFloat64 = *(Float64 *)(valuePtr); break;       \
+        default: printf("*** WARNING: default case in SET_VALUE \n"); break; \
+    }
+
+// Casts the specified value into the specified type and copies it into the provided memory
+// Needs to handle all canonical types
+#define GET_VALUE(value, type, resultPtr)       \
+    switch (type) {                             \
+        case kCFNumberSInt8Type:        *(int8_t *)(resultPtr) = (int8_t)value; break;  \
+        case kCFNumberSInt16Type:       *(int16_t *)(resultPtr) = (int16_t)value; break;        \
+        case kCFNumberSInt32Type:       *(SInt32 *)(resultPtr) = (SInt32)value; break;  \
+        case kCFNumberSInt64Type:       *(int64_t *)(resultPtr) = (int64_t)value; break;        \
+        case kCFNumberFloat32Type:      *(Float32 *)(resultPtr) = (Float32)value; break;        \
+        case kCFNumberFloat64Type:      *(Float64 *)(resultPtr) = (Float64)value; break;        \
+        default: printf("*** WARNING: default case in GET_VALUE \n"); break; \
+    }
+
+// Extracts the stored type out of the union and copies it in the desired type into the provided memory
+// Needs to handle all storage types
+static void __CFNumberGetValue_old(const __CFNumberValue_old *value, CFNumberType numberType, CFNumberType typeToGet, void *valuePtr) {
+    switch (numberType) {
+        case kCFNumberSInt32Type:       GET_VALUE(value->valSInt32, typeToGet, valuePtr); break;
+        case kCFNumberSInt64Type:       GET_VALUE(value->valSInt64, typeToGet, valuePtr); break;
+        case kCFNumberFloat32Type:      GET_VALUE(value->valFloat32, typeToGet, valuePtr); break;
+        case kCFNumberFloat64Type:      GET_VALUE(value->valFloat64, typeToGet, valuePtr); break;
+        default: printf("*** WARNING: default case in __CFNumberGetValue_old \n"); break; \
+    }
+}
+
+// Sees if two value union structs have the same value (will do type conversion)
+static Boolean __CFNumberEqualValue_old(const __CFNumberValue_old *value1, CFNumberType type1, const __CFNumberValue_old *value2, CFNumberType type2) {
+    if (__CFNumberTypeIsFloat_old(type1) || __CFNumberTypeIsFloat_old(type2)) {
+        Float64 d1, d2;
+        __CFNumberGetValue_old(value1, type1, kCFNumberFloat64Type, &d1);
+        __CFNumberGetValue_old(value2, type2, kCFNumberFloat64Type, &d2);
+            if (isnan(d1) && isnan(d2)) return true;    // Not mathematically sound, but required
+        return d1 == d2;
+    } else {
+        int64_t i1, i2;
+        __CFNumberGetValue_old(value1, type1, kCFNumberSInt64Type, &i1);
+        __CFNumberGetValue_old(value2, type2, kCFNumberSInt64Type, &i2);
+        return i1 == i2;
+    }
+}
+
+static Boolean __CFNumberEqual_old(CFTypeRef cf1, CFTypeRef cf2) {
+    struct __CFNumber_old * number1 = (struct __CFNumber_old *)cf1;
+    struct __CFNumber_old * number2 = (struct __CFNumber_old *)cf2;
+    return __CFNumberEqualValue_old(&(number1->value), __CFNumberGetType_old(number1), &(number2->value), __CFNumberGetType_old(number2));
+}
+
+static CFHashCode __CFNumberHash_old(CFTypeRef cf) {
+    struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
+    switch (__CFNumberGetType_old((struct __CFNumber_old *)cf)) {
+        case kCFNumberSInt32Type: return _CFHashInt(number->value.valSInt32);
+        case kCFNumberSInt64Type: return _CFHashDouble((double)(number->value.valSInt64));
+        case kCFNumberFloat32Type: return _CFHashDouble((double)(number->value.valFloat32));
+        case kCFNumberFloat64Type: return _CFHashDouble((double)(number->value.valFloat64));
+        default: printf("*** WARNING default case in __CFNumberHash_old\n");
+            return 0;
+    }
+}
+
+#define BUFFER_SIZE 100
+#define emitChar(ch) \
+    {if (buf - stackBuf == BUFFER_SIZE) {CFStringAppendCharacters(mstr, stackBuf, BUFFER_SIZE); buf = stackBuf;} *buf++ = ch;}
+                 
+static void __CFNumberEmitInt64_old(CFMutableStringRef mstr, int64_t value, int32_t width, UniChar pad, bool explicitPlus) {
+    UniChar stackBuf[BUFFER_SIZE], *buf = stackBuf;
+    uint64_t uvalue, factor, tmp;
+    int32_t w;
+    bool neg;
+
+    neg = (value < 0) ? true : false;
+    uvalue = (neg) ? -value : value;
+    if (neg || explicitPlus) width--;
+    width--;
+    factor = 1;
+    tmp = uvalue;
+    while (9 < tmp) {
+        width--;
+        factor *= 10;
+        tmp /= 10;
+    }
+    for (w = 0; w < width; w++) emitChar(pad);
+    if (neg) {
+        emitChar('-');
+    } else if (explicitPlus) {
+        emitChar('+');
+    }
+    while (0 < factor) {
+        UniChar ch = '0' + (UniChar)(uvalue / factor);
+        uvalue %= factor;
+        emitChar(ch);
+        factor /= 10;
+    }
+    if (buf > stackBuf) CFStringAppendCharacters(mstr, stackBuf, buf - stackBuf);
+}
+
+static CFStringRef __CFNumberCopyDescription_old(CFTypeRef cf) {
+    struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
+    CFMutableStringRef mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+    CFStringAppendFormat(mstr, NULL, CFSTR("<CFNumber %p [%p]>{value = "), cf, CFGetAllocator(cf));
+    switch (__CFNumberGetType_old(number)) {
+    case kCFNumberSInt32Type:
+        __CFNumberEmitInt64_old(mstr, number->value.valSInt32, 0, ' ', true);
+        CFStringAppendFormat(mstr, NULL, CFSTR(", type = kCFNumberSInt32Type}"));
+        break;
+    case kCFNumberSInt64Type:
+        __CFNumberEmitInt64_old(mstr, number->value.valSInt64, 0, ' ', true);
+        CFStringAppendFormat(mstr, NULL, CFSTR(", type = kCFNumberSInt64Type}"));
+        break;
+    case kCFNumberFloat32Type:
+        // debugging formatting is intentionally more verbose and explicit about the value of the number
+        if (isnan(number->value.valFloat32)) {
+            CFStringAppend(mstr, CFSTR("nan"));
+        } else if (isinf(number->value.valFloat32)) {
+            CFStringAppend(mstr, (0.0f < number->value.valFloat32) ? CFSTR("+infinity") : CFSTR("-infinity"));
+        } else if (0.0f == number->value.valFloat32) {
+            CFStringAppend(mstr, (copysign(1.0, number->value.valFloat32) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
+        } else {
+            CFStringAppendFormat(mstr, NULL, CFSTR("%+.10f"), number->value.valFloat32);
+        }
+        CFStringAppend(mstr, CFSTR(", type = kCFNumberFloat32Type}"));
+        break;
+    case kCFNumberFloat64Type:
+        // debugging formatting is intentionally more verbose and explicit about the value of the number
+        if (isnan(number->value.valFloat64)) {
+            CFStringAppend(mstr, CFSTR("nan"));
+        } else if (isinf(number->value.valFloat64)) {
+            CFStringAppend(mstr, (0.0 < number->value.valFloat64) ? CFSTR("+infinity") : CFSTR("-infinity"));
+        } else if (0.0 == number->value.valFloat64) {
+            CFStringAppend(mstr, (copysign(1.0, number->value.valFloat64) < 0.0) ? CFSTR("-0.0") : CFSTR("+0.0"));
+        } else {
+            CFStringAppendFormat(mstr, NULL, CFSTR("%+.20f"), number->value.valFloat64);
+        }
+        CFStringAppend(mstr, CFSTR(", type = kCFNumberFloat64Type}"));
+        break;
+    default:
+        CFRelease(mstr);
+        return NULL;
+    }
+    return mstr;
+}
+
+// This function separated out from __CFNumberCopyFormattingDescription() so the plist creation can use it as well.
+
+__private_extern__ CFStringRef __CFNumberCopyFormattingDescriptionAsFloat64_old(CFTypeRef cf) {
+    double d;
+    CFNumberGetValue_old((struct __CFNumber_old *)cf, kCFNumberFloat64Type, &d);
+        if (isnan(d)) {
+            return (CFStringRef)CFRetain(CFSTR("nan"));
+        }
+        if (isinf(d)) {
+            return (CFStringRef)CFRetain((0.0 < d) ? CFSTR("+infinity") : CFSTR("-infinity"));
+        }
+        if (0.0 == d) {
+            return (CFStringRef)CFRetain(CFSTR("0.0"));
+        }
+        // if %g is used here, need to use DBL_DIG + 2 on Mac OS X, but %f needs +1
+        return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%.*g"), DBL_DIG + 2, d);
+}
+
+static CFStringRef __CFNumberCopyFormattingDescription_old(CFTypeRef cf, CFDictionaryRef formatOptions) {
+    struct __CFNumber_old * number = (struct __CFNumber_old *)cf;
+    CFMutableStringRef mstr;
+    int64_t value;
+    switch (__CFNumberGetType_old(number)) {
+    case kCFNumberSInt32Type:
+    case kCFNumberSInt64Type: 
+        value = (__CFNumberGetType_old(number) == kCFNumberSInt32Type) ? number->value.valSInt32 : number->value.valSInt64;
+        mstr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+        __CFNumberEmitInt64_old(mstr, value, 0, ' ', false);
+        return mstr;
+    case kCFNumberFloat32Type:
+            if (isnan(number->value.valFloat32)) {
+                return (CFStringRef)CFRetain(CFSTR("nan"));
+            }
+            if (isinf(number->value.valFloat32)) {
+                return (CFStringRef)CFRetain((0.0f < number->value.valFloat32) ? CFSTR("+infinity") : CFSTR("-infinity"));
+            }
+            if (0.0f == number->value.valFloat32) {
+                return (CFStringRef)CFRetain(CFSTR("0.0"));
+            }
+            // if %g is used here, need to use FLT_DIG + 2 on Mac OS X, but %f needs +1
+            return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%.*g"), FLT_DIG + 2, number->value.valFloat32);
+    case kCFNumberFloat64Type:
+        return __CFNumberCopyFormattingDescriptionAsFloat64_old(number);
+        break;
+    default:
+        return NULL;
+    }
+}
+
+
+
+static struct __CFNumber_old * CFNumberCreate_old(CFAllocatorRef allocator, CFNumberType type, const void *valuePtr) {
+    struct __CFNumber_old * num;
+    CFNumberType equivType, storageType;
+
+if (type == 17) {
+CFSInt128Struct *s = valuePtr;
+s->high = (int64_t)s->low;
+type = kCFNumberSInt64Type;
+}
+
+    
+    equivType = __CFNumberGetCanonicalTypeForType_old(type);
+
+    storageType = __CFNumberGetStorageTypeForType_old(type);
+
+    num = (struct __CFNumber_old *)_CFRuntimeCreateInstance(allocator, __kCFNumberTypeID, __CFNumberSizeOfType_old(storageType), NULL);
+    if (NULL == num) {
+        return NULL;
+    }
+    SET_VALUE((__CFNumberValue_old *)&(num->value), equivType, valuePtr);
+    __CFBitfieldSetValue(((struct __CFNumber_old *)num)->_base._cfinfo[CF_INFO_BITS], 6, 0, (uint8_t)storageType);
+    
+if (__CFNumberGetType_old(num) == 0) printf("*** ERROR: new number %p type is 0 (%d)\n", num, storageType);
+    return num;
+}
+
+static CFNumberType CFNumberGetType_old(struct __CFNumber_old * number) {
+
+    return __CFNumberGetType_old(number);
+}
+
+static CFIndex CFNumberGetByteSize_old(struct __CFNumber_old * number) {
+    return __CFNumberSizeOfType_old(CFNumberGetType_old(number));
+}
+
+static Boolean CFNumberIsFloatType_old(struct __CFNumber_old * number) {
+    return __CFNumberTypeIsFloat_old(CFNumberGetType_old(number));
+}
+
+static Boolean CFNumberGetValue_old(struct __CFNumber_old * number, CFNumberType type, void *valuePtr) {
+    uint8_t localMemory[sizeof(__CFNumberValue_old)];
+    __CFNumberValue_old localValue;
+    CFNumberType numType;
+    CFNumberType storageTypeForType;
+
+if (type == 17) type = kCFNumberSInt64Type;
+
+    storageTypeForType = __CFNumberGetStorageTypeForType_old(type);
+    type = __CFNumberGetCanonicalTypeForType_old(type);
+    if (!valuePtr) valuePtr = &localMemory;
+
+    numType = __CFNumberGetType_old(number);
+    __CFNumberGetValue_old((__CFNumberValue_old *)&(number->value), numType, type, valuePtr);
+
+    // If the types match, then we're fine!
+    if (numType == storageTypeForType) return true;
+
+    // Test to see if the returned value is intact...
+    SET_VALUE(&localValue, type, valuePtr);
+    return __CFNumberEqualValue_old(&localValue, storageTypeForType, &(number->value), numType);
+}
+
+static CFComparisonResult CFNumberCompare_old(struct __CFNumber_old * number1, struct __CFNumber_old * number2, void *context) {
+    CFNumberType type1, type2;
+
+
+    type1 = __CFNumberGetType_old(number1);
+    type2 = __CFNumberGetType_old(number2);
+
+    if (__CFNumberTypeIsFloat_old(type1) || __CFNumberTypeIsFloat_old(type2)) {
+        Float64 d1, d2;
+        double s1, s2;
+        __CFNumberGetValue_old(&(number1->value), type1, kCFNumberFloat64Type, &d1);
+        __CFNumberGetValue_old(&(number2->value), type2, kCFNumberFloat64Type, &d2);
+        s1 = copysign(1.0, d1);
+        s2 = copysign(1.0, d2);
+        if (isnan(d1) && isnan(d2)) return kCFCompareEqualTo;
+        if (isnan(d1)) return (s2 < 0.0) ? kCFCompareGreaterThan : kCFCompareLessThan;
+        if (isnan(d2)) return (s1 < 0.0) ? kCFCompareLessThan : kCFCompareGreaterThan;
+        // at this point, we know we don't have any NaNs
+        if (s1 < s2) return kCFCompareLessThan;
+        if (s2 < s1) return kCFCompareGreaterThan;
+        // at this point, we know the signs are the same; do not combine these tests
+        if (d1 < d2) return kCFCompareLessThan;
+        if (d2 < d1) return kCFCompareGreaterThan;
+        return kCFCompareEqualTo;
+    } else {
+        int64_t i1, i2;
+        __CFNumberGetValue_old(&(number1->value), type1, kCFNumberSInt64Type, &i1);
+        __CFNumberGetValue_old(&(number2->value), type2, kCFNumberSInt64Type, &i2);
+        return (i1 > i2) ? kCFCompareGreaterThan : ((i1 < i2) ? kCFCompareLessThan : kCFCompareEqualTo);
+    }
+}
+
+#endif
+
+
 #undef __CFAssertIsBoolean
 #undef __CFAssertIsNumber
 #undef __CFAssertIsValidNumberType
index 55e900173e6a26e98607d606f2d170abba91ba33..4352b0562a2f4522b5101b72d78354ece0885c2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFNumber.h
-       Copyright (c) 1999-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFNUMBER__)
@@ -62,7 +62,7 @@ enum {
     kCFNumberDoubleType = 13,
     /* Other */
     kCFNumberCFIndexType = 14,
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
     kCFNumberNSIntegerType = 15,
     kCFNumberCGFloatType = 16,
     kCFNumberMaxType = 16
index 12e2a635c3e2ad153f312099dde37e4cfb541be6..cde8c2b303590310ca9fe414721d399dbc7e1dd9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFNumberFormatter.c
-       Copyright 2002-2003, Apple, Inc. All rights reserved.
+       Copyright (c) 2002-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #include <CoreFoundation/CFNumberFormatter.h>
 #include "CFInternal.h"
+#include "CFLocaleInternal.h"
 #include <unicode/unum.h>
 #include <unicode/ucurr.h>
 #include <math.h>
 #include <float.h>
 
 static void __CFNumberFormatterCustomize(CFNumberFormatterRef formatter);
+static CFStringRef __CFNumberFormatterCreateCompressedString(CFStringRef inString, Boolean isFormat, CFRange *rangep);
+static UErrorCode __CFNumberFormatterApplyPattern(CFNumberFormatterRef formatter, CFStringRef pattern);
 
 #define BUFFER_SIZE 768
 
@@ -43,8 +46,11 @@ struct __CFNumberFormatter {
     CFNumberFormatterStyle _style;
     CFStringRef _format;       // NULL for RBNFs
     CFStringRef _defformat;
+    CFStringRef _compformat;
     CFNumberRef _multiplier;
     CFStringRef _zeroSym;
+    Boolean _isLenient;
+    Boolean _userSetMultiplier;
 };
 
 static CFStringRef __CFNumberFormatterCopyDescription(CFTypeRef cf) {
@@ -58,6 +64,7 @@ static void __CFNumberFormatterDeallocate(CFTypeRef cf) {
     if (formatter->_locale) CFRelease(formatter->_locale);
     if (formatter->_format) CFRelease(formatter->_format);
     if (formatter->_defformat) CFRelease(formatter->_defformat);
+    if (formatter->_compformat) CFRelease(formatter->_compformat);
     if (formatter->_multiplier) CFRelease(formatter->_multiplier);
     if (formatter->_zeroSym) CFRelease(formatter->_zeroSym);
 }
@@ -99,8 +106,11 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR
     memory->_locale = NULL;
     memory->_format = NULL;
     memory->_defformat = NULL;
+    memory->_compformat = NULL;
     memory->_multiplier = NULL;
     memory->_zeroSym = NULL;
+    memory->_isLenient = false;
+    memory->_userSetMultiplier = false;
     if (NULL == locale) locale = CFLocaleGetSystem();
     memory->_style = style;
     uint32_t ustyle;
@@ -153,6 +163,7 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR
        }
     }
     memory->_defformat = memory->_format ? (CFStringRef)CFRetain(memory->_format) : NULL;
+    memory->_compformat = memory->_format ? __CFNumberFormatterCreateCompressedString(memory->_format, true, NULL) : NULL;
     if (kCFNumberFormatterSpellOutStyle != memory->_style) {
        int32_t n = unum_getAttribute(memory->_nf, UNUM_MULTIPLIER);
        if (1 != n) {
@@ -160,6 +171,7 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR
            unum_setAttribute(memory->_nf, UNUM_MULTIPLIER, 1);
        }
     }
+    unum_setAttribute(memory->_nf, UNUM_LENIENT_PARSE, 0);
     return (CFNumberFormatterRef)memory;
 }
 
@@ -217,15 +229,7 @@ static void __substituteFormatStringFromPrefsNF(CFNumberFormatterRef formatter)
                        CFRange result;
                        if (CFStringFindWithOptions(formatString, numberString, CFRangeMake(0, formatter_len), 0, &result)) {
                            CFStringReplace(formatString, result, pref);
-                           int32_t new_len = CFStringGetLength(formatString);
-                           STACK_BUFFER_DECL(UChar, new_buffer, new_len);
-                           const UChar *new_ustr = (const UChar *)CFStringGetCharactersPtr(formatString);
-                           if (NULL == new_ustr) {
-                               CFStringGetCharacters(formatString, CFRangeMake(0, new_len), (UniChar *)new_buffer);
-                               new_ustr = new_buffer;
-                           }
-                           status = U_ZERO_ERROR;
-                           unum_applyPattern(formatter->_nf, false, new_ustr, new_len, NULL, &status);
+                           __CFNumberFormatterApplyPattern(formatter, formatString);
                        }
                        CFRelease(formatString);
                    }
@@ -237,6 +241,40 @@ static void __substituteFormatStringFromPrefsNF(CFNumberFormatterRef formatter)
     }
 }
 
+static UniChar __CFNumberFormatterNormalizeCharacter(UniChar c) {
+    if (CFCharacterSetIsCharacterMember(CFCharacterSetGetPredefined(kCFCharacterSetWhitespace), c)) {
+       return ' ';
+    } else {
+       return c;
+    }
+}
+
+/* Attempt to match the unimplemented lenient parsing behavior described at http://www.unicode.org/reports/tr35/#Lenient_Parsing -- specifically any whitespace is ignored that does not exist between two letters or two numbers, and no-break spaces map to spaces. */
+static CFStringRef __CFNumberFormatterCreateCompressedString(CFStringRef inString, Boolean isFormat, CFRange *rangep) {
+    if (!inString) return NULL;
+    CFRange range = { 0, 0 };
+    if (rangep) {
+       range = *rangep;
+    } else {
+       range.length = CFStringGetLength(inString);
+    }
+    CFMutableStringRef outString = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+    CFCharacterSetRef letters = CFCharacterSetGetPredefined(kCFCharacterSetLetter);
+    CFCharacterSetRef numbers = CFCharacterSetGetPredefined(kCFCharacterSetDecimalDigit);
+    UniChar prevCh = 0, nextCh = 0;
+    Boolean inQuote = false;
+    for (CFIndex in_idx = range.location; in_idx < range.location + range.length; in_idx++) {
+        UniChar ch = __CFNumberFormatterNormalizeCharacter(CFStringGetCharacterAtIndex(inString, in_idx));
+       nextCh = (in_idx+1 < range.length) ? CFStringGetCharacterAtIndex(inString, in_idx+1) : 0;
+       if (isFormat && ch == '\'') inQuote = !inQuote;
+       if (inQuote || ch != ' ' || (CFCharacterSetIsCharacterMember(letters, prevCh) && CFCharacterSetIsCharacterMember(letters, nextCh)) || (CFCharacterSetIsCharacterMember(numbers, prevCh) && CFCharacterSetIsCharacterMember(numbers, nextCh))) {
+           CFStringAppendCharacters(outString, &ch, 1);
+           prevCh = ch;
+       }
+    }
+    return outString;
+}
+
 static void __CFNumberFormatterApplySymbolPrefs(const void *key, const void *value, void *context) {
     if (CFGetTypeID(key) == CFStringGetTypeID() && CFGetTypeID(value) == CFStringGetTypeID()) {
        CFNumberFormatterRef formatter = (CFNumberFormatterRef)context;
@@ -254,6 +292,35 @@ static void __CFNumberFormatterApplySymbolPrefs(const void *key, const void *val
    }
 }
 
+static UErrorCode __CFNumberFormatterApplyPattern(CFNumberFormatterRef formatter, CFStringRef pattern) {
+    CFIndex cnt = CFStringGetLength(pattern);
+    STACK_BUFFER_DECL(UChar, ubuffer, cnt);
+    const UChar *ustr = (const UChar *)CFStringGetCharactersPtr(pattern);
+    if (NULL == ustr) {
+       CFStringGetCharacters(pattern, CFRangeMake(0, cnt), (UniChar *)ubuffer);
+       ustr = ubuffer;
+    }
+    UErrorCode status = U_ZERO_ERROR;
+    unum_applyPattern(formatter->_nf, false, ustr, cnt, NULL, &status);
+
+    // unum_applyPattern() may have magically changed other attributes based on
+    // the contents of the format string; we simply expose that ICU behavior, except
+    // for UNUM_MULTIPLIER, which we re-read and reset, like we did at initialization
+    // time though any user-set multiplier state takes precedence.
+    if (formatter->_userSetMultiplier) {
+       unum_setAttribute(formatter->_nf, UNUM_MULTIPLIER, 1);
+    } else {
+       if (formatter->_multiplier) CFRelease(formatter->_multiplier);
+        formatter->_multiplier = NULL;
+        int32_t n = unum_getAttribute(formatter->_nf, UNUM_MULTIPLIER);
+        if (1 != n) {
+           formatter->_multiplier = CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
+           unum_setAttribute(formatter->_nf, UNUM_MULTIPLIER, 1);
+        }
+    }
+    return status;
+}
+
 static void __CFNumberFormatterCustomize(CFNumberFormatterRef formatter) {
     __substituteFormatStringFromPrefsNF(formatter);
     CFDictionaryRef prefs = __CFLocaleGetPrefs(formatter->_locale);
@@ -285,9 +352,13 @@ CFStringRef CFNumberFormatterGetFormat(CFNumberFormatterRef formatter) {
     }
     if (newString && !formatter->_format) {
        formatter->_format = newString;
+       if (formatter->_compformat) CFRelease(formatter->_compformat);
+       formatter->_compformat = __CFNumberFormatterCreateCompressedString(formatter->_format, true, NULL);
     } else if (newString && !CFEqual(newString, formatter->_format)) {
        CFRelease(formatter->_format);
        formatter->_format = newString;
+       if (formatter->_compformat) CFRelease(formatter->_compformat);
+       formatter->_compformat = __CFNumberFormatterCreateCompressedString(formatter->_format, true, NULL);
     } else if (newString) {
        CFRelease(newString);
     }
@@ -301,21 +372,16 @@ void CFNumberFormatterSetFormat(CFNumberFormatterRef formatter, CFStringRef form
     CFIndex cnt = CFStringGetLength(formatString);
     CFAssert1(cnt <= 1024, __kCFLogAssertion, "%s(): format string too long", __PRETTY_FUNCTION__);
     if ((!formatter->_format || !CFEqual(formatter->_format, formatString)) && cnt <= 1024) {
-       STACK_BUFFER_DECL(UChar, ubuffer, cnt);
-       const UChar *ustr = (const UChar *)CFStringGetCharactersPtr(formatString);
-       if (NULL == ustr) {
-           CFStringGetCharacters(formatString, CFRangeMake(0, cnt), (UniChar *)ubuffer);
-           ustr = ubuffer;
-       }
-       UErrorCode status = U_ZERO_ERROR;
-       unum_applyPattern(formatter->_nf, false, ustr, cnt, NULL, &status);
+       UErrorCode status = __CFNumberFormatterApplyPattern(formatter, formatString);
        if (U_SUCCESS(status)) {
-           if (formatter->_format) CFRelease(formatter->_format);
            UChar ubuffer2[BUFFER_SIZE];
            status = U_ZERO_ERROR;
            int32_t ret = unum_toPattern(formatter->_nf, false, ubuffer2, BUFFER_SIZE, &status);
            if (U_SUCCESS(status) && ret <= BUFFER_SIZE) {
+               if (formatter->_format) CFRelease(formatter->_format);
                formatter->_format = CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer2, ret);
+               if (formatter->_compformat) CFRelease(formatter->_compformat);
+               formatter->_compformat = __CFNumberFormatterCreateCompressedString(formatter->_format, true, NULL);
            }
        }
     }
@@ -335,7 +401,14 @@ CFStringRef CFNumberFormatterCreateStringWithNumber(CFAllocatorRef allocator, CF
 #define FORMAT(T, FUNC)                                                        \
        T value = *(T *)valuePtr;                                       \
        if (0 == value && formatter->_zeroSym) { return (CFStringRef)CFRetain(formatter->_zeroSym); }   \
-       if (1.0 != multiplier) value = (T)(value * multiplier);         \
+       if (1.0 != multiplier) {                                        \
+               double dummy;                                           \
+               if (modf(multiplier, &dummy) < FLT_EPSILON) { /* float epsilon specifically chosen cuz it is a bit bigger */    \
+                       value = value * (T)floor(multiplier);           \
+               } else {                                                \
+                       value = (T)(value * multiplier);                \
+               }                                                       \
+       }                                                               \
        status = U_ZERO_ERROR;                                          \
        used = FUNC(formatter->_nf, value, ubuffer, cnt, NULL, &status); \
        if (status == U_BUFFER_OVERFLOW_ERROR || cnt < used) {          \
@@ -406,25 +479,41 @@ CFNumberRef CFNumberFormatterCreateNumberFromString(CFAllocatorRef allocator, CF
 Boolean CFNumberFormatterGetValueFromString(CFNumberFormatterRef formatter, CFStringRef string, CFRange *rangep, CFNumberType numberType, void *valuePtr) {
     __CFGenericValidateType(formatter, CFNumberFormatterGetTypeID());
     __CFGenericValidateType(string, CFStringGetTypeID());
-    Boolean isZero = false;
+    CFStringRef stringToParse = formatter->_isLenient ? __CFNumberFormatterCreateCompressedString(string, false, rangep) : (CFStringRef)CFRetain(string);
     CFRange range = {0, 0};
-    if (rangep) {
-       range = *rangep;
+    if(formatter->_isLenient) {
+        range.length = CFStringGetLength(stringToParse);
     } else {
-        range.length = CFStringGetLength(string);
+        if (rangep) {
+            range = *rangep;
+        } else {
+            range.length = CFStringGetLength(stringToParse);
+        }
+        // unum_parse chokes on leading whitespace
+        CFCharacterSetRef whitespace = CFCharacterSetGetPredefined(kCFCharacterSetWhitespace);
+        while(range.length > 0 && CFCharacterSetIsCharacterMember(whitespace, CFStringGetCharacterAtIndex(stringToParse, range.location))) {
+            range.location++;
+            range.length--;
+        }
     }
-    if (formatter->_zeroSym && kCFCompareEqualTo == CFStringCompareWithOptions(string, formatter->_zeroSym, range, 0)) {
-       isZero = true;
+    Boolean isZero = false;
+    if (formatter->_zeroSym) {
+       CFStringRef zeroSym = formatter->_isLenient ? __CFNumberFormatterCreateCompressedString(formatter->_zeroSym, false, NULL) : (CFStringRef)CFRetain(formatter->_zeroSym);
+       if (kCFCompareEqualTo == CFStringCompare(stringToParse, zeroSym, 0)) {
+           isZero = true;
+       }
+       CFRelease(zeroSym);
     }
     if (1024 < range.length) range.length = 1024;
-    const UChar *ustr = (const UChar *)CFStringGetCharactersPtr(string);
+    const UChar *ustr = (const UChar *)CFStringGetCharactersPtr(stringToParse);
     STACK_BUFFER_DECL(UChar, ubuffer, (NULL == ustr) ? range.length : 1);
     if (NULL == ustr) {
-       CFStringGetCharacters(string, range, (UniChar *)ubuffer);
+       CFStringGetCharacters(stringToParse, range, (UniChar *)ubuffer);
        ustr = ubuffer;
-    } else {
-        ustr += range.location;
+    } else if (!formatter->_isLenient) {
+       ustr += range.location;
     }
+    if (formatter->_isLenient) __CFNumberFormatterApplyPattern(formatter, formatter->_compformat);
     Boolean integerOnly = 1;
     switch (numberType) {
     case kCFNumberSInt8Type: case kCFNumberCharType:
@@ -452,7 +541,20 @@ Boolean CFNumberFormatterGetValueFromString(CFNumberFormatterRef formatter, CFSt
            dretd = unum_parseDouble(formatter->_nf, ustr, range.length, &dpos, &status);
        }
     }
-    if (rangep) rangep->length = dpos;
+    if (formatter->_isLenient) {
+       if (rangep) {
+           CFIndex uncompEnd = rangep->location + rangep->length;
+           CFIndex uncompIdx = rangep->location;
+           for (CFIndex compIdx = 0; compIdx < dpos && uncompIdx < uncompEnd; compIdx++, uncompIdx++) {
+               while (uncompIdx < uncompEnd && ustr[compIdx] != __CFNumberFormatterNormalizeCharacter(CFStringGetCharacterAtIndex(string, uncompIdx))) uncompIdx++;
+           }
+           rangep->length = uncompIdx - rangep->location;
+       }
+       __CFNumberFormatterApplyPattern(formatter, formatter->_format);
+    } else if (rangep) {
+        rangep->length = dpos + (range.location - rangep->location);
+    }
+    CFRelease(stringToParse);
     if (U_FAILURE(status)) {
        return false;
     }
@@ -519,195 +621,203 @@ void CFNumberFormatterSetProperty(CFNumberFormatterRef formatter, CFStringRef ke
     CFIndex cnt;
     __CFGenericValidateType(formatter, CFNumberFormatterGetTypeID());
     __CFGenericValidateType(key, CFStringGetTypeID());
-    if (kCFNumberFormatterCurrencyCode == key) {
+    if (kCFNumberFormatterCurrencyCodeKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setTextAttribute(formatter->_nf, UNUM_CURRENCY_CODE, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterDecimalSeparator == key) {
+    } else if (kCFNumberFormatterDecimalSeparatorKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_DECIMAL_SEPARATOR_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterCurrencyDecimalSeparator == key) {
+    } else if (kCFNumberFormatterCurrencyDecimalSeparatorKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_MONETARY_SEPARATOR_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterAlwaysShowDecimalSeparator == key) {
+    } else if (kCFNumberFormatterAlwaysShowDecimalSeparatorKey == key) {
        __CFGenericValidateType(value, CFBooleanGetTypeID());
        unum_setAttribute(formatter->_nf, UNUM_DECIMAL_ALWAYS_SHOWN, (kCFBooleanTrue == value));
-    } else if (kCFNumberFormatterGroupingSeparator == key) {
+    } else if (kCFNumberFormatterGroupingSeparatorKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_GROUPING_SEPARATOR_SYMBOL, (const UChar *)ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterUseGroupingSeparator == key) {
+    } else if (kCFNumberFormatterUseGroupingSeparatorKey == key) {
        __CFGenericValidateType(value, CFBooleanGetTypeID());
        unum_setAttribute(formatter->_nf, UNUM_GROUPING_USED, (kCFBooleanTrue == value));
-    } else if (kCFNumberFormatterPercentSymbol == key) {
+    } else if (kCFNumberFormatterPercentSymbolKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_PERCENT_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterZeroSymbol == key) {
+    } else if (kCFNumberFormatterZeroSymbolKey == key) {
         __CFGenericValidateType(value, CFStringGetTypeID());
         CFStringRef old = formatter->_zeroSym;
         formatter->_zeroSym = value ? (CFStringRef)CFRetain(value) : NULL;
         if (old) CFRelease(old);
-    } else if (kCFNumberFormatterNaNSymbol == key) {
+    } else if (kCFNumberFormatterNaNSymbolKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_NAN_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterInfinitySymbol == key) {
+    } else if (kCFNumberFormatterInfinitySymbolKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_INFINITY_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterMinusSign == key) {
+    } else if (kCFNumberFormatterMinusSignKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_MINUS_SIGN_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterPlusSign == key) {
+    } else if (kCFNumberFormatterPlusSignKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_PLUS_SIGN_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterCurrencySymbol == key) {
+    } else if (kCFNumberFormatterCurrencySymbolKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_CURRENCY_SYMBOL, (const UChar *)ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterExponentSymbol == key) {
+    } else if (kCFNumberFormatterExponentSymbolKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setSymbol(formatter->_nf, UNUM_EXPONENTIAL_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterMinIntegerDigits == key) {
+    } else if (kCFNumberFormatterMinIntegerDigitsKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_MIN_INTEGER_DIGITS, n);
-    } else if (kCFNumberFormatterMaxIntegerDigits == key) {
+    } else if (kCFNumberFormatterMaxIntegerDigitsKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_MAX_INTEGER_DIGITS, n);
-    } else if (kCFNumberFormatterMinFractionDigits == key) {
+    } else if (kCFNumberFormatterMinFractionDigitsKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_MIN_FRACTION_DIGITS, n);
-    } else if (kCFNumberFormatterMaxFractionDigits == key) {
+    } else if (kCFNumberFormatterMaxFractionDigitsKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_MAX_FRACTION_DIGITS, n);
-    } else if (kCFNumberFormatterGroupingSize == key) {
+    } else if (kCFNumberFormatterGroupingSizeKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_GROUPING_SIZE, n);
-    } else if (kCFNumberFormatterSecondaryGroupingSize == key) {
+    } else if (kCFNumberFormatterSecondaryGroupingSizeKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_SECONDARY_GROUPING_SIZE, n);
-    } else if (kCFNumberFormatterRoundingMode == key) {
+    } else if (kCFNumberFormatterRoundingModeKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_ROUNDING_MODE, n);
-    } else if (kCFNumberFormatterRoundingIncrement == key) {
+    } else if (kCFNumberFormatterRoundingIncrementKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberDoubleType, &d);
        unum_setDoubleAttribute(formatter->_nf, UNUM_ROUNDING_INCREMENT, d);
-    } else if (kCFNumberFormatterFormatWidth == key) {
+    } else if (kCFNumberFormatterFormatWidthKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_FORMAT_WIDTH, n);
-    } else if (kCFNumberFormatterPaddingPosition == key) {
+    } else if (kCFNumberFormatterPaddingPositionKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_PADDING_POSITION, n);
-    } else if (kCFNumberFormatterPaddingCharacter == key) {
+    } else if (kCFNumberFormatterPaddingCharacterKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setTextAttribute(formatter->_nf, UNUM_PADDING_CHARACTER, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterDefaultFormat == key) {
+    } else if (kCFNumberFormatterDefaultFormatKey == key) {
        // read-only attribute
-    } else if (kCFNumberFormatterMultiplier == key) {
+    } else if (kCFNumberFormatterMultiplierKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
         CFNumberRef old = formatter->_multiplier;
         formatter->_multiplier = value ? (CFNumberRef)CFRetain(value) : NULL;
+       formatter->_userSetMultiplier = value ? true : false;
         if (old) CFRelease(old);
-    } else if (kCFNumberFormatterPositivePrefix == key) {
+    } else if (kCFNumberFormatterPositivePrefixKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setTextAttribute(formatter->_nf, UNUM_POSITIVE_PREFIX, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterPositiveSuffix == key) {
+    } else if (kCFNumberFormatterPositiveSuffixKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setTextAttribute(formatter->_nf, UNUM_POSITIVE_SUFFIX, (const UChar *)ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterNegativePrefix == key) {
+    } else if (kCFNumberFormatterNegativePrefixKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setTextAttribute(formatter->_nf, UNUM_NEGATIVE_PREFIX, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterNegativeSuffix == key) {
+    } else if (kCFNumberFormatterNegativeSuffixKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
        cnt = CFStringGetLength((CFStringRef)value);
        if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
        CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
        unum_setTextAttribute(formatter->_nf, UNUM_NEGATIVE_SUFFIX, (const UChar *)ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterPerMillSymbol == key) {
+    } else if (kCFNumberFormatterPerMillSymbolKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
         cnt = CFStringGetLength((CFStringRef)value);
         if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
         CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
         unum_setSymbol(formatter->_nf, UNUM_PERMILL_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterInternationalCurrencySymbol == key) {
+    } else if (kCFNumberFormatterInternationalCurrencySymbolKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
         cnt = CFStringGetLength((CFStringRef)value);
         if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
         CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
         unum_setSymbol(formatter->_nf, UNUM_INTL_CURRENCY_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterCurrencyGroupingSeparator == key) {
+    } else if (kCFNumberFormatterCurrencyGroupingSeparatorKey == key) {
        __CFGenericValidateType(value, CFStringGetTypeID());
         cnt = CFStringGetLength((CFStringRef)value);
         if (BUFFER_SIZE < cnt) cnt = BUFFER_SIZE;
         CFStringGetCharacters((CFStringRef)value, CFRangeMake(0, cnt), (UniChar *)ubuffer);
         unum_setSymbol(formatter->_nf, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, ubuffer, cnt, &status);
-    } else if (kCFNumberFormatterIsLenient == key) {
+    } else if (kCFNumberFormatterIsLenientKey == key) {
        __CFGenericValidateType(value, CFBooleanGetTypeID());
+       formatter->_isLenient = (kCFBooleanTrue == value);
        unum_setAttribute(formatter->_nf, UNUM_LENIENT_PARSE, (kCFBooleanTrue == value));
-    } else if (kCFNumberFormatterUseSignificantDigits == key) {
+    } else if (kCFNumberFormatterUseSignificantDigitsKey == key) {
        __CFGenericValidateType(value, CFBooleanGetTypeID());
        unum_setAttribute(formatter->_nf, UNUM_SIGNIFICANT_DIGITS_USED, (kCFBooleanTrue == value));
-    } else if (kCFNumberFormatterMinSignificantDigits == key) {
+    } else if (kCFNumberFormatterMinSignificantDigitsKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_MIN_SIGNIFICANT_DIGITS, n);
-    } else if (kCFNumberFormatterMaxSignificantDigits == key) {
+    } else if (kCFNumberFormatterMaxSignificantDigitsKey == key) {
        __CFGenericValidateType(value, CFNumberGetTypeID());
        CFNumberGetValue((CFNumberRef)value, kCFNumberSInt32Type, &n);
        unum_setAttribute(formatter->_nf, UNUM_MAX_SIGNIFICANT_DIGITS, n);
     } else {
        CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key);
     }
+    if (_CFExecutableLinkedOnOrAfter(CFSystemVersionSnowLeopard)) {
+        // do a dummy call to CFNumberFormatterGetFormat() after changing an attribute because
+        // ICU sometimes changes the pattern due to a property change, and we need to poke
+        // unum_toPattern() and also update our own variables
+        CFNumberFormatterGetFormat(formatter);
+    }
 }
 
 CFTypeRef CFNumberFormatterCopyProperty(CFNumberFormatterRef formatter, CFStringRef key) {
@@ -718,7 +828,7 @@ CFTypeRef CFNumberFormatterCopyProperty(CFNumberFormatterRef formatter, CFString
     CFIndex cnt;
     __CFGenericValidateType(formatter, CFNumberFormatterGetTypeID());
     __CFGenericValidateType(key, CFStringGetTypeID());
-    if (kCFNumberFormatterCurrencyCode == key) {
+    if (kCFNumberFormatterCurrencyCodeKey == key) {
        cnt = unum_getTextAttribute(formatter->_nf, UNUM_CURRENCY_CODE, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt == 0) {
            CFStringRef localeName = CFLocaleGetIdentifier(formatter->_locale);
@@ -740,178 +850,176 @@ CFTypeRef CFNumberFormatterCopyProperty(CFNumberFormatterRef formatter, CFString
        if (U_SUCCESS(status) && 0 < cnt && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterDecimalSeparator == key) {
+    } else if (kCFNumberFormatterDecimalSeparatorKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_DECIMAL_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterCurrencyDecimalSeparator == key) {
+    } else if (kCFNumberFormatterCurrencyDecimalSeparatorKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_MONETARY_SEPARATOR_SYMBOL, (UChar *)ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterAlwaysShowDecimalSeparator == key) {
+    } else if (kCFNumberFormatterAlwaysShowDecimalSeparatorKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_DECIMAL_ALWAYS_SHOWN);
        if (1) {
            return CFRetain(n ? kCFBooleanTrue : kCFBooleanFalse);
        }
-    } else if (kCFNumberFormatterGroupingSeparator == key) {
+    } else if (kCFNumberFormatterGroupingSeparatorKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_GROUPING_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterUseGroupingSeparator == key) {
+    } else if (kCFNumberFormatterUseGroupingSeparatorKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_GROUPING_USED);
        if (1) {
            return CFRetain(n ? kCFBooleanTrue : kCFBooleanFalse);
        }
-   } else if (kCFNumberFormatterPercentSymbol == key) {
+   } else if (kCFNumberFormatterPercentSymbolKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_PERCENT_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterZeroSymbol == key) {
+    } else if (kCFNumberFormatterZeroSymbolKey == key) {
         return formatter->_zeroSym ? CFRetain(formatter->_zeroSym) : NULL;
-    } else if (kCFNumberFormatterNaNSymbol == key) {
+    } else if (kCFNumberFormatterNaNSymbolKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_NAN_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterInfinitySymbol == key) {
+    } else if (kCFNumberFormatterInfinitySymbolKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_INFINITY_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterMinusSign == key) {
+    } else if (kCFNumberFormatterMinusSignKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_MINUS_SIGN_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterPlusSign == key) {
+    } else if (kCFNumberFormatterPlusSignKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_PLUS_SIGN_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterCurrencySymbol == key) {
+    } else if (kCFNumberFormatterCurrencySymbolKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_CURRENCY_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterExponentSymbol == key) {
+    } else if (kCFNumberFormatterExponentSymbolKey == key) {
        cnt = unum_getSymbol(formatter->_nf, UNUM_EXPONENTIAL_SYMBOL, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterMinIntegerDigits == key) {
+    } else if (kCFNumberFormatterMinIntegerDigitsKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_MIN_INTEGER_DIGITS);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterMaxIntegerDigits == key) {
+    } else if (kCFNumberFormatterMaxIntegerDigitsKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_MAX_INTEGER_DIGITS);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterMinFractionDigits == key) {
+    } else if (kCFNumberFormatterMinFractionDigitsKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_MIN_FRACTION_DIGITS);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterMaxFractionDigits == key) {
+    } else if (kCFNumberFormatterMaxFractionDigitsKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_MAX_FRACTION_DIGITS);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterGroupingSize == key) {
+    } else if (kCFNumberFormatterGroupingSizeKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_GROUPING_SIZE);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterSecondaryGroupingSize == key) {
+    } else if (kCFNumberFormatterSecondaryGroupingSizeKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_SECONDARY_GROUPING_SIZE);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterRoundingMode == key) {
+    } else if (kCFNumberFormatterRoundingModeKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_ROUNDING_MODE);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterRoundingIncrement == key) {
+    } else if (kCFNumberFormatterRoundingIncrementKey == key) {
        d = unum_getDoubleAttribute(formatter->_nf, UNUM_ROUNDING_INCREMENT);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberDoubleType, &d);
        }
-    } else if (kCFNumberFormatterFormatWidth == key) {
+    } else if (kCFNumberFormatterFormatWidthKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_FORMAT_WIDTH);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterPaddingPosition == key) {
+    } else if (kCFNumberFormatterPaddingPositionKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_PADDING_POSITION);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterPaddingCharacter == key) {
+    } else if (kCFNumberFormatterPaddingCharacterKey == key) {
        cnt = unum_getTextAttribute(formatter->_nf, UNUM_PADDING_CHARACTER, ubuffer, BUFFER_SIZE, &status);
        if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
            return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
        }
-    } else if (kCFNumberFormatterDefaultFormat == key) {
+    } else if (kCFNumberFormatterDefaultFormatKey == key) {
        return formatter->_defformat ? CFRetain(formatter->_defformat) : NULL;
-    } else if (kCFNumberFormatterMultiplier == key) {
+    } else if (kCFNumberFormatterMultiplierKey == key) {
         return formatter->_multiplier ? CFRetain(formatter->_multiplier) : NULL;
-    } else if (kCFNumberFormatterPositivePrefix == key) {
+    } else if (kCFNumberFormatterPositivePrefixKey == key) {
         cnt = unum_getTextAttribute(formatter->_nf, UNUM_POSITIVE_PREFIX, ubuffer, BUFFER_SIZE, &status);
         if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
             return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
         }
-    } else if (kCFNumberFormatterPositiveSuffix == key) {
+    } else if (kCFNumberFormatterPositiveSuffixKey == key) {
         cnt = unum_getTextAttribute(formatter->_nf, UNUM_POSITIVE_SUFFIX, ubuffer, BUFFER_SIZE, &status);
         if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
             return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
         }
-    } else if (kCFNumberFormatterNegativePrefix == key) {
+    } else if (kCFNumberFormatterNegativePrefixKey == key) {
         cnt = unum_getTextAttribute(formatter->_nf, UNUM_NEGATIVE_PREFIX, ubuffer, BUFFER_SIZE, &status);
         if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
             return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
         }
-    } else if (kCFNumberFormatterNegativeSuffix == key) {
+    } else if (kCFNumberFormatterNegativeSuffixKey == key) {
         cnt = unum_getTextAttribute(formatter->_nf, UNUM_NEGATIVE_SUFFIX, ubuffer, BUFFER_SIZE, &status);
         if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
             return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
         }
-    } else if (kCFNumberFormatterPerMillSymbol == key) {
+    } else if (kCFNumberFormatterPerMillSymbolKey == key) {
         cnt = unum_getSymbol(formatter->_nf, UNUM_PERMILL_SYMBOL, ubuffer, BUFFER_SIZE, &status);
         if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
             return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
         }
-    } else if (kCFNumberFormatterInternationalCurrencySymbol == key) {
+    } else if (kCFNumberFormatterInternationalCurrencySymbolKey == key) {
         cnt = unum_getSymbol(formatter->_nf, UNUM_INTL_CURRENCY_SYMBOL, ubuffer, BUFFER_SIZE, &status);
         if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
             return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
         }
-    } else if (kCFNumberFormatterCurrencyGroupingSeparator == key) {
+    } else if (kCFNumberFormatterCurrencyGroupingSeparatorKey == key) {
         cnt = unum_getSymbol(formatter->_nf, UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL, ubuffer, BUFFER_SIZE, &status);
         if (U_SUCCESS(status) && cnt <= BUFFER_SIZE) {
             return CFStringCreateWithCharacters(CFGetAllocator(formatter), (const UniChar *)ubuffer, cnt);
         }
-    } else if (kCFNumberFormatterIsLenient == key) {
-       n = unum_getAttribute(formatter->_nf, UNUM_LENIENT_PARSE);
-       if (1) {
-           return CFRetain(n ? kCFBooleanTrue : kCFBooleanFalse);
-       }
-    } else if (kCFNumberFormatterUseSignificantDigits == key) {
+    } else if (kCFNumberFormatterIsLenientKey == key) {
+       // unum_getAttribute(, UNUM_LENIENT_PARSE) is undefined.
+       return CFRetain(formatter->_isLenient ? kCFBooleanTrue : kCFBooleanFalse);
+    } else if (kCFNumberFormatterUseSignificantDigitsKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_SIGNIFICANT_DIGITS_USED);
        if (1) {
            return CFRetain(n ? kCFBooleanTrue : kCFBooleanFalse);
        }
-    } else if (kCFNumberFormatterMinSignificantDigits == key) {
+    } else if (kCFNumberFormatterMinSignificantDigitsKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_MIN_SIGNIFICANT_DIGITS);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
        }
-    } else if (kCFNumberFormatterMaxSignificantDigits == key) {
+    } else if (kCFNumberFormatterMaxSignificantDigitsKey == key) {
        n = unum_getAttribute(formatter->_nf, UNUM_MAX_SIGNIFICANT_DIGITS);
        if (1) {
            return CFNumberCreate(CFGetAllocator(formatter), kCFNumberSInt32Type, &n);
@@ -922,46 +1030,6 @@ CFTypeRef CFNumberFormatterCopyProperty(CFNumberFormatterRef formatter, CFString
     return NULL;
 }
 
-CONST_STRING_DECL(kCFNumberFormatterCurrencyCode, "kCFNumberFormatterCurrencyCode")
-CONST_STRING_DECL(kCFNumberFormatterDecimalSeparator, "kCFNumberFormatterDecimalSeparator")
-CONST_STRING_DECL(kCFNumberFormatterCurrencyDecimalSeparator, "kCFNumberFormatterCurrencyDecimalSeparator")
-CONST_STRING_DECL(kCFNumberFormatterAlwaysShowDecimalSeparator, "kCFNumberFormatterAlwaysShowDecimalSeparator")
-CONST_STRING_DECL(kCFNumberFormatterGroupingSeparator, "kCFNumberFormatterGroupingSeparator")
-CONST_STRING_DECL(kCFNumberFormatterUseGroupingSeparator, "kCFNumberFormatterUseGroupingSeparator")
-CONST_STRING_DECL(kCFNumberFormatterPercentSymbol, "kCFNumberFormatterPercentSymbol")
-CONST_STRING_DECL(kCFNumberFormatterZeroSymbol, "kCFNumberFormatterZeroSymbol")
-CONST_STRING_DECL(kCFNumberFormatterNaNSymbol, "kCFNumberFormatterNaNSymbol")
-CONST_STRING_DECL(kCFNumberFormatterInfinitySymbol, "kCFNumberFormatterInfinitySymbol")
-CONST_STRING_DECL(kCFNumberFormatterMinusSign, "kCFNumberFormatterMinusSignSymbol")
-CONST_STRING_DECL(kCFNumberFormatterPlusSign, "kCFNumberFormatterPlusSignSymbol")
-CONST_STRING_DECL(kCFNumberFormatterCurrencySymbol, "kCFNumberFormatterCurrencySymbol")
-CONST_STRING_DECL(kCFNumberFormatterExponentSymbol, "kCFNumberFormatterExponentSymbol")
-CONST_STRING_DECL(kCFNumberFormatterMinIntegerDigits, "kCFNumberFormatterMinIntegerDigits")
-CONST_STRING_DECL(kCFNumberFormatterMaxIntegerDigits, "kCFNumberFormatterMaxIntegerDigits")
-CONST_STRING_DECL(kCFNumberFormatterMinFractionDigits, "kCFNumberFormatterMinFractionDigits")
-CONST_STRING_DECL(kCFNumberFormatterMaxFractionDigits, "kCFNumberFormatterMaxFractionDigits")
-CONST_STRING_DECL(kCFNumberFormatterGroupingSize, "kCFNumberFormatterGroupingSize")
-CONST_STRING_DECL(kCFNumberFormatterSecondaryGroupingSize, "kCFNumberFormatterSecondaryGroupingSize")
-CONST_STRING_DECL(kCFNumberFormatterRoundingMode, "kCFNumberFormatterRoundingMode")
-CONST_STRING_DECL(kCFNumberFormatterRoundingIncrement, "kCFNumberFormatterRoundingIncrement")
-CONST_STRING_DECL(kCFNumberFormatterFormatWidth, "kCFNumberFormatterFormatWidth")
-CONST_STRING_DECL(kCFNumberFormatterPaddingPosition, "kCFNumberFormatterPaddingPosition")
-CONST_STRING_DECL(kCFNumberFormatterPaddingCharacter, "kCFNumberFormatterPaddingCharacter")
-CONST_STRING_DECL(kCFNumberFormatterDefaultFormat, "kCFNumberFormatterDefaultFormat")
-
-CONST_STRING_DECL(kCFNumberFormatterMultiplier, "kCFNumberFormatterMultiplier")
-CONST_STRING_DECL(kCFNumberFormatterPositivePrefix, "kCFNumberFormatterPositivePrefix")
-CONST_STRING_DECL(kCFNumberFormatterPositiveSuffix, "kCFNumberFormatterPositiveSuffix")
-CONST_STRING_DECL(kCFNumberFormatterNegativePrefix, "kCFNumberFormatterNegativePrefix")
-CONST_STRING_DECL(kCFNumberFormatterNegativeSuffix, "kCFNumberFormatterNegativeSuffix")
-CONST_STRING_DECL(kCFNumberFormatterPerMillSymbol, "kCFNumberFormatterPerMillSymbol")
-CONST_STRING_DECL(kCFNumberFormatterInternationalCurrencySymbol, "kCFNumberFormatterInternationalCurrencySymbol")
-
-CONST_STRING_DECL(kCFNumberFormatterCurrencyGroupingSeparator, "kCFNumberFormatterCurrencyGroupingSeparator")
-CONST_STRING_DECL(kCFNumberFormatterIsLenient, "kCFNumberFormatterIsLenient")
-CONST_STRING_DECL(kCFNumberFormatterUseSignificantDigits, "kCFNumberFormatterUseSignificantDigits")
-CONST_STRING_DECL(kCFNumberFormatterMinSignificantDigits, "kCFNumberFormatterMinSignificantDigits")
-CONST_STRING_DECL(kCFNumberFormatterMaxSignificantDigits, "kCFNumberFormatterMaxSignificantDigits")
 
 Boolean CFNumberFormatterGetDecimalInfoForCurrencyCode(CFStringRef currencyCode, int32_t *defaultFractionDigits, double *roundingIncrement) {
     UChar ubuffer[4];
index faaf9d860e5b2acdf7f5fe03d565ea032310736f..ace9c751b55adc70f33437345523913172f31eb9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFNumberFormatter.h
-       Copyright (c) 2003-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2003-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFNUMBERFORMATTER__)
index d0dbed0c20daf676d12d745ff62454ecc0c90b0e..22ec9c00496c6ab9eaa7b890d84204d6731e05bd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPlatform.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #include "CFInternal.h"
-#include "CFPriv.h"
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <crt_externs.h>
-#include <mach-o/dyld.h>
+#include <CoreFoundation/CFPriv.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    #include <stdlib.h>
+    #include <sys/stat.h>
+    #include <string.h>
+    #include <unistd.h>
+    #include <fcntl.h>
+    #include <pwd.h>
+    #include <crt_externs.h>
+    #include <mach-o/dyld.h>
+#endif
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+#include <shellapi.h>
+#include <shlobj.h>
+
+#define getcwd _NS_getcwd
+
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
 #define kCFPlatformInterfaceStringEncoding     kCFStringEncodingUTF8
 #else
 #define kCFPlatformInterfaceStringEncoding     CFStringGetSystemEncoding()
@@ -43,7 +54,7 @@
 
 static CFStringRef _CFUserName(void);
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 // CoreGraphics and LaunchServices are only projects (1 Dec 2006) that use these
 char **_CFArgv(void) { return *_NSGetArgv(); }
 int _CFArgc(void) { return *_NSGetArgc(); }
@@ -51,12 +62,7 @@ int _CFArgc(void) { return *_NSGetArgc(); }
 
 
 __private_extern__ Boolean _CFGetCurrentDirectory(char *path, int maxlen) {
-#if 0 || 0
-    DWORD len = GetCurrentDirectoryA(maxlen, path);
-    return ((0 != len) && (maxlen > 0) && (len + 1 <= (DWORD)maxlen));
-#else
     return getcwd(path, maxlen) != NULL;
-#endif
 }
 
 static Boolean __CFIsCFM = false;
@@ -66,47 +72,46 @@ __private_extern__ Boolean _CFIsCFM(void) {
     return __CFIsCFM;
 }
 
-#if 0 || 0
+#if DEPLOYMENT_TARGET_WINDOWS
 #define PATH_SEP '\\'
 #else
 #define PATH_SEP '/'
 #endif
 
-#if !defined(__WIN32__)
-#define PATH_LIST_SEP ':'
-
-static char *_CFSearchForNameInPath(const char *name, char *path) {
-    struct stat statbuf;
-    char nname[strlen(name) + strlen(path) + 2];
-    int no_hang_fd = open("/dev/autofs_nowait", 0);
-    for (;;) {
-        char *p = (char *)strchr(path, PATH_LIST_SEP);
-        if (NULL != p) {
-            *p = '\0';
-        }
-        nname[0] = '\0';
-        strlcat(nname, path, sizeof(nname));
-        strlcat(nname, "/", sizeof(nname));
-        strlcat(nname, name, sizeof(nname));
-        // Could also do access(us, X_OK) == 0 in next condition,
-        // for executable-only searching
-        if (0 == stat(nname, &statbuf) && (statbuf.st_mode & S_IFMT) == S_IFREG) {
-            if (p != NULL) {
-                *p = PATH_LIST_SEP;
+
+#if DEPLOYMENT_TARGET_WINDOWS
+// Returns the path to the CF DLL, which we can then use to find resources like char sets
+bool bDllPathCached = false;
+__private_extern__ const wchar_t *_CFDLLPath(void) {
+    static wchar_t cachedPath[MAX_PATH+1];
+
+    if (!bDllPathCached) {
+#ifdef _DEBUG
+        // might be nice to get this from the project file at some point
+        wchar_t *DLLFileName = L"CoreFoundation_debug.dll";
+#else
+        wchar_t *DLLFileName = L"CoreFoundation.dll";
+#endif
+        HMODULE ourModule = GetModuleHandleW(DLLFileName);
+        
+        CFAssert(ourModule, __kCFLogAssertion, "GetModuleHandle failed");
+
+        DWORD wResult = GetModuleFileNameW(ourModule, cachedPath, MAX_PATH+1);
+        CFAssert1(wResult > 0, __kCFLogAssertion, "GetModuleFileName failed: %d", GetLastError());
+        CFAssert1(wResult < MAX_PATH+1, __kCFLogAssertion, "GetModuleFileName result truncated: %s", cachedPath);
+
+        // strip off last component, the DLL name
+        CFIndex idx;
+        for (idx = wResult - 1; idx; idx--) {
+            if ('\\' == cachedPath[idx]) {
+                cachedPath[idx] = '\0';
+                break;
             }
-           close(no_hang_fd);
-            return strdup(nname);
-        }
-        if (NULL == p) {
-            break;
         }
-        *p = PATH_LIST_SEP;
-        path = p + 1;
+        bDllPathCached = true;
     }
-    close(no_hang_fd);
-    return NULL;
+    return cachedPath;
 }
-
 #endif
 
 static const char *__CFProcessPath = NULL;
@@ -124,136 +129,87 @@ const char **_CFGetProcessPath(void) {
     return &__CFProcessPath;
 }
 
+#if DEPLOYMENT_TARGET_WINDOWS
 const char *_CFProcessPath(void) {
     if (__CFProcessPath) return __CFProcessPath;
+    wchar_t buf[CFMaxPathSize] = {0};
+    DWORD rlen = GetModuleFileNameW(NULL, buf, sizeof(buf) / sizeof(buf[0]));
+    if (0 < rlen) {
+       char asciiBuf[CFMaxPathSize] = {0};
+       int res = WideCharToMultiByte(CP_UTF8, 0, buf, rlen, asciiBuf, sizeof(asciiBuf) / sizeof(asciiBuf[0]), NULL, NULL);
+       if (0 < res) {
+           __CFProcessPath = strdup(asciiBuf);
+           __CFprogname = strrchr(__CFProcessPath, PATH_SEP);
+           __CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
+       }
+    }
+    if (!__CFProcessPath) {
+       __CFProcessPath = "";
+        __CFprogname = __CFProcessPath;
+    }
+    return __CFProcessPath;
+}
+#endif
 
-    char *thePath = NULL;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+const char *_CFProcessPath(void) {
+    if (__CFProcessPath) return __CFProcessPath;
 #if DEPLOYMENT_TARGET_MACOSX
     if (!issetugid()) {
-       thePath = getenv("CFProcessPath");
-       if (thePath) {
-           int len = strlen(thePath);
-           __CFProcessPath = (const char *)CFAllocatorAllocate(kCFAllocatorSystemDefault, len+1, 0);
-           if (__CFOASafe) __CFSetLastAllocationEventName((void *)__CFProcessPath, "CFUtilities (process-path)");
-           memmove((char *)__CFProcessPath, thePath, len + 1);
+       const char *path = (char *)__CFgetenv("CFProcessPath");
+       if (path) {
+           __CFProcessPath = strdup(path);
+           __CFprogname = strrchr(__CFProcessPath, PATH_SEP);
+           __CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
+           return __CFProcessPath;
        }
     }
 #endif
-#if DEPLOYMENT_TARGET_MACOSX
-    int execIndex = 0;
-#endif
-    
-    if (!__CFProcessPath && NULL != (*_NSGetArgv())[execIndex]) {
-       int no_hang_fd = open("/dev/autofs_nowait", 0);
-        char buf[CFMaxPathSize] = {0};
-       struct stat statbuf;
-        const char *arg0 = (*_NSGetArgv())[execIndex];
-        if (arg0[0] == '/') {
-            // We've got an absolute path; look no further;
-            thePath = (char *)arg0;
-        } else {
-            char *theList = getenv("PATH");
-            if (NULL != theList && NULL == strrchr(arg0, '/')) {
-                thePath = _CFSearchForNameInPath(arg0, theList);
-                if (thePath) {
-                    // User could have "." or "../bin" or other relative path in $PATH
-                    if (('/' != thePath[0]) && _CFGetCurrentDirectory(buf, CFMaxPathSize)) {
-                        strlcat(buf, "/", sizeof(buf));
-                        strlcat(buf, thePath, sizeof(buf));
-                        if (0 == stat(buf, &statbuf)) {
-                               free(thePath);
-                            thePath = buf;
-                        }
-                    }
-                    if (thePath != buf) {
-                        strlcpy(buf, thePath, sizeof(buf));
-                        free((void *)thePath);
-                        thePath = buf;
-                    }
-                }
-            }
-        }
-        
-       // After attempting a search through $PATH, if existant,
-       // try prepending the current directory to argv[0].
-        if (!thePath && _CFGetCurrentDirectory(buf, CFMaxPathSize)) {
-            if (buf[strlen(buf)-1] != '/') {
-                strlcat(buf, "/", sizeof(buf));
-            }
-           strlcat(buf, arg0, CFMaxPathSize);
-            if (0 == stat(buf, &statbuf)) {
-               thePath = buf;
-            }
-       }
-
-        if (thePath) {
-            // We are going to process the buffer replacing all "/./" and "//" with "/"
-            CFIndex srcIndex = 0, dstIndex = 0;
-            CFIndex len = strlen(thePath);
-            for (srcIndex=0; srcIndex<len; srcIndex++) {
-                thePath[dstIndex] = thePath[srcIndex];
-                dstIndex++;
-                while (srcIndex < len-1 && thePath[srcIndex] == '/' && (thePath[srcIndex+1] == '/' || (thePath[srcIndex+1] == '.' && srcIndex < len-2 && thePath[srcIndex+2] == '/'))) srcIndex += (thePath[srcIndex+1] == '/' ? 1 : 2);
-            }
-            thePath[dstIndex] = 0;
-        }
-        if (!thePath) {
-           thePath = (*_NSGetArgv())[execIndex];
-        }
-
-       if (thePath) {
-               int len = strlen(thePath);
-           __CFProcessPath = (const char *)CFAllocatorAllocate(kCFAllocatorSystemDefault, len + 1, 0);
-            if (__CFOASafe) __CFSetLastAllocationEventName((void *)__CFProcessPath, "CFUtilities (process-path)");
-            memmove((char *)__CFProcessPath, thePath, len + 1);
-       }
-       if (__CFProcessPath) {
-            
-           const char *p = 0;
-           int i;
-           for (i = 0; __CFProcessPath[i] != 0; i++){
-               if (__CFProcessPath[i] == PATH_SEP)
-                   p = __CFProcessPath + i; 
+    uint32_t size = CFMaxPathSize;
+    char buffer[size];
+    if (0 == _NSGetExecutablePath(buffer, &size)) {
+#if DEPLOYMENT_TARGET_MACOSX && defined(__ppc__)
+       size_t len = strlen(buffer);
+       if (12 <= len && 0 == strcmp("LaunchCFMApp", buffer + len - 12)) {
+           struct stat exec, lcfm;
+           const char *launchcfm = "/System/Library/Frameworks/Carbon.framework/Versions/Current/Support/LaunchCFMApp";
+           if (0 == stat(launchcfm, &lcfm) && 0 == stat(buffer, &exec) && (lcfm.st_dev == exec.st_dev) && (lcfm.st_ino == exec.st_ino)) {
+               // Executable is LaunchCFMApp, take special action
+               __CFIsCFM = true;
+               if ((*_NSGetArgv())[1] && '/' == *((*_NSGetArgv())[1])) {
+                   strlcpy(buffer, (*_NSGetArgv())[1], sizeof(buffer));
+               }
            }
-           if (p != 0)
-               __CFprogname = p + 1;
-           else
-               __CFprogname = __CFProcessPath;
        }
-
-       close(no_hang_fd);
+#endif
+       __CFProcessPath = strdup(buffer);
+       __CFprogname = strrchr(__CFProcessPath, PATH_SEP);
+       __CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
     }
     if (!__CFProcessPath) {
        __CFProcessPath = "";
         __CFprogname = __CFProcessPath;
-    } else {
-        const char *p = 0;
-        int i;
-        for (i = 0; __CFProcessPath[i] != 0; i++){
-            if (__CFProcessPath[i] == PATH_SEP)
-                p = __CFProcessPath + i; 
-        }
-        if (p != 0)
-            __CFprogname = p + 1;
-        else
-            __CFprogname = __CFProcessPath;
     }
     return __CFProcessPath;
 }
+#endif
 
 __private_extern__ CFStringRef _CFProcessNameString(void) {
     static CFStringRef __CFProcessNameString = NULL;
     if (!__CFProcessNameString) {
         const char *processName = *_CFGetProgname();
         if (!processName) processName = "";
-        __CFProcessNameString = CFStringCreateWithCString(__CFGetDefaultAllocator(), processName, kCFPlatformInterfaceStringEncoding);
+        CFStringRef newStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, processName, kCFPlatformInterfaceStringEncoding);
+        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *) newStr, (void * volatile *)& __CFProcessNameString)) {
+            CFRelease(newStr);    // someone else made the assignment, so just release the extra string.
+        }
     }
     return __CFProcessNameString;
 }
 
 static CFStringRef __CFUserName = NULL;
 
-#if (DEPLOYMENT_TARGET_MACOSX) || defined(__svr4__) || defined(__hpux__) || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 static CFURLRef __CFHomeDirectory = NULL;
 static uint32_t __CFEUID = -1;
 static uint32_t __CFUID = -1;
@@ -261,7 +217,7 @@ static uint32_t __CFUID = -1;
 static CFURLRef _CFCopyHomeDirURLForUser(struct passwd *upwd) {
     CFURLRef home = NULL;
     if (!issetugid()) {
-       const char *path = getenv("CFFIXED_USER_HOME");
+       const char *path = __CFgetenv("CFFIXED_USER_HOME");
        if (path) {
            home = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)path, strlen(path), true);
        }
@@ -287,7 +243,7 @@ static void _CFUpdateUserInfo(void) {
     upwd = getpwuid(__CFEUID ? __CFEUID : __CFUID);
     __CFHomeDirectory = _CFCopyHomeDirURLForUser(upwd);
     if (!__CFHomeDirectory) {
-        const char *cpath = getenv("HOME");
+        const char *cpath = __CFgetenv("HOME");
         if (cpath) {
             __CFHomeDirectory = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)cpath, strlen(cpath), true);
         }
@@ -300,15 +256,19 @@ static void _CFUpdateUserInfo(void) {
     if (upwd && upwd->pw_name) {
         __CFUserName = CFStringCreateWithCString(kCFAllocatorSystemDefault, upwd->pw_name, kCFPlatformInterfaceStringEncoding);
     } else {
-        const char *cuser = getenv("USER");
+        const char *cuser = __CFgetenv("USER");
         if (cuser)
             __CFUserName = CFStringCreateWithCString(kCFAllocatorSystemDefault, cuser, kCFPlatformInterfaceStringEncoding);
     }
 }
 #endif
 
+#if DEPLOYMENT_TARGET_WINDOWS
+typedef DWORD (*NetUserGetInfoCall)(wchar_t *, wchar_t *, DWORD, char* *);
+#endif
+
 static CFURLRef _CFCreateHomeDirectoryURLForUser(CFStringRef uName) {
-#if (DEPLOYMENT_TARGET_MACOSX) || defined(__svr4__) || defined(__hpux__) || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
     if (!uName) {
         if (geteuid() != __CFEUID || getuid() != __CFUID || !__CFHomeDirectory)
             _CFUpdateUserInfo();
@@ -334,80 +294,127 @@ static CFURLRef _CFCreateHomeDirectoryURLForUser(CFStringRef uName) {
         }
         return _CFCopyHomeDirURLForUser(upwd);
     }
-#elif defined(__WIN32__)
+#elif DEPLOYMENT_TARGET_WINDOWS
     CFStringRef user = !uName ? _CFUserName() : uName;
-    CFURLRef home = NULL;
+    CFURLRef retVal = NULL;
+    CFIndex len = 0;
+    CFStringRef str = NULL;
 
     if (!uName || CFEqual(user, _CFUserName())) {
-        const char *cpath = getenv("HOMEPATH");
-        const char *cdrive = getenv("HOMEDRIVE");
+        const char *cpath = __CFgetenv("HOMEPATH");
+        const char *cdrive = __CFgetenv("HOMEDRIVE");
         if (cdrive && cpath) {
             char fullPath[CFMaxPathSize];
-            CFStringRef str;
             strlcpy(fullPath, cdrive, sizeof(fullPath));
             strlcat(fullPath, cpath, sizeof(fullPath));
             str = CFStringCreateWithCString(kCFAllocatorSystemDefault, fullPath, kCFPlatformInterfaceStringEncoding);
-            home = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, kCFURLWindowsPathStyle, true);
+            retVal = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, kCFURLWindowsPathStyle, true);
             CFRelease(str);
-        }
+       }
     }
-    if (home == NULL) {
+    if (retVal == NULL) {
                UniChar pathChars[MAX_PATH];
-               if (S_OK == SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, (LPWSTR) pathChars)) {
+               if (S_OK == SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, (wchar_t *) pathChars)) {
                        UniChar* p = pathChars;
-                       CFIndex len = 0;
-                       CFStringRef str;
                        while (*p++ != 0)
                                ++len;
                        str = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, pathChars, len);
-            home = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, kCFURLWindowsPathStyle, true);
-            CFRelease(str);
-                } else {
-                    // We have to get "some" directory location, so fall-back to the 
-                    // processes current directory.
-                    UniChar currDir[MAX_PATH];
-                    DWORD dwChars = GetCurrentDirectory(MAX_PATH + 1, (LPWSTR)currDir);
-                    if (dwChars > 0) {
-                        UniChar* p = currDir;
-                                   CFIndex len = 0;
-                                   CFStringRef str;
-                                   while (*p++ != 0)
-                                           ++len;
-                                   str = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, currDir, len);
-                        home = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, kCFURLWindowsPathStyle, true);
-                    }
+                       retVal = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, kCFURLWindowsPathStyle, true);
+               } else {
+                       // We have to get "some" directory location, so fall-back to the
+                       // processes current directory.
+                       UniChar currDir[MAX_PATH];
+                       DWORD dwChars = GetCurrentDirectoryW(MAX_PATH + 1, (wchar_t *)currDir);
+                       if (dwChars > 0) {
+                               UniChar* p = currDir;
+                               while (*p++ != 0)
+                                       ++len;
+                               str = CFStringCreateWithCharacters(kCFAllocatorDefault, currDir, len);
+                               retVal = CFURLCreateWithFileSystemPath(NULL, str, kCFURLWindowsPathStyle, true);
+                       }
+                   CFRelease(str);
                 }
     }
+#if 0
+        char fullPath[CFMaxPathSize];
+        HRESULT hr = SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0 /* SHGFP_TYPE_CURRENT */, fullPath);
+        if (SUCCEEDED(hr)) {
+            CFStringRef str = CFStringCreateWithCString(NULL, fullPath, kCFPlatformInterfaceStringEncoding);
+            retVal = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, kCFURLWindowsPathStyle, true);
+            CFRelease(str);
+        }
+    }
+    if (!retVal) {
+        struct _USER_INFO_2 *userInfo;
+        HINSTANCE hinstDll = GetModuleHandleA("NETAPI32");
+        if (!hinstDll)
+            hinstDll = LoadLibraryExA("NETAPI32", NULL, 0);
+        if (hinstDll) {
+            NetUserGetInfoCall lpfn = (NetUserGetInfoCall)GetProcAddress(hinstDll, "NetUserGetInfo");
+            if (lpfn) {
+        unsigned namelen = CFStringGetLength(user);
+                UniChar *username;
+                username = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UniChar) * (namelen + 1), 0);
+        CFStringGetCharacters(user, CFRangeMake(0, namelen), username);
+                if (!(*lpfn)(NULL, (wchar_t *)username, 2, (char * *)&userInfo)) {
+            UInt32 len = 0;
+            CFMutableStringRef str;
+            while (userInfo->usri2_home_dir[len] != 0) len ++;
+            str = CFStringCreateMutable(kCFAllocatorSystemDefault, len+1);
+            CFStringAppendCharacters(str, (const UniChar *)userInfo->usri2_home_dir, len);
+                    retVal = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, kCFURLWindowsPathStyle, true);
+            CFRelease(str);
+        }
+        CFAllocatorDeallocate(kCFAllocatorSystemDefault, username);
+    }
+        } else {
+        }
+    }
+#endif
+
     // We could do more here (as in KB Article Q101507). If that article is to
     // be believed, we should only run into this case on Win95, or through
     // user error.
-    if (home) {
-        CFStringRef str = CFURLCopyFileSystemPath(home, kCFURLWindowsPathStyle);
+#if DEPLOYMENT_TARGET_WINDOWS_SAFARI
+    if (retVal) {
+        CFStringRef str = CFURLCopyFileSystemPath(retVal, kCFURLWindowsPathStyle);
         if (str && CFStringGetLength(str) == 0) {
-            CFRelease(home);
-            home=NULL;
+            CFRelease(retVal);
+            retVal=NULL;
         }
         if (str) CFRelease(str);
     }
-    return home;
+#else
+    CFStringRef testPath = CFURLCopyPath(retVal);
+    if (CFStringGetLength(testPath) == 0) {
+        CFRelease(retVal);
+        retVal=NULL;
+        }
+    if (testPath) {
+        CFRelease(testPath);
+    }
+#endif
+    return retVal;
+
 #else
 #error Dont know how to compute users home directories on this platform
 #endif
 }
 
 static CFStringRef _CFUserName(void) {
-#if (DEPLOYMENT_TARGET_MACOSX) || defined(__svr4__) || defined(__hpux__) || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
     if (geteuid() != __CFEUID || getuid() != __CFUID)
        _CFUpdateUserInfo();
-#elif defined(__WIN32__)
+#elif DEPLOYMENT_TARGET_WINDOWS
     if (!__CFUserName) {
-       char username[1040];
+       wchar_t username[1040];
        DWORD size = 1040;
        username[0] = 0;
-       if (GetUserNameA(username, &size)) {
-            __CFUserName = CFStringCreateWithCString(kCFAllocatorSystemDefault, username, kCFPlatformInterfaceStringEncoding);
+       if (GetUserNameW(username, &size)) {
+           // discount the extra NULL by decrementing the size
+           __CFUserName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)username, size - 1);
        } else {
-           const char *cname = getenv("USERNAME");
+           const char *cname = __CFgetenv("USERNAME");
            if (cname)
                 __CFUserName = CFStringCreateWithCString(kCFAllocatorSystemDefault, cname, kCFPlatformInterfaceStringEncoding);
        }
@@ -449,3 +456,268 @@ CF_EXPORT CFURLRef CFCopyHomeDirectoryURLForUser(CFStringRef uName) {
 #undef CFMaxHostNameLength
 #undef CFMaxHostNameSize
 
+#if DEPLOYMENT_TARGET_WINDOWS
+CF_INLINE CFIndex strlen_UniChar(const UniChar* p) {
+       CFIndex result = 0;
+       while ((*p++) != 0)
+               ++result;
+       return result;
+}
+
+//#include <shfolder.h>
+/*
+ * _CFCreateApplicationRepositoryPath returns the path to the application's
+ * repository in a CFMutableStringRef. The path returned will be:
+ *     <nFolder_path>\Apple Computer\<bundle_name>\
+ * or if the bundle name cannot be obtained:
+ *     <nFolder_path>\Apple Computer\
+ * where nFolder_path is obtained by calling SHGetFolderPath with nFolder
+ * (for example, with CSIDL_APPDATA or CSIDL_LOCAL_APPDATA).
+ *
+ * The CFMutableStringRef result must be released by the caller.
+ *
+ * If anything fails along the way, the result will be NULL.  
+ */
+CF_EXPORT CFMutableStringRef _CFCreateApplicationRepositoryPath(CFAllocatorRef alloc, int nFolder) {
+    CFMutableStringRef result = NULL;
+    UniChar szPath[MAX_PATH];
+    
+    // get the current path to the data repository: CSIDL_APPDATA (roaming) or CSIDL_LOCAL_APPDATA (nonroaming)
+    if (S_OK == SHGetFolderPathW(NULL, nFolder, NULL, 0, (wchar_t *) szPath)) {
+       CFStringRef directoryPath;
+       
+       // make it a CFString
+       directoryPath = CFStringCreateWithCharacters(alloc, szPath, strlen_UniChar(szPath));
+       if (directoryPath) {
+           CFBundleRef bundle;
+           CFStringRef bundleName;
+           CFStringRef completePath;
+           
+           // attempt to get the bundle name
+           bundle = CFBundleGetMainBundle();
+           if (bundle) {
+               bundleName = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleNameKey);
+           }
+           else {
+               bundleName = NULL;
+           }
+           
+           if (bundleName) {
+               // the path will be "<directoryPath>\Apple Computer\<bundleName>\" if there is a bundle name
+               completePath = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@\\Apple Computer\\%@\\"), directoryPath, bundleName);
+           }
+           else {
+               // or "<directoryPath>\Apple Computer\" if there is no bundle name.
+               completePath = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@\\Apple Computer\\"), directoryPath);
+           }
+
+           CFRelease(directoryPath);
+
+           // make a mutable copy to return
+           if (completePath) {
+               result = CFStringCreateMutableCopy(alloc, 0, completePath);
+               CFRelease(completePath);
+           }
+       }
+    }
+
+    return ( result );
+}
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+/* On Windows, we want to use UTF-16LE for path names to get full unicode support. Internally, however, everything remains in UTF-8 representation. These helper functions stand between CF and the Microsoft CRT to ensure that we are using the right representation on both sides. */
+
+#include <sys/stat.h>
+#include <share.h>
+
+// Creates a buffer of wchar_t to hold a UTF16LE version of the UTF8 str passed in. Caller must free the buffer when done. If resultLen is non-NULL, it is filled out with the number of characters in the string.
+static wchar_t *createWideFileSystemRepresentation(const char *str, CFIndex *resultLen) {
+    // Get the real length of the string in UTF16 characters
+    CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorSystemDefault, str, kCFStringEncodingUTF8);
+    CFIndex strLen = CFStringGetLength(cfStr);
+    
+    // Allocate a wide buffer to hold the converted string, including space for a NULL terminator
+    wchar_t *wideBuf = (wchar_t *)malloc((strLen + 1) * sizeof(wchar_t));
+    
+    // Copy the string into the buffer and terminate
+    CFStringGetCharacters(cfStr, CFRangeMake(0, strLen), (UniChar *)wideBuf);
+    wideBuf[strLen] = 0;
+    
+    CFRelease(cfStr);
+    if (resultLen) *resultLen = strLen;
+    return wideBuf;
+}
+
+// Copies a UTF16 buffer into a supplied UTF8 buffer. 
+static void copyToNarrowFileSystemRepresentation(const wchar_t *wide, CFIndex dstBufSize, char *dstbuf) {
+    // Get the real length of the wide string in UTF8 characters
+    CFStringRef cfStr = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)wide, wcslen(wide));
+    CFIndex strLen = CFStringGetLength(cfStr);
+    CFIndex bytesUsed;
+    
+    // Copy the wide string into the buffer and terminate
+    CFStringGetBytes(cfStr, CFRangeMake(0, strLen), kCFStringEncodingUTF8, 0, false, (uint8_t *)dstbuf, dstBufSize, &bytesUsed);
+    dstbuf[bytesUsed] = 0;
+    
+    CFRelease(cfStr);
+}
+
+CF_EXPORT int _NS_stat(const char *name, struct _stat *st) {
+    wchar_t *wide = createWideFileSystemRepresentation(name, NULL);
+    int res = _wstat(wide, st);
+    free(wide);
+    return res;
+}
+
+CF_EXPORT int _NS_mkdir(const char *name) {
+    wchar_t *wide = createWideFileSystemRepresentation(name, NULL);
+    int res = _wmkdir(wide);
+    free(wide);
+    return res;
+}
+
+CF_EXPORT int _NS_rmdir(const char *name) {
+    wchar_t *wide = createWideFileSystemRepresentation(name, NULL);
+    int res = _wrmdir(wide);
+    free(wide);
+    return res;
+}
+
+CF_EXPORT int _NS_chmod(const char *name, int mode) {
+    wchar_t *wide = createWideFileSystemRepresentation(name, NULL);
+    int res = _wchmod(wide, mode);
+    free(wide);
+    return res;
+}
+
+CF_EXPORT int _NS_unlink(const char *name) {
+    wchar_t *wide = createWideFileSystemRepresentation(name, NULL);
+    int res = _wunlink(wide);
+    free(wide);
+    return res;
+}
+
+// Warning: this doesn't support dstbuf as null even though 'getcwd' does
+CF_EXPORT char *_NS_getcwd(char *dstbuf, size_t size) {
+    if (!dstbuf) {
+       CFLog(kCFLogLevelWarning, CFSTR("CFPlatform: getcwd called with null buffer"));
+       return 0;
+    }
+    
+    wchar_t *buf = _wgetcwd(NULL, 0);
+    if (!buf) {
+        return NULL;
+    }
+        
+    // Convert result to UTF8
+    copyToNarrowFileSystemRepresentation(buf, (CFIndex)size, dstbuf);
+    free(buf);
+    return dstbuf;
+}
+
+CF_EXPORT char *_NS_getenv(const char *name) {
+    // todo: wide env variables
+    return getenv(name);
+}
+
+CF_EXPORT int _NS_rename(const char *oldName, const char *newName) {
+    wchar_t *oldWide = createWideFileSystemRepresentation(oldName, NULL);
+    wchar_t *newWide = createWideFileSystemRepresentation(newName, NULL);
+    // _wrename on Windows does not behave exactly as rename() on Mac OS -- if the file exists, the Windows one will fail whereas the Mac OS version will replace
+    // To simulate the Mac OS behavior, we use the Win32 API then fill out errno if something goes wrong
+    BOOL winRes = MoveFileExW(oldWide, newWide, MOVEFILE_REPLACE_EXISTING);
+    DWORD error = GetLastError();
+    if (!winRes) {
+           switch (error) {
+            case ERROR_SUCCESS:
+                errno = 0;
+                break;
+            case ERROR_FILE_NOT_FOUND:
+            case ERROR_PATH_NOT_FOUND:
+            case ERROR_OPEN_FAILED:
+                errno = ENOENT;
+                break;
+            case ERROR_ACCESS_DENIED:
+                errno = EACCES;
+                break;
+            default:
+                errno = error;
+        }
+    }
+    free(oldWide);
+    free(newWide);
+    return (winRes ? 0 : -1);
+}
+
+CF_EXPORT int _NS_open(const char *name, int oflag, int pmode) {
+    wchar_t *wide = createWideFileSystemRepresentation(name, NULL);
+    int fd;
+    _wsopen_s(&fd, wide, oflag, _SH_DENYNO, _S_IREAD | _S_IWRITE);
+    free(wide);
+    return fd;
+}
+
+CF_EXPORT int _NS_chdir(const char *name) {
+    wchar_t *wide = createWideFileSystemRepresentation(name, NULL);
+    int res = _wchdir(wide);
+    free(wide);
+    return res;
+}
+
+CF_EXPORT int _NS_access(const char *name, int amode) {
+    // execute is always true
+    if (amode == 1) return 0;
+
+    wchar_t *wide = createWideFileSystemRepresentation(name, NULL);
+    // we only care about the read-only (04) and write-only (02) bits, so mask octal 06
+    int res = _waccess(wide, amode & 06);
+    free(wide);
+    return res;
+}
+
+// This is a bit different than the standard 'mkstemp', because the size parameter is needed so we know the size of the UTF8 buffer
+// Also, we don't avoid the race between creating a temporary file name and opening it on Windows like we do on Mac
+CF_EXPORT int _NS_mkstemp(char *name, int bufSize) {
+    CFIndex nameLen;
+    wchar_t *wide = createWideFileSystemRepresentation(name, &nameLen);
+    
+    // First check to see if the directory that this new temporary file will be created in exists. If not, set errno to ENOTDIR. This mimics the behavior of mkstemp on MacOS more closely.
+    // Look for the last '\' in the path
+    wchar_t *lastSlash = wcsrchr(wide, '\\');
+    if (!lastSlash) {
+       free(wide);
+       return -1;
+    }
+    
+    // Set the last slash to NULL temporarily and use it for _wstat
+    *lastSlash = 0;
+    struct _stat dirInfo;
+    int res = _wstat(wide, &dirInfo);
+    if (res < 0) {
+       if (errno == ENOENT) {
+           errno = ENOTDIR;
+       }
+       free(wide);
+       return -1;
+    }
+    // Restore the last slash
+    *lastSlash = '\\';
+    
+    errno_t err = _wmktemp_s(wide, nameLen + 1);
+    if (err != 0) {
+        free(wide);
+        return 0;
+    }
+    
+    int fd;
+    _wsopen_s(&fd, wide, _O_RDWR | _O_CREAT | CF_OPENFLGS, _SH_DENYNO, _S_IREAD | _S_IWRITE);
+    
+    // Convert the wide name back into the UTF8 buffer the caller supplied
+    copyToNarrowFileSystemRepresentation(wide, bufSize, name);
+    free(wide);
+    return fd;    
+}
+
+#endif
+
diff --git a/CFPlatformConverters.c b/CFPlatformConverters.c
new file mode 100644 (file)
index 0000000..440372e
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*     CFPlatformConverters.c
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
+       Responsibility: Aki Inoue
+*/
+
+#include "CFInternal.h"
+#include <CoreFoundation/CFString.h>
+#include "CFStringEncodingConverterExt.h"
+#include <CoreFoundation/CFStringEncodingExt.h>
+#include <CoreFoundation/CFPreferences.h>
+#include "CFUniChar.h"
+#include "CFUnicodeDecomposition.h"
+#include "CFStringEncodingConverterPriv.h"
+#include "CFICUConverters.h"
+
+
+CF_INLINE bool __CFIsPlatformConverterAvailable(int encoding) {
+
+#if DEPLOYMENT_TARGET_WINDOWS
+    return (IsValidCodePage(CFStringConvertEncodingToWindowsCodepage(encoding)) ? true : false);
+#else
+    return false;
+#endif
+}
+
+static const CFStringEncodingConverter __CFICUBootstrap = {
+    NULL /* toBytes */, NULL /* toUnicode */, 6 /* maxBytesPerChar */, 4 /* maxDecomposedCharLen */,
+    kCFStringEncodingConverterICU /* encodingClass */,
+    NULL /* toBytesLen */, NULL /* toUnicodeLen */, NULL /* toBytesFallback */,
+    NULL /* toUnicodeFallback */, NULL /* toBytesPrecompose */, NULL, /* isValidCombiningChar */
+};
+
+static const CFStringEncodingConverter __CFPlatformBootstrap = {
+    NULL /* toBytes */, NULL /* toUnicode */, 6 /* maxBytesPerChar */, 4 /* maxDecomposedCharLen */,
+    kCFStringEncodingConverterPlatformSpecific /* encodingClass */,
+    NULL /* toBytesLen */, NULL /* toUnicodeLen */, NULL /* toBytesFallback */,
+    NULL /* toUnicodeFallback */, NULL /* toBytesPrecompose */, NULL, /* isValidCombiningChar */
+};
+
+__private_extern__ const CFStringEncodingConverter *__CFStringEncodingGetExternalConverter(uint32_t encoding) {
+
+    if (NULL != __CFStringEncodingGetICUName(encoding)) return &__CFICUBootstrap;
+    
+    return (__CFIsPlatformConverterAvailable(encoding) ? &__CFPlatformBootstrap : NULL);
+}
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+__private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) {
+
+    return NULL;
+}
+#elif DEPLOYMENT_TARGET_WINDOWS
+        
+#include <tchar.h>
+
+static uint32_t __CFWin32EncodingIndex = 0;
+static CFStringEncoding *__CFWin32EncodingList = NULL;
+
+static char CALLBACK __CFWin32EnumCodePageProc(LPTSTR string) {
+    uint32_t encoding = CFStringConvertWindowsCodepageToEncoding(_tcstoul(string, NULL, 10));
+    CFIndex idx;
+    
+    if (encoding != kCFStringEncodingInvalidId) { // We list only encodings we know
+        if (__CFWin32EncodingList) {
+            for (idx = 0;idx < (CFIndex)__CFWin32EncodingIndex;idx++) if (__CFWin32EncodingList[idx] == encoding) break;
+            if (idx != __CFWin32EncodingIndex) return true;
+            __CFWin32EncodingList[__CFWin32EncodingIndex] = encoding;
+        }
+        ++__CFWin32EncodingIndex;
+    }
+    return true;
+}
+
+__private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) {
+    CFStringEncoding *encodings;
+
+    EnumSystemCodePages((CODEPAGE_ENUMPROC)&__CFWin32EnumCodePageProc, CP_INSTALLED);
+    __CFWin32EncodingList = (uint32_t *)CFAllocatorAllocate(allocator, sizeof(uint32_t) * __CFWin32EncodingIndex, 0);
+    EnumSystemCodePages((CODEPAGE_ENUMPROC)&__CFWin32EnumCodePageProc, CP_INSTALLED);
+
+    *numberOfConverters = __CFWin32EncodingIndex;
+    encodings = __CFWin32EncodingList;
+
+    __CFWin32EncodingIndex = 0;
+    __CFWin32EncodingList = NULL;
+
+    return encodings;
+}
+#else
+__private_extern__ CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters) { return NULL; }
+#endif
+
+__private_extern__ CFIndex __CFStringEncodingPlatformUnicodeToBytes(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen) {
+
+#if DEPLOYMENT_TARGET_WINDOWS
+    WORD dwFlags = 0;
+    CFIndex usedLen;
+
+    dwFlags |= (flags & (kCFStringEncodingAllowLossyConversion|kCFStringEncodingSubstituteCombinings) ? WC_DEFAULTCHAR : 0);
+    dwFlags |= (flags & kCFStringEncodingComposeCombinings ? WC_COMPOSITECHECK : 0);
+    dwFlags |= (flags & kCFStringEncodingIgnoreCombinings ? WC_DISCARDNS : 0);
+
+    if ((usedLen = WideCharToMultiByte(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCWSTR)characters, numChars, (LPSTR)bytes, maxByteLen, NULL, NULL)) == 0) {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+            CPINFO cpInfo;
+
+            if (!GetCPInfo(CFStringConvertEncodingToWindowsCodepage(encoding), &cpInfo)) {
+                cpInfo.MaxCharSize = 1; // Is this right ???
+            }
+            if (cpInfo.MaxCharSize == 1) {
+                numChars = maxByteLen;
+            } else {
+                usedLen = WideCharToMultiByte(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCWSTR)characters, numChars, NULL, 0, NULL, NULL);
+                usedLen -= maxByteLen;
+                numChars = (numChars > usedLen ? numChars - usedLen : 1);
+            }
+            if (WideCharToMultiByte(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCWSTR)characters, numChars, (LPSTR)bytes, maxByteLen, NULL, NULL) == 0) {
+                if (usedCharLen) *usedCharLen = 0;
+                if (usedByteLen) *usedByteLen = 0;
+            } else {
+                CFIndex lastUsedLen = 0;
+
+                while ((usedLen = WideCharToMultiByte(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCWSTR)characters, ++numChars, (LPSTR)bytes, maxByteLen, NULL, NULL))) lastUsedLen = usedLen;
+                if (usedCharLen) *usedCharLen = (numChars - 1);
+                if (usedByteLen) *usedByteLen = lastUsedLen;
+            }
+
+            return kCFStringEncodingInsufficientOutputBufferLength;
+        } else {
+            return kCFStringEncodingInvalidInputStream;
+        }
+    } else {
+        if (usedCharLen) *usedCharLen = numChars;
+        if (usedByteLen) *usedByteLen = usedLen;
+        return kCFStringEncodingConversionSuccess;
+    }
+#endif /* DEPLOYMENT_TARGET_WINDOWS */
+
+    return kCFStringEncodingConverterUnavailable;
+}
+
+__private_extern__ CFIndex __CFStringEncodingPlatformBytesToUnicode(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) {
+
+#if DEPLOYMENT_TARGET_WINDOWS
+    WORD dwFlags = 0;
+    CFIndex usedLen;
+
+    dwFlags |= (flags & (kCFStringEncodingAllowLossyConversion|kCFStringEncodingSubstituteCombinings) ? 0 : MB_ERR_INVALID_CHARS);
+    dwFlags |= (flags & (kCFStringEncodingUseCanonical|kCFStringEncodingUseHFSPlusCanonical) ? MB_COMPOSITE : MB_PRECOMPOSED);
+
+    if ((usedLen = MultiByteToWideChar(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCSTR)bytes, numBytes, (LPWSTR)characters, maxCharLen) == 0)) {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+            CPINFO cpInfo;
+
+            if (!GetCPInfo(CFStringConvertEncodingToWindowsCodepage(encoding), &cpInfo)) {
+                cpInfo.MaxCharSize = 1; // Is this right ???
+            }
+            if (cpInfo.MaxCharSize == 1) {
+                numBytes = maxCharLen;
+            } else {
+                usedLen = MultiByteToWideChar(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCSTR)bytes, numBytes, (LPWSTR)characters, maxCharLen);
+                usedLen -= maxCharLen;
+                numBytes = (numBytes > usedLen ? numBytes - usedLen : 1);
+            }
+            while ((usedLen = MultiByteToWideChar(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCSTR)bytes, numBytes, (LPWSTR)characters, maxCharLen)) == 0) {
+                if ((--numBytes) == 0) break;
+            }
+            if (usedCharLen) *usedCharLen = usedLen;
+            if (usedByteLen) *usedByteLen = numBytes;
+
+            return kCFStringEncodingInsufficientOutputBufferLength;
+        } else {
+            return kCFStringEncodingInvalidInputStream;
+        }
+    } else {
+        if (usedCharLen) *usedCharLen = usedLen;
+        if (usedByteLen) *usedByteLen = numBytes;
+        return kCFStringEncodingConversionSuccess;
+    }
+#endif /* DEPLOYMENT_TARGET_WINDOWS */
+
+    return kCFStringEncodingConverterUnavailable;
+}
+
+__private_extern__ CFIndex __CFStringEncodingPlatformCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) {
+    CFIndex usedCharLen;
+    return (__CFStringEncodingPlatformBytesToUnicode(encoding, flags, bytes, numBytes, NULL, NULL, 0, &usedCharLen) == kCFStringEncodingConversionSuccess ? usedCharLen : 0);
+}
+
+__private_extern__ CFIndex __CFStringEncodingPlatformByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars) {
+    CFIndex usedByteLen;
+    return (__CFStringEncodingPlatformUnicodeToBytes(encoding, flags, characters, numChars, NULL, NULL, 0, &usedByteLen) == kCFStringEncodingConversionSuccess ? usedByteLen : 0);
+}
+
+#undef __CFCarbonCore_GetTextEncodingBase0
+
index da8913272fcd91b57a296b6f00b69ac914492272..7ed4cdd147d2cbdb8fbb746579371eeeb3192292 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -20,9 +20,9 @@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
-/*     CFPlugIn.c
-       Copyright (c) 1999-2007 Apple Inc.  All rights reserved.
-       Responsibility: Doug Davidson
+/*      CFPlugIn.c
+        Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
+        Responsibility: Doug Davidson
 */
 
 #include "CFBundle_Internal.h"
@@ -47,13 +47,8 @@ CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInType(CFUUIDRef typeID) {
     
     if (array) {
         SInt32 i, c = CFArrayGetCount(array);
-
-        // Use default allocator
         result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
-        
-        for (i=0; i<c; i++) {
-            CFArrayAppendValue(result, _CFPFactoryGetFactoryID((_CFPFactory *)CFArrayGetValueAtIndex(array, i)));
-        }
+        for (i = 0; i < c; i++) CFArrayAppendValue(result, _CFPFactoryGetFactoryID((_CFPFactory *)CFArrayGetValueAtIndex(array, i)));
     }
     return result;
 }
@@ -65,15 +60,10 @@ CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInTypeInPlugIn(CFUUIDRef typeID
     if (array) {
         SInt32 i, c = CFArrayGetCount(array);
         _CFPFactory *factory;
-        
-        // Use default allocator
         result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
-
-        for (i=0; i<c; i++) {
+        for (i = 0; i < c; i++) {
             factory = (_CFPFactory *)CFArrayGetValueAtIndex(array, i);
-            if (_CFPFactoryGetPlugIn(factory) == plugIn) {
-                CFArrayAppendValue(result, _CFPFactoryGetFactoryID(factory));
-            }
+            if (_CFPFactoryGetPlugIn(factory) == plugIn) CFArrayAppendValue(result, _CFPFactoryGetFactoryID(factory));
         }
     }
     return result;
index b451cdf9f9283b5810d25c05f7393bd77020bba8..ff4ef32eaec14edbbd513c2594d76db4c11801d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPlugIn.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFPLUGIN__)
index dcc1af4ec5cd4f10d085eb796d76a7da73c86fbe..33678266eced92aa8581ce27d573b084a6c859e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPlugInCOM.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFPLUGINCOM__)
@@ -101,9 +101,9 @@ CF_EXTERN_C_END
 /* This is a definition of IUnknown as a pure abstract virtual C++ class.  This class will work only with compilers that can produce COM-compatible object layouts for C++ classes.  egcs can not do this.  MetroWerks can do this (if you subclass from __comobject) */
 
 class IUnknown
-#if defined(__MWERKS__) && !defined(__MACH__)
+#if defined(__MWERKS__) && TARGET_OS_WIN32
  : __comobject
-#endif /* __MWERKS__ && !__MACH__ */
+#endif
 {
     public:
     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) = 0;
index 876cce7bd3b1af2c6c9b0f12e1295df15c501bd8..c30e7f9be84d541f085e409b3e0da2277e5b870f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPlugIn_Factory.c
-       Copyright (c) 1999-2007 Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
        Responsibility: Doug Davidson
 */
 
@@ -34,9 +34,8 @@ static CFMutableDictionaryRef _factoriesByTypeID = NULL; /* Value is array of _C
 
 static void _CFPFactoryAddToTable(_CFPFactory *factory) {
     __CFSpinLock(&CFPlugInGlobalDataLock);
-    if (_factoriesByFactoryID == NULL) {
+    if (!_factoriesByFactoryID) {
         CFDictionaryValueCallBacks _factoryDictValueCallbacks = {0, NULL, NULL, NULL, NULL};
-        // Use default allocator
         _factoriesByFactoryID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &_factoryDictValueCallbacks);
     }
     CFDictionarySetValue(_factoriesByFactoryID, factory->_uuid, factory);
@@ -45,9 +44,7 @@ static void _CFPFactoryAddToTable(_CFPFactory *factory) {
 
 static void _CFPFactoryRemoveFromTable(_CFPFactory *factory) {
     __CFSpinLock(&CFPlugInGlobalDataLock);
-    if (_factoriesByFactoryID != NULL) {
-        CFDictionaryRemoveValue(_factoriesByFactoryID, factory->_uuid);
-    }
+    if (_factoriesByFactoryID) CFDictionaryRemoveValue(_factoriesByFactoryID, factory->_uuid);
     __CFSpinUnlock(&CFPlugInGlobalDataLock);
 }
 
@@ -55,11 +52,9 @@ __private_extern__ _CFPFactory *_CFPFactoryFind(CFUUIDRef factoryID, Boolean ena
     _CFPFactory *result = NULL;
     
     __CFSpinLock(&CFPlugInGlobalDataLock);
-    if (_factoriesByFactoryID != NULL) {
+    if (_factoriesByFactoryID) {
         result = (_CFPFactory *)CFDictionaryGetValue(_factoriesByFactoryID, factoryID);
-        if (result && result->_enabled != enabled) {
-            result = NULL;
-        }
+        if (result && result->_enabled != enabled) result = NULL;
     }
     __CFSpinUnlock(&CFPlugInGlobalDataLock);
     return result;
@@ -71,24 +66,15 @@ static void _CFPFactoryDeallocate(_CFPFactory *factory) {
     
     _CFPFactoryRemoveFromTable(factory);
 
-    if (factory->_plugIn) {
-        _CFPlugInRemoveFactory(factory->_plugIn, factory);
-    }
+    if (factory->_plugIn) _CFPlugInRemoveFactory(factory->_plugIn, factory);
 
     /* Remove all types for this factory. */
     c = CFArrayGetCount(factory->_types);
-    while (c--) {
-        _CFPFactoryRemoveType(factory, (CFUUIDRef)CFArrayGetValueAtIndex(factory->_types, c));
-    }
+    while (c-- > 0) _CFPFactoryRemoveType(factory, (CFUUIDRef)CFArrayGetValueAtIndex(factory->_types, c));
     CFRelease(factory->_types);
 
-    if (factory->_funcName) {
-        CFRelease(factory->_funcName);
-    }
-
-    if (factory->_uuid) {
-        CFRelease(factory->_uuid);
-    }
+    if (factory->_funcName) CFRelease(factory->_funcName);
+    if (factory->_uuid) CFRelease(factory->_uuid);
 
     CFAllocatorDeallocate(allocator, factory);
     CFRelease(allocator);
@@ -98,15 +84,14 @@ static _CFPFactory *_CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRef
     _CFPFactory *factory;
     UInt32 size;
     size = sizeof(_CFPFactory);
-    allocator = ((NULL == allocator) ? (CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()) : (CFAllocatorRef)CFRetain(allocator));
+    allocator = (allocator ? (CFAllocatorRef)CFRetain(allocator) : (CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()));
     factory = (_CFPFactory *)CFAllocatorAllocate(allocator, size, 0);
-    if (NULL == factory) {
+    if (!factory) {
         CFRelease(allocator);
         return NULL;
     }
 
     factory->_allocator = allocator;
-
     factory->_uuid = (CFUUIDRef)CFRetain(factoryID);
     factory->_enabled = true;
     factory->_instanceCount = 0;
@@ -133,9 +118,7 @@ __private_extern__ _CFPFactory *_CFPFactoryCreateByName(CFAllocatorRef allocator
 
     factory->_func = NULL;
     factory->_plugIn = plugIn;
-    if (plugIn) {
-        _CFPlugInAddFactory(plugIn, factory);
-    }
+    if (plugIn) _CFPlugInAddFactory(plugIn, factory);
     factory->_funcName = (funcName ? (CFStringRef)CFStringCreateCopy(allocator, funcName) : NULL);
 
     return factory;
@@ -152,15 +135,12 @@ __private_extern__ CFPlugInRef _CFPFactoryGetPlugIn(_CFPFactory *factory) {
 __private_extern__ void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactory *factory, CFUUIDRef typeID) {
     void *result = NULL;
     if (factory->_enabled) {
-        if (factory->_func == NULL) {
+        if (!factory->_func) {
             factory->_func = (CFPlugInFactoryFunction)CFBundleGetFunctionPointerForName(factory->_plugIn, factory->_funcName);
-            if (factory->_func == NULL) {
-                CFLog(__kCFLogPlugIn, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory->_funcName, factory->_uuid, factory->_plugIn);
-            }
+            if (!factory->_func) CFLog(__kCFLogPlugIn, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory->_funcName, factory->_uuid, factory->_plugIn);
 #if BINARY_SUPPORT_CFM
-            else {
-                // return values from CFBundleGetFunctionPointerForName will always be dyld, but
-                // we must force-fault them because pointers to glue code do not fault correctly
+            if (factory->_func) {
+                // return values from CFBundleGetFunctionPointerForName will always be dyld, but we must force-fault them because pointers to glue code do not fault correctly
                 factory->_func = (void *)((uint32_t)(factory->_func) | 0x1);
             }
 #endif /* BINARY_SUPPORT_CFM */
@@ -178,9 +158,7 @@ __private_extern__ void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CF
 
 __private_extern__ void _CFPFactoryDisable(_CFPFactory *factory) {
     factory->_enabled = false;
-    if (factory->_instanceCount == 0) {
-        _CFPFactoryDeallocate(factory);
-    }
+    if (factory->_instanceCount == 0) _CFPFactoryDeallocate(factory);
 }
 
 __private_extern__ Boolean _CFPFactoryIsEnabled(_CFPFactory *factory) {
@@ -201,12 +179,9 @@ __private_extern__ void _CFPFactoryAddType(_CFPFactory *factory, CFUUIDRef typeI
 
     /* Add the factory to the type's array of factories */
     __CFSpinLock(&CFPlugInGlobalDataLock);
-    if (_factoriesByTypeID == NULL) {
-        // Create this from default allocator
-        _factoriesByTypeID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    }
+    if (!_factoriesByTypeID) _factoriesByTypeID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
-    if (array == NULL) {
+    if (!array) {
         CFArrayCallBacks _factoryArrayCallbacks = {0, NULL, NULL, NULL, NULL};
         // Create this from default allocator
         array = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &_factoryArrayCallbacks);
@@ -222,21 +197,17 @@ __private_extern__ void _CFPFactoryRemoveType(_CFPFactory *factory, CFUUIDRef ty
     SInt32 idx;
 
     idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID);
-    if (idx >=0) {
-        CFArrayRemoveValueAtIndex(factory->_types, idx);
-    }
+    if (idx >= 0) CFArrayRemoveValueAtIndex(factory->_types, idx);
 
     /* Remove the factory from the type's list of factories */
     __CFSpinLock(&CFPlugInGlobalDataLock);
-    if (_factoriesByTypeID != NULL) {
+    if (_factoriesByTypeID) {
         CFMutableArrayRef array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
-        if (array != NULL) {
+        if (array) {
             idx = CFArrayGetFirstIndexOfValue(array, CFRangeMake(0, CFArrayGetCount(array)), factory);
-            if (idx >=0) {
+            if (idx >= 0) {
                 CFArrayRemoveValueAtIndex(array, idx);
-                if (CFArrayGetCount(array) == 0) {
-                    CFDictionaryRemoveValue(_factoriesByTypeID, typeID);
-                }
+                if (CFArrayGetCount(array) == 0) CFDictionaryRemoveValue(_factoriesByTypeID, typeID);
             }
         }
     }
@@ -247,16 +218,14 @@ __private_extern__ Boolean _CFPFactorySupportsType(_CFPFactory *factory, CFUUIDR
     SInt32 idx;
 
     idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID);
-    return ((idx >= 0) ? true : false);
+    return (idx >= 0 ? true : false);
 }
 
 __private_extern__ CFArrayRef _CFPFactoryFindForType(CFUUIDRef typeID) {
     CFArrayRef result = NULL;
 
     __CFSpinLock(&CFPlugInGlobalDataLock);
-    if (_factoriesByTypeID != NULL) {
-        result = (CFArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
-    }
+    if (_factoriesByTypeID) result = (CFArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
     __CFSpinUnlock(&CFPlugInGlobalDataLock);
 
     return result;
@@ -266,18 +235,12 @@ __private_extern__ CFArrayRef _CFPFactoryFindForType(CFUUIDRef typeID) {
 __private_extern__ void _CFPFactoryAddInstance(_CFPFactory *factory) {
     /* MF:!!! Assert that factory is enabled. */
     factory->_instanceCount++;
-    if (factory->_plugIn) {
-        _CFPlugInAddPlugInInstance(factory->_plugIn);
-    }
+    if (factory->_plugIn) _CFPlugInAddPlugInInstance(factory->_plugIn);
 }
 
 __private_extern__ void _CFPFactoryRemoveInstance(_CFPFactory *factory) {
     /* MF:!!! Assert that _instanceCount > 0. */
     factory->_instanceCount--;
-    if (factory->_plugIn) {
-        _CFPlugInRemovePlugInInstance(factory->_plugIn);
-    }
-    if ((factory->_instanceCount == 0) && (!factory->_enabled)) {
-        _CFPFactoryDeallocate(factory);
-    }
+    if (factory->_plugIn) _CFPlugInRemovePlugInInstance(factory->_plugIn);
+    if (factory->_instanceCount == 0 && !factory->_enabled) _CFPFactoryDeallocate(factory);
 }
index 4a17ca61eb574642a65fd02736896a63f5972ad1..9b51b294233d06ceda39be338902ceada53e29c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPlugIn_Factory.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFPLUGIN_FACTORY__)
index 077a2d1daf51d6b8136bee29363f420dae00b09b..6f900c228770870b96790bfd96913cf5b56017c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPlugIn_Instance.c
-       Copyright (c) 1999-2007 Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
        Responsibility: Doug Davidson
 */
 
@@ -63,9 +63,7 @@ static void __CFPlugInInstanceDeallocate(CFTypeRef cf) {
         (void)INVOKE_CALLBACK1(instance->deallocateInstanceDataFunction, (void *)(&instance->_instanceData[0]));
     }
 
-    if (instance->factory) {
-        _CFPFactoryRemoveInstance(instance->factory);
-    }
+    if (instance->factory) _CFPFactoryRemoveInstance(instance->factory);
 }
 
 static const CFRuntimeClass __CFPlugInInstanceClass = {
@@ -87,19 +85,16 @@ __private_extern__ void __CFPlugInInstanceInitialize(void) {
 CFTypeID CFPlugInInstanceGetTypeID(void) {
     return __kCFPlugInInstanceTypeID;
 }
+
 CF_EXPORT CFPlugInInstanceRef CFPlugInInstanceCreateWithInstanceDataSize(CFAllocatorRef allocator, CFIndex instanceDataSize, CFPlugInInstanceDeallocateInstanceDataFunction deallocateInstanceFunction, CFStringRef factoryName, CFPlugInInstanceGetInterfaceFunction getInterfaceFunction) {
     CFPlugInInstanceRef instance;
     UInt32 size;
     size = sizeof(struct __CFPlugInInstance) + instanceDataSize - sizeof(CFRuntimeBase);
     instance = (CFPlugInInstanceRef)_CFRuntimeCreateInstance(allocator, __kCFPlugInInstanceTypeID, size, NULL);
-    if (NULL == instance) {
-        return NULL;
-    }
+    if (!instance) return NULL;
 
     instance->factory = _CFPFactoryFind((CFUUIDRef)factoryName, true);
-    if (instance->factory) {
-        _CFPFactoryAddInstance(instance->factory);
-    }
+    if (instance->factory) _CFPFactoryAddInstance(instance->factory);
     instance->getInterfaceFunction = getInterfaceFunction;
     instance->deallocateInstanceDataFunction = deallocateInstanceFunction;
 
@@ -114,9 +109,7 @@ CF_EXPORT Boolean CFPlugInInstanceGetInterfaceFunctionTable(CFPlugInInstanceRef
         FAULT_CALLBACK((void **)&(instance->getInterfaceFunction));
         result = INVOKE_CALLBACK3(instance->getInterfaceFunction, instance, interfaceName, &myFtbl) ? true : false;
     }
-    if (ftbl) {
-        *ftbl = (result ? myFtbl : NULL);
-    }
+    if (ftbl) *ftbl = (result ? myFtbl : NULL);
     return result;
 }
 
index ce68bddcc113c7f49992d32edb66caf716c8b691..879188c3f90b6edb90b430f3fbc2870bec89a7f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -20,9 +20,9 @@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
-/*     CFPlugIn_PlugIn.c
-       Copyright (c) 1999-2007 Apple Inc.  All rights reserved.
-       Responsibility: Doug Davidson
+/*      CFPlugIn_PlugIn.c
+        Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
+        Responsibility: Doug Davidson
 */
 
 #include "CFBundle_Internal.h"
@@ -34,10 +34,10 @@ static void _registerFactory(const void *key, const void *val, void *context) {
     CFStringRef factoryFuncStr = (CFStringRef)val;
     CFBundleRef bundle = (CFBundleRef)context;
     CFUUIDRef factoryID = (CFGetTypeID(factoryIDStr) == CFStringGetTypeID()) ? CFUUIDCreateFromString(kCFAllocatorSystemDefault, factoryIDStr) : NULL;
-    if (NULL == factoryID) factoryID = (CFUUIDRef)CFRetain(factoryIDStr);
+    if (!factoryID) factoryID = (CFUUIDRef)CFRetain(factoryIDStr);
     if (CFGetTypeID(factoryFuncStr) != CFStringGetTypeID() || CFStringGetLength(factoryFuncStr) <= 0) factoryFuncStr = NULL;
     CFPlugInRegisterFactoryFunctionByName(factoryID, bundle, factoryFuncStr);
-    if (NULL != factoryID) CFRelease(factoryID);
+    if (factoryID) CFRelease(factoryID);
 }
 
 static void _registerType(const void *key, const void *val, void *context) {
@@ -48,21 +48,21 @@ static void _registerType(const void *key, const void *val, void *context) {
     CFStringRef curFactoryIDStr;
     CFUUIDRef typeID = (CFGetTypeID(typeIDStr) == CFStringGetTypeID()) ? CFUUIDCreateFromString(kCFAllocatorSystemDefault, typeIDStr) : NULL;
     CFUUIDRef curFactoryID;
-    if (NULL == typeID) typeID = (CFUUIDRef)CFRetain(typeIDStr);
-    if (0 == c && (CFGetTypeID(factoryIDStrArray) != CFArrayGetTypeID())) {
+    if (!typeID) typeID = (CFUUIDRef)CFRetain(typeIDStr);
+    if (0 == c && CFGetTypeID(factoryIDStrArray) != CFArrayGetTypeID()) {
         curFactoryIDStr = (CFStringRef)val;
         curFactoryID = (CFGetTypeID(curFactoryIDStr) == CFStringGetTypeID()) ? CFUUIDCreateFromString(CFGetAllocator(bundle), curFactoryIDStr) : NULL;
-        if (NULL == curFactoryID) curFactoryID = (CFUUIDRef)CFRetain(curFactoryIDStr);
+        if (!curFactoryID) curFactoryID = (CFUUIDRef)CFRetain(curFactoryIDStr);
         CFPlugInRegisterPlugInType(curFactoryID, typeID);
-        if (NULL != curFactoryID) CFRelease(curFactoryID);
-    } else for (i=0; i<c; i++) {
+        if (curFactoryID) CFRelease(curFactoryID);
+    } else for (i = 0; i < c; i++) {
         curFactoryIDStr = (CFStringRef)CFArrayGetValueAtIndex(factoryIDStrArray, i);
         curFactoryID = (CFGetTypeID(curFactoryIDStr) == CFStringGetTypeID()) ? CFUUIDCreateFromString(CFGetAllocator(bundle), curFactoryIDStr) : NULL;
-        if (NULL == curFactoryID) curFactoryID = (CFUUIDRef)CFRetain(curFactoryIDStr);
+        if (!curFactoryID) curFactoryID = (CFUUIDRef)CFRetain(curFactoryIDStr);
         CFPlugInRegisterPlugInType(curFactoryID, typeID);
-        if (NULL != curFactoryID) CFRelease(curFactoryID);
+        if (curFactoryID) CFRelease(curFactoryID);
     }
-    if (NULL != typeID) CFRelease(typeID);
+    if (typeID) CFRelease(typeID);
 }
 
 __private_extern__ Boolean _CFBundleNeedsInitPlugIn(CFBundleRef bundle) {
@@ -71,9 +71,9 @@ __private_extern__ Boolean _CFBundleNeedsInitPlugIn(CFBundleRef bundle) {
     CFStringRef tempStr;
     if (infoDict) {
         factoryDict = (CFDictionaryRef)CFDictionaryGetValue(infoDict, kCFPlugInFactoriesKey);
-        if (factoryDict != NULL && CFGetTypeID(factoryDict) == CFDictionaryGetTypeID()) result = true;
+        if (factoryDict && CFGetTypeID(factoryDict) == CFDictionaryGetTypeID()) result = true;
         tempStr = (CFStringRef)CFDictionaryGetValue(infoDict, kCFPlugInDynamicRegistrationKey);
-        if (tempStr != NULL && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) result = true;
+        if (tempStr && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) result = true;
     }
     return result;
 }
@@ -87,19 +87,13 @@ __private_extern__ void _CFBundleInitPlugIn(CFBundleRef bundle) {
     CFStringRef tempStr;
 
     infoDict = CFBundleGetInfoDictionary(bundle);
-    if (infoDict == NULL) {
-        return;
-    }
+    if (!infoDict) return;
+    
     factoryDict = (CFDictionaryRef)CFDictionaryGetValue(infoDict, kCFPlugInFactoriesKey);
-    if (factoryDict != NULL && CFGetTypeID(factoryDict) != CFDictionaryGetTypeID()) factoryDict = NULL;
+    if (factoryDict && CFGetTypeID(factoryDict) != CFDictionaryGetTypeID()) factoryDict = NULL;
     tempStr = (CFStringRef)CFDictionaryGetValue(infoDict, kCFPlugInDynamicRegistrationKey);
-    if (tempStr != NULL && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
-        doDynamicReg = true;
-    }
-    if (!factoryDict && !doDynamicReg) {
-        // This is not a plugIn.
-        return;
-    }
+    if (tempStr && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) doDynamicReg = true;
+    if (!factoryDict && !doDynamicReg) return;  // This is not a plug-in.
 
     /* loadOnDemand is true by default if the plugIn does not do dynamic registration.  It is false, by default if it does do dynamic registration.  The dynamic register function can set this. */
     __CFBundleGetPlugInData(bundle)->_isPlugIn = true;
@@ -112,14 +106,10 @@ __private_extern__ void _CFBundleInitPlugIn(CFBundleRef bundle) {
     /* Now do the registration */
 
     /* First do static registrations, if any. */
-    if (factoryDict != NULL) {
-        CFDictionaryApplyFunction(factoryDict, _registerFactory, bundle);
-    }
+    if (factoryDict) CFDictionaryApplyFunction(factoryDict, _registerFactory, bundle);
     typeDict = (CFDictionaryRef)CFDictionaryGetValue(infoDict, kCFPlugInTypesKey);
-    if (typeDict != NULL && CFGetTypeID(typeDict) != CFDictionaryGetTypeID()) typeDict = NULL;
-    if (typeDict != NULL) {
-        CFDictionaryApplyFunction(typeDict, _registerType, bundle);
-    }
+    if (typeDict && CFGetTypeID(typeDict) != CFDictionaryGetTypeID()) typeDict = NULL;
+    if (typeDict) CFDictionaryApplyFunction(typeDict, _registerType, bundle);
 
     /* Now set key for dynamic registration if necessary */
     if (doDynamicReg) {
@@ -136,12 +126,10 @@ __private_extern__ void _CFBundlePlugInLoaded(CFBundleRef bundle) {
     if (!__CFBundleGetPlugInData(bundle)->_isPlugIn || __CFBundleGetPlugInData(bundle)->_isDoingDynamicRegistration || !infoDict || !CFBundleIsExecutableLoaded(bundle)) return;
 
     tempStr = (CFStringRef)CFDictionaryGetValue(infoDict, CFSTR("CFPlugInNeedsDynamicRegistration"));
-    if (tempStr != NULL && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+    if (tempStr && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
         CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, CFSTR("CFPlugInNeedsDynamicRegistration"));
         tempStr = (CFStringRef)CFDictionaryGetValue(infoDict, kCFPlugInDynamicRegisterFunctionKey);
-        if (tempStr == NULL || CFGetTypeID(tempStr) != CFStringGetTypeID() || CFStringGetLength(tempStr) <= 0) {
-            tempStr = CFSTR("CFPlugInDynamicRegister");
-        }
+        if (!tempStr || CFGetTypeID(tempStr) != CFStringGetTypeID() || CFStringGetLength(tempStr) <= 0) tempStr = CFSTR("CFPlugInDynamicRegister");
         __CFBundleGetPlugInData(bundle)->_loadOnDemand = false;
         __CFBundleGetPlugInData(bundle)->_isDoingDynamicRegistration = true;
 
@@ -153,10 +141,7 @@ __private_extern__ void _CFBundlePlugInLoaded(CFBundleRef bundle) {
         }
 
         __CFBundleGetPlugInData(bundle)->_isDoingDynamicRegistration = false;
-        if (__CFBundleGetPlugInData(bundle)->_loadOnDemand && (__CFBundleGetPlugInData(bundle)->_instanceCount == 0)) {
-            /* Unload now if we can/should. */
-            CFBundleUnloadExecutable(bundle);
-        }
+        if (__CFBundleGetPlugInData(bundle)->_loadOnDemand && __CFBundleGetPlugInData(bundle)->_instanceCount == 0) CFBundleUnloadExecutable(bundle);   // Unload now if we can/should.
     } else {
         CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, CFSTR("CFPlugInNeedsDynamicRegistration"));
     }
@@ -168,9 +153,7 @@ __private_extern__ void _CFBundleDeallocatePlugIn(CFBundleRef bundle) {
 
         /* Go through factories disabling them.  Disabling these factories should cause them to dealloc since we wouldn't be deallocating if any of the factories had outstanding instances.  So go backwards. */
         c = CFArrayGetCount(__CFBundleGetPlugInData(bundle)->_factories);
-        while (c--) {
-            _CFPFactoryDisable((_CFPFactory *)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(bundle)->_factories, c));
-        }
+        while (c-- > 0) _CFPFactoryDisable((_CFPFactory *)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(bundle)->_factories, c));
         CFRelease(__CFBundleGetPlugInData(bundle)->_factories);
 
         __CFBundleGetPlugInData(bundle)->_isPlugIn = false;
@@ -193,7 +176,7 @@ CFBundleRef CFPlugInGetBundle(CFPlugInRef plugIn) {
 void CFPlugInSetLoadOnDemand(CFPlugInRef plugIn, Boolean flag) {
     if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
         __CFBundleGetPlugInData(plugIn)->_loadOnDemand = flag;
-        if (__CFBundleGetPlugInData(plugIn)->_loadOnDemand && !__CFBundleGetPlugInData(plugIn)->_isDoingDynamicRegistration && (__CFBundleGetPlugInData(plugIn)->_instanceCount == 0)) {
+        if (__CFBundleGetPlugInData(plugIn)->_loadOnDemand && !__CFBundleGetPlugInData(plugIn)->_isDoingDynamicRegistration && __CFBundleGetPlugInData(plugIn)->_instanceCount == 0) {
             /* Unload now if we can/should. */
             /* If we are doing dynamic registration currently, do not unload.  The unloading will happen when dynamic registration is done, if necessary. */
             CFBundleUnloadExecutable(plugIn);
@@ -216,18 +199,13 @@ __private_extern__ void _CFPlugInWillUnload(CFPlugInRef plugIn) {
     if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
         SInt32 c = CFArrayGetCount(__CFBundleGetPlugInData(plugIn)->_factories);
         /* First, flush all the function pointers that may be cached by our factories. */
-        while (c--) {
-            _CFPFactoryFlushFunctionCache((_CFPFactory *)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, c));
-        }
+        while (c-- > 0) _CFPFactoryFlushFunctionCache((_CFPFactory *)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, c));
     }
 }
 
 __private_extern__ void _CFPlugInAddPlugInInstance(CFPlugInRef plugIn) {
     if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
-        if ((__CFBundleGetPlugInData(plugIn)->_instanceCount == 0) && (__CFBundleGetPlugInData(plugIn)->_loadOnDemand)) {
-            /* Make sure we are not scheduled for unloading */
-            _CFBundleUnscheduleForUnloading(CFPlugInGetBundle(plugIn));
-        }
+        if (__CFBundleGetPlugInData(plugIn)->_instanceCount == 0 && __CFBundleGetPlugInData(plugIn)->_loadOnDemand) _CFBundleUnscheduleForUnloading(CFPlugInGetBundle(plugIn));     // Make sure we are not scheduled for unloading
         __CFBundleGetPlugInData(plugIn)->_instanceCount++;
         /* Instances also retain the CFBundle */
         CFRetain(plugIn);
@@ -238,7 +216,7 @@ __private_extern__ void _CFPlugInRemovePlugInInstance(CFPlugInRef plugIn) {
     if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
         /* MF:!!! Assert that instanceCount > 0. */
         __CFBundleGetPlugInData(plugIn)->_instanceCount--;
-        if ((__CFBundleGetPlugInData(plugIn)->_instanceCount == 0) && (__CFBundleGetPlugInData(plugIn)->_loadOnDemand)) {
+        if (__CFBundleGetPlugInData(plugIn)->_instanceCount == 0 && __CFBundleGetPlugInData(plugIn)->_loadOnDemand) {
             // We unload the code lazily because the code that caused this function to be called is probably code from the plugin itself.  If we unload now, we will hose things.
             //CFBundleUnloadExecutable(plugIn);
             _CFBundleScheduleForUnloading(CFPlugInGetBundle(plugIn));
@@ -250,16 +228,12 @@ __private_extern__ void _CFPlugInRemovePlugInInstance(CFPlugInRef plugIn) {
 }
 
 __private_extern__ void _CFPlugInAddFactory(CFPlugInRef plugIn, _CFPFactory *factory) {
-    if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
-        CFArrayAppendValue(__CFBundleGetPlugInData(plugIn)->_factories, factory);
-    }
+    if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) CFArrayAppendValue(__CFBundleGetPlugInData(plugIn)->_factories, factory);
 }
 
 __private_extern__ void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactory *factory) {
     if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
         SInt32 idx = CFArrayGetFirstIndexOfValue(__CFBundleGetPlugInData(plugIn)->_factories, CFRangeMake(0, CFArrayGetCount(__CFBundleGetPlugInData(plugIn)->_factories)), factory);
-        if (idx >= 0) {
-            CFArrayRemoveValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, idx);
-        }
+        if (idx >= 0) CFArrayRemoveValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, idx);
     }
 }
index 6e9083dcd84b8b165a279da440a1a88a38b16f7e..fe25404ab36bd1d173ca1f982a8ad540710f6e41 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPreferences.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Chris Parker
 */
 
 #include <CoreFoundation/CFPreferences.h>
 #include <CoreFoundation/CFURLAccess.h>
-#ifndef __WIN32__
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <CoreFoundation/CFUserNotification.h>
 #endif
 #include <CoreFoundation/CFPropertyList.h>
 #include <CoreFoundation/CFBundle.h>
 #include <CoreFoundation/CFNumber.h>
 #include <CoreFoundation/CFPriv.h>
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
 #include <sys/stat.h>
 #if DEPLOYMENT_TARGET_MACOSX
 #include <unistd.h>
-#endif //__MACH__
+#include <CoreFoundation/CFUUID.h>
+#endif
 
 #if DEBUG_PREFERENCES_MEMORY
 #include "../Tests/CFCountingAllocator.c"
@@ -95,46 +96,101 @@ CF_EXPORT void CFPreferencesDumpMem(void) {
 #pragma mark Determining host UUID
 #endif
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+// The entry point is in libSystem.B.dylib, but not actually declared
+// If this becomes available in a header (<rdar://problem/4943036>), I need to pull this out
+int gethostuuid(unsigned char *uuid_buf, const struct timespec *timeoutp);
+
+__private_extern__ CFStringRef _CFGetHostUUIDString(void) {
+    static CFStringRef __hostUUIDString = NULL;
+    
+    if (!__hostUUIDString) {
+        CFUUIDBytes uuidBytes;
+        int getuuidErr = 0;
+        struct timespec timeout = {0, 0};   // Infinite timeout for gethostuuid()
+        
+        getuuidErr = gethostuuid((unsigned char *)&uuidBytes, &timeout);
+        if (getuuidErr == -1) {
+            // An error has occurred trying to get the host UUID string. There's nothing we can do here, so we should just return NULL.
+            CFLog(kCFLogLevelWarning, CFSTR("_CFGetHostUUIDString: unable to determine UUID for host. Error: %d"), errno);
+            return NULL;
+        }
+        
+        CFUUIDRef uuidRef = CFUUIDCreateFromUUIDBytes(kCFAllocatorSystemDefault, uuidBytes);
+        CFStringRef uuidAsString = CFUUIDCreateString(kCFAllocatorSystemDefault, uuidRef);
+        
+        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)uuidAsString, (void *)&__hostUUIDString)) {
+            CFRelease(uuidAsString);    // someone else made the assignment, so just release the extra string.
+        }
+        
+        CFRelease(uuidRef);
+    }
+    
+    return __hostUUIDString;
+}
+
+__private_extern__ CFStringRef _CFPreferencesGetByHostIdentifierString(void) {
+    static CFStringRef __byHostIdentifierString = NULL;
+
+    if (!__byHostIdentifierString) {
+        CFStringRef hostID = _CFGetHostUUIDString();
+        if (hostID) {
+            if (CFStringHasPrefix(hostID, CFSTR("00000000-0000-1000-8000-"))) {
+                // If the host UUID is prefixed by "00000000-0000-1000-8000-" then the UUID returned is the "compatible" type. The last field of the string will be the MAC address of the primary ethernet interface of the computer. We use this for compatibility with existing by-host preferences.
+                CFStringRef lastField = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, hostID, CFRangeMake(24, 12));
+                CFMutableStringRef tmpstr = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, lastField);
+                CFStringLowercase(tmpstr, NULL);
+                CFStringRef downcasedField = CFStringCreateCopy(kCFAllocatorSystemDefault, tmpstr);
+                
+                if (!OSAtomicCompareAndSwapPtrBarrier(NULL, (void *)downcasedField, (void *)&__byHostIdentifierString)) {
+                    CFRelease(downcasedField);
+                }
+                
+                CFRelease(tmpstr);
+                CFRelease(lastField);
+            } else {
+                // The host UUID is a full UUID, and we should just use that. This doesn't involve any additional string creation, so we should just be able to do the assignment.
+                __byHostIdentifierString = hostID;
+            }
+        } else {
+            __byHostIdentifierString = CFSTR("UnknownHostID");
+        }
+    }
+    
+    return __byHostIdentifierString;
+}
+
+#else
 
 __private_extern__ CFStringRef _CFPreferencesGetByHostIdentifierString(void) {
     return CFSTR("");
 }
 
+#endif
 
 
 static unsigned long __CFSafeLaunchLevel = 0;
 
-#if 0
+#if DEPLOYMENT_TARGET_WINDOWS
 #include <shfolder.h>
 
-CF_INLINE CFIndex strlen_UniChar(const UniChar* p) {
-       CFIndex result = 0;
-       while ((*p++) != 0)
-               ++result;
-       return result;
-}
-
 #endif
 
 static CFURLRef _preferencesDirectoryForUserHostSafetyLevel(CFStringRef userName, CFStringRef hostName, unsigned long safeLevel) {
     CFAllocatorRef alloc = __CFPreferencesAllocator();
-#if 0
+#if DEPLOYMENT_TARGET_WINDOWS
 
        CFURLRef url = NULL;
 
-       UniChar szPath[MAX_PATH];
-       if (S_OK == SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, (LPWSTR) szPath)) {
-               CFStringRef directoryPath = CFStringCreateWithCharacters(alloc, szPath, strlen_UniChar(szPath));
-               if (directoryPath) {
-                       CFStringRef completePath = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@\\Apple\\"), directoryPath);
-                       if (completePath) {
-                               url = CFURLCreateWithFileSystemPath(alloc, completePath, kCFURLWindowsPathStyle, true);
-                               CFRelease(completePath);
-                       }
-                       CFRelease(directoryPath);
-               }
+       CFMutableStringRef completePath = _CFCreateApplicationRepositoryPath(alloc, CSIDL_APPDATA);
+       if (completePath) {
+           // append "Preferences\" and make the CFURL
+           CFStringAppend(completePath, CFSTR("Preferences\\"));
+               url = CFURLCreateWithFileSystemPath(alloc, completePath, kCFURLWindowsPathStyle, true);
+               CFRelease(completePath);
        }
 
+
        // Can't find a better place?  Home directory then?
        if (url == NULL)
                url = CFCopyHomeDirectoryURLForUser((userName == kCFPreferencesCurrentUser) ? NULL : userName);
@@ -409,7 +465,7 @@ static CFStringRef  _CFPreferencesStandardDomainCacheKey(CFStringRef  domainName
 static CFURLRef _CFPreferencesURLForStandardDomainWithSafetyLevel(CFStringRef domainName, CFStringRef userName, CFStringRef hostName, unsigned long safeLevel) {
     CFURLRef theURL = NULL;
     CFAllocatorRef prefAlloc = __CFPreferencesAllocator();
-#if (DEPLOYMENT_TARGET_MACOSX) || defined(__WIN32__)
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS
     CFURLRef prefDir = _preferencesDirectoryForUserHostSafetyLevel(userName, hostName, safeLevel);
     CFStringRef  appName;
     CFStringRef  fileName;
@@ -443,7 +499,11 @@ static CFURLRef _CFPreferencesURLForStandardDomainWithSafetyLevel(CFStringRef do
        CFRelease(appName);
     }
     if (fileName) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
         theURL = CFURLCreateWithFileSystemPathRelativeToBase(prefAlloc, fileName, kCFURLPOSIXPathStyle, false, prefDir);
+#elif DEPLOYMENT_TARGET_WINDOWS
+               theURL = CFURLCreateWithFileSystemPathRelativeToBase(prefAlloc, fileName, kCFURLWindowsPathStyle, false, prefDir);
+#endif
         if (prefDir) CFRelease(prefDir);
         CFRelease(fileName);
     }
index 7383f11502cb8f69fc3f46d5f538a6129be8db22..a026cd62de44677f2e9838b48c9c2fa19720257e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPreferences.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFPREFERENCES__)
index ae662c9ac4fefbd69f07a18e35324a67344107fc..56e28a00c55d095b8de744d04b359d5ea3a98f21 100644 (file)
--- a/CFPriv.h
+++ b/CFPriv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPriv.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 /*
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFURL.h>
 #include <CoreFoundation/CFBundlePriv.h>
+#include <pthread.h>
+#include <math.h>
 
 
-#if defined(__MACH__)
+
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
 #include <CoreFoundation/CFMachPort.h>
 #endif
 
-#if defined(__MACH__) || defined(__WIN32__)
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || TARGET_OS_WIN32
 #include <CoreFoundation/CFRunLoop.h>
 #include <CoreFoundation/CFSocket.h>
 #endif
 
-#if defined(__MACH__)
-#include <CoreFoundation/CFMachPort.h>
-#endif
-
-#if 0
-#include <shlobj.h>
-#endif
-
 CF_EXTERN_C_BEGIN
 
 CF_EXPORT intptr_t _CFDoOperation(intptr_t code, intptr_t subcode1, intptr_t subcode2);
@@ -67,7 +62,7 @@ CF_EXPORT const char **_CFGetProcessPath(void);
 CF_EXPORT const char **_CFGetProgname(void);
 
 
-#if defined(__MACH__)
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
 CF_EXPORT CFRunLoopRef CFRunLoopGetMain(void);
 CF_EXPORT SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled);
 
@@ -78,20 +73,21 @@ CF_EXPORT void _CFRunLoopAddModeToMode(CFRunLoopRef rl, CFStringRef modeName, CF
 CF_EXPORT void _CFRunLoopRemoveModeFromMode(CFRunLoopRef rl, CFStringRef modeName, CFStringRef fromModeName);
 CF_EXPORT void _CFRunLoopStopMode(CFRunLoopRef rl, CFStringRef modeName);
 
-#if defined(__MACH__)
 CF_EXPORT CFIndex CFMachPortGetQueuedMessageCount(CFMachPortRef mp);
-#endif
 
 CF_EXPORT CFPropertyListRef _CFURLCopyPropertyListRepresentation(CFURLRef url);
-CF_EXPORT CFURLRef _CFURLCreateFromPropertyListRepresentation(CFAllocatorRef alloc, CFPropertyListRef pListRepresentation);
 #endif
 CF_EXPORT CFPropertyListRef _CFURLCopyPropertyListRepresentation(CFURLRef url);
 CF_EXPORT CFURLRef _CFURLCreateFromPropertyListRepresentation(CFAllocatorRef alloc, CFPropertyListRef pListRepresentation);
 
 CF_EXPORT void CFPreferencesFlushCaches(void);
 
+#if TARGET_OS_WIN32
+CF_EXPORT Boolean _CFURLGetWideFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBase, wchar_t *buffer, CFIndex bufferLength);
+#endif
+
 #if !__LP64__
-#if !defined(__WIN32__)
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
 struct FSSpec;
 CF_EXPORT
 Boolean _CFGetFSSpecFromURL(CFAllocatorRef alloc, CFURLRef url, struct FSSpec *spec);
@@ -166,11 +162,6 @@ CF_EXPORT
 CFURLRef CFCopyHomeDirectoryURLForUser(CFStringRef uName);     /* Pass NULL for the current user's home directory */
 
 
-/* Extra user notification key for iPhone */
-CF_EXPORT
-const CFStringRef kCFUserNotificationKeyboardTypesKey AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
-
-
 /*
        CFCopySearchPathForDirectoriesInDomains returns the various
        standard system directories where apps, resources, etc get
@@ -223,7 +214,7 @@ CF_EXPORT const CFStringRef kCFHTTPURLStatusLine;
 
 
 /* System Version file access */
-CF_EXPORT CFStringRef CFCopySystemVersionString(void);                 // Human-readable string containing both marketing and build version, should be API'd
+CF_EXPORT CFStringRef CFCopySystemVersionString(void);                 // Human-readable string containing both marketing and build version
 CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void);
 CF_EXPORT CFDictionaryRef _CFCopyServerVersionDictionary(void);
 CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey;
@@ -252,9 +243,11 @@ enum {
     CFSystemVersionPinot = 3,           /* Deprecated name for Panther */
     CFSystemVersionTiger = 4,           /* 10.4 */
     CFSystemVersionMerlot = 4,          /* Deprecated name for Tiger */
-    CFSystemVersionLeopard = 5,         /* Post-Tiger */
+    CFSystemVersionLeopard = 5,         /* 10.5 */
     CFSystemVersionChablis = 5,         /* Deprecated name for Leopard */
-    CFSystemVersionMax                  /* This should bump up when new entries are added */
+    CFSystemVersionSnowLeopard = 6,    /* 10.6 */
+    CFSystemVersionMax,                 /* This should bump up when new entries are added */
+
 };
 typedef CFIndex CFSystemVersion;
 
@@ -273,14 +266,24 @@ CF_EXPORT CFRange CFStringGetRangeOfCharacterClusterAtIndex(CFStringRef string,
 
 // Compatibility kCFCompare flags. Use the new public kCFCompareDiacriticInsensitive
 enum {
-    kCFCompareDiacriticsInsensitive = 128, /* kCFCompareDiacriticInsensitive */
-    kCFCompareDiacriticsInsensitiveCompatibilityMask = ((1 << 28)|kCFCompareDiacriticsInsensitive),
+    kCFCompareDiacriticsInsensitive = 128 /* Use kCFCompareDiacriticInsensitive */
+};
+
+/* kCFCompare flags planned to be publicized (Aki 10/20/2008 Does not work with kCFCompareForceOrdering/CFStringFold). see <rdar://problem/6305147>)
+ */
+enum {
+    kCFCompareIgnoreNonAlphanumeric = (1UL << 16), // Ignores characters NOT in kCFCharacterSetAlphaNumeric
 };
 
+
 /* CFStringEncoding SPI */
 /* When set, CF encoding conversion engine keeps ASCII compatibility. (i.e. ASCII backslash <-> Unicode backslash in MacJapanese */
 CF_EXPORT void _CFStringEncodingSetForceASCIICompatibility(Boolean flag);
 
+extern void __CFSetCharToUniCharFunc(Boolean (*func)(UInt32 flags, UInt8 ch, UniChar *unicodeChar));
+extern UniChar __CFCharToUniCharTable[256];
+
+
 #if defined(CF_INLINE)
 CF_INLINE const UniChar *CFStringGetCharactersPtrFromInlineBuffer(CFStringInlineBuffer *buf, CFRange desiredRange) {
     if ((desiredRange.location < 0) || ((desiredRange.location + desiredRange.length) > buf->rangeToBuffer.length)) return NULL;
@@ -359,9 +362,9 @@ typedef struct {
 
 // Bits for flags field
 enum {
-    kCFCharacterSetIsCompactBitmap = (1 << 0),
-    kCFCharacterSetNoBitmapAvailable = (1 << 1),
-    kCFCharacterSetIsInverted = (1 << 2)
+    kCFCharacterSetIsCompactBitmap = (1UL << 0),
+    kCFCharacterSetNoBitmapAvailable = (1UL << 1),
+    kCFCharacterSetIsInverted = (1UL << 2)
 };
 
 /*!
@@ -391,7 +394,7 @@ CF_INLINE bool CFCharacterSetInlineBufferIsLongCharacterMember(CFCharacterSetInl
         if (NULL == buffer->bitmap) {
             if (0 == (buffer->flags & kCFCharacterSetIsCompactBitmap)) isInverted = !isInverted;
         } else if (0 == (buffer->flags & kCFCharacterSetIsCompactBitmap)) {
-            if (buffer->bitmap[character >> 3] & (1 << (character & 7))) isInverted = !isInverted;
+            if (buffer->bitmap[character >> 3] & (1UL << (character & 7))) isInverted = !isInverted;
         } else {
             uint8_t value = buffer->bitmap[character >> 8];
             
@@ -400,7 +403,7 @@ CF_INLINE bool CFCharacterSetInlineBufferIsLongCharacterMember(CFCharacterSetInl
             } else if (value > 0) {
                 const uint8_t *segment = buffer->bitmap + (256 + (32 * (value - 1)));
                 character &= 0xFF;
-                if (segment[character >> 3] & (1 << (character % 8))) isInverted = !isInverted;
+                if (segment[character >> 3] & (1UL << (character % 8))) isInverted = !isInverted;
             }
         }
     }
@@ -411,7 +414,37 @@ CF_INLINE bool CFCharacterSetInlineBufferIsLongCharacterMember(CFCharacterSetInl
 #endif /* CF_INLINE */
 
 
-#if defined(__MACH__)
+#if TARGET_OS_WIN32
+CF_EXPORT CFMutableStringRef _CFCreateApplicationRepositoryPath(CFAllocatorRef alloc, int nFolder);
+#endif
+
+/*
+ CFLocaleGetLanguageRegionEncodingForLocaleIdentifier gets the appropriate language and region codes,
+ and the default legacy script code and encoding, for the specified locale (or language) string.
+ Returns false if CFLocale has no information about the given locale; otherwise may set
+ *langCode and/or *regCode to -1 if there is no appropriate legacy value for the locale.
+ This is a replacement for the CFBundle SPI CFBundleGetLocalizationInfoForLocalization (which was intended to be temporary and transitional);
+ this function is more up-to-date in its handling of locale strings, and is in CFLocale where this functionality should belong. Compared
+ to CFBundleGetLocalizationInfoForLocalization, this function does not spcially interpret a NULL localeIdentifier to mean use the single most
+ preferred localization in the current context (this function returns NO for a NULL localeIdentifier); and in this function
+ langCode, regCode, and scriptCode are all SInt16* (not SInt32* like the equivalent parameters in CFBundleGetLocalizationInfoForLocalization).
+*/
+CF_EXPORT
+Boolean CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(CFStringRef localeIdentifier, LangCode *langCode, RegionCode *regCode, ScriptCode *scriptCode, CFStringEncoding *stringEncoding);
+
+#if TARGET_OS_WIN32
+CF_EXPORT CFMutableStringRef _CFCreateApplicationRepositoryPath(CFAllocatorRef alloc, int nFolder);
+#endif
+
+#if TARGET_OS_WIN32
+#include <CoreFoundation/CFMessagePort.h>
+
+#define CF_MESSAGE_PORT_CLONE_MESSAGE_ID -1209
+CF_EXPORT CFMessagePortRef     CFMessagePortCreateUber(CFAllocatorRef allocator, CFStringRef name, CFMessagePortCallBack callout, CFMessagePortContext *context, Boolean *shouldFreeInfo, Boolean isRemote);
+CF_EXPORT void CFMessagePortSetCloneCallout(CFMessagePortRef ms, CFMessagePortCallBack cloneCallout);
+#endif
+
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
 #include <CoreFoundation/CFMessagePort.h>
 
 CFMessagePortRef CFMessagePortCreatePerProcessLocal(CFAllocatorRef allocator, CFStringRef name, CFMessagePortCallBack callout, CFMessagePortContext *context, Boolean *shouldFreeInfo);
@@ -419,6 +452,31 @@ CFMessagePortRef CFMessagePortCreatePerProcessRemote(CFAllocatorRef allocator, C
 #endif
 
 
+CF_INLINE CFAbsoluteTime _CFAbsoluteTimeFromFileTimeSpec(struct timespec ts) {
+    return (CFAbsoluteTime)((CFTimeInterval)ts.tv_sec - kCFAbsoluteTimeIntervalSince1970) + (1.0e-9 * (CFTimeInterval)ts.tv_nsec);
+}
+
+#if 0
+CF_INLINE struct timespec _CFFileTimeSpecFromAbsoluteTime(CFAbsoluteTime at) {
+   struct timespec ts;
+   double sec = 0.0;
+   double frac = modf(at, &sec);
+   if (frac < 0.0) {
+       frac += 1.0;
+       sec -= 1.0;
+   }
+   ts.tv_sec = (time_t)(sec + kCFAbsoluteTimeIntervalSince1970);
+   ts.tv_nsec = (long)(NSEC_PER_SEC * frac + 0.5);
+   return ts;
+}
+#endif
+
+#if TARGET_OS_WIN32
+CF_EXPORT CFStringRef _CFGetWindowsAppleAppDataDirectory(void);
+CF_EXPORT CFArrayRef _CFGetWindowsBinaryDirectories(void);
+CF_EXPORT CFStringRef _CFGetWindowsAppleSystemLibraryDirectory(void);
+#endif
+
 CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFPRIV__ */
index e3a5392897570b88b0b51105d4f971525d177eb4..f7f437e7d8e7e905b91cbb9770509354dd3b6a52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPropertyList.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
-       Responsibility: Christopher Kane
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
+       Responsibility: Tony Parker
 */
 
 #include <CoreFoundation/CFPropertyList.h>
 #include <CoreFoundation/CFDate.h>
 #include <CoreFoundation/CFNumber.h>
 #include <CoreFoundation/CFSet.h>
-#include "CFPriv.h"
-#include "CFStringEncodingConverter.h"
-#include "CFInternal.h"
+#include <CoreFoundation/CFError.h>
+#include <CoreFoundation/CFError_Private.h>
+#include <CoreFoundation/CFPriv.h>
+#include <CoreFoundation/CFStringEncodingConverter.h>
+#include <CoreFoundation/CFInternal.h>
 #include <CoreFoundation/CFStream.h>
 #include <CoreFoundation/CFCalendar.h>
+#include "CFLocaleInternal.h"
 #include <limits.h>
 #include <float.h>
 #include <string.h>
 #include <stdlib.h>
 #include <math.h>
 #include <ctype.h>
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <CoreFoundation/CFPreferences.h>
 #include <mach-o/dyld.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 
@@ -84,6 +90,9 @@ intptr_t _CFDoOperation(intptr_t code, intptr_t subcode1, intptr_t subcode2) {
 #define DOCTYPE_TAG_LENGTH     7
 #define CDSECT_TAG_LENGTH      9
 
+// Used to reference an old-style plist parser error inside of a more general XML error
+#define CFPropertyListOldStyleParserErrorKey     CFSTR("kCFPropertyListOldStyleParsingError")
+
 // don't allow _CFKeyedArchiverUID here
 #define __CFAssertIsPList(cf) CFAssert2(CFGetTypeID(cf) == CFStringGetTypeID() || CFGetTypeID(cf) == CFArrayGetTypeID() || CFGetTypeID(cf) == CFBooleanGetTypeID() || CFGetTypeID(cf) == CFNumberGetTypeID() || CFGetTypeID(cf) == CFDictionaryGetTypeID() || CFGetTypeID(cf) == CFDateGetTypeID() || CFGetTypeID(cf) == CFDataGetTypeID(), __kCFLogAssertion, "%s(): %p not of a property list type", __PRETTY_FUNCTION__, cf);
 
@@ -122,6 +131,41 @@ static void initStatics() {
     }
 }
 
+__private_extern__ CFErrorRef __CFPropertyListCreateError(CFAllocatorRef allocator, CFIndex code, CFStringRef debugString, ...) {    
+    va_list argList;        
+    CFErrorRef error = NULL;
+    
+    if (debugString != NULL) {
+        CFStringRef debugMessage = NULL;
+        va_start(argList, debugString);
+        debugMessage = CFStringCreateWithFormatAndArguments(allocator, NULL, debugString, argList);
+        va_end(argList);
+    
+        CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(allocator, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 
+        CFDictionarySetValue(userInfo, kCFErrorDebugDescriptionKey, debugMessage);
+                
+        error = CFErrorCreate(allocator, kCFErrorDomainCocoa, code, userInfo);
+        
+        CFRelease(debugMessage);
+        CFRelease(userInfo);
+    } else {
+        error = CFErrorCreate(allocator, kCFErrorDomainCocoa, code, NULL);
+    }
+    
+    return error;
+}
+
+CFStringRef __CFPropertyListCopyErrorDebugDescription(CFErrorRef error) {
+    CFStringRef result = NULL;
+    if (error) {
+        CFDictionaryRef userInfo = CFErrorCopyUserInfo(error);
+        result = CFStringCreateCopy(kCFAllocatorDefault, (CFStringRef)CFDictionaryGetValue(userInfo, kCFErrorDebugDescriptionKey));
+        CFRelease(userInfo);
+    }
+    return result;
+}
+
+
 struct context {
     bool answer;
     CFMutableSetRef set;
@@ -158,15 +202,18 @@ static bool __CFPropertyListIsValidAux(CFPropertyListRef plist, bool recursive,
     if (!plist) CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListIsValid(): property lists cannot contain NULL"));
 #endif
     if (!plist) return false;
-    type = CFGetTypeID(plist);
+    type = CFGetTypeID(plist);    
     if (stringtype == type) return true;
     if (datatype == type) return true;
     if (kCFPropertyListOpenStepFormat != format) {
        if (booltype == type) return true;
        if (numbertype == type) return true;
        if (datetype == type) return true;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
        if (_CFKeyedArchiverUIDGetTypeID() == type) return true;
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     }
     if (!recursive && arraytype == type) return true;
@@ -229,11 +276,10 @@ typedef struct {
     const UniChar *begin; // first character of the XML to be parsed
     const UniChar *curr;  // current parse location
     const UniChar *end;   // the first character _after_ the end of the XML
-    CFStringRef errorString;
+    CFErrorRef error;
     CFAllocatorRef allocator;
     UInt32 mutabilityOption;
     CFMutableSetRef stringSet;  // set of all strings involved in this parse; allows us to share non-mutable strings in the returned plist
-    CFMutableStringRef tmpString; // Mutable string with external characters that functions can feel free to use as temporary storage as the parse progresses
     Boolean allowNewTypes; // Whether to allow the new types supported by XML property lists, but not by the old, OPENSTEP ASCII property lists (CFNumber, CFBoolean, CFDate)
     char _padding[3];
 } _CFXMLPlistParseInfo;
@@ -455,7 +501,7 @@ static void _CFAppendXML0(CFTypeRef object, UInt32 indentation, CFMutableDataRef
         _plistAppendUTF8CString(xmlString, "</");
         _plistAppendCharacters(xmlString, CFXMLPlistTags[STRING_IX], STRING_TAG_LENGTH);
         _plistAppendUTF8CString(xmlString, ">\n");
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
     } else if (typeID == _CFKeyedArchiverUIDGetTypeID()) {
         _plistAppendUTF8CString(xmlString, "<");
         _plistAppendCharacters(xmlString, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH);
@@ -485,7 +531,7 @@ static void _CFAppendXML0(CFTypeRef object, UInt32 indentation, CFMutableDataRef
         _plistAppendUTF8CString(xmlString, "</");
         _plistAppendCharacters(xmlString, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH);
         _plistAppendUTF8CString(xmlString, ">\n");
-#elif 0
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
@@ -565,7 +611,7 @@ static void _CFAppendXML0(CFTypeRef object, UInt32 indentation, CFMutableDataRef
        m = date.minute;
        s = (int32_t)date.second;
 #else
-       CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFGregorianCalendar);
+       CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFCalendarIdentifierGregorian);
        CFTimeZoneRef tz = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, CFSTR("GMT"), true);
        CFCalendarSetTimeZone(calendar, tz);
        CFCalendarDecomposeAbsoluteTime(calendar, CFDateGetAbsoluteTime((CFDateRef)object), (const uint8_t *)"yMdHms", &y, &M, &d, &H, &m, &s);
@@ -628,24 +674,25 @@ static void _CFGenerateXMLPropertyListToData(CFMutableDataRef xml, CFTypeRef pro
     _plistAppendUTF8CString(xml, ">\n");
 }
 
-CFDataRef CFPropertyListCreateXMLData(CFAllocatorRef allocator, CFPropertyListRef propertyList) {
+CFDataRef _CFPropertyListCreateXMLData(CFAllocatorRef allocator, CFPropertyListRef propertyList, Boolean checkValidPlist) {
     initStatics();
     CFMutableDataRef xml;
     CFAssert1(propertyList != NULL, __kCFLogAssertion, "%s(): Cannot be called with a NULL property list", __PRETTY_FUNCTION__);
-    __CFAssertIsPList(propertyList);
-       if (!CFPropertyListIsValid(propertyList, kCFPropertyListXMLFormat_v1_0)) return NULL;
+    if (checkValidPlist && !CFPropertyListIsValid(propertyList, kCFPropertyListXMLFormat_v1_0)) {
+        __CFAssertIsPList(propertyList);
+        return NULL;
+    }
     xml = CFDataCreateMutable(allocator, 0);
     _CFGenerateXMLPropertyListToData(xml, propertyList);
     return xml;
 }
 
-CFDataRef _CFPropertyListCreateXMLDataWithExtras(CFAllocatorRef allocator, CFPropertyListRef propertyList) {
-    initStatics();
-    CFMutableDataRef xml;
-    CFAssert1(propertyList != NULL, __kCFLogAssertion, "%s(): Cannot be called with a NULL property list", __PRETTY_FUNCTION__);
-    xml = CFDataCreateMutable(allocator, 0);
-    _CFGenerateXMLPropertyListToData(xml, propertyList);
-    return xml;
+CFDataRef CFPropertyListCreateXMLData(CFAllocatorRef allocator, CFPropertyListRef propertyList) {
+    return _CFPropertyListCreateXMLData(allocator, propertyList, true);
+}
+
+CF_EXPORT CFDataRef _CFPropertyListCreateXMLDataWithExtras(CFAllocatorRef allocator, CFPropertyListRef propertyList) {
+    return _CFPropertyListCreateXMLData(allocator, propertyList, false);
 }
 
 // ========================================================================
@@ -703,7 +750,7 @@ static void skipXMLComment(_CFXMLPlistParseInfo *pInfo) {
         }
         p ++; 
     }
-    pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unterminated comment started on line %d"), lineNumber(pInfo));
+    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unterminated comment started on line %d"), lineNumber(pInfo));
 }
 
 // stringToMatch and buf must both be of at least len
@@ -735,14 +782,14 @@ static void skipXMLProcessingInstruction(_CFXMLPlistParseInfo *pInfo) {
         pInfo->curr ++; 
     }
     pInfo->curr = begin;
-    pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected EOF while parsing the processing instruction begun on line %d"), lineNumber(pInfo));
+    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF while parsing the processing instruction begun on line %d"), lineNumber(pInfo));
 }
 
 // first character should be immediately after the "<!"
 static void skipDTD(_CFXMLPlistParseInfo *pInfo) {
     // First pass "DOCTYPE"
     if (pInfo->end - pInfo->curr < DOCTYPE_TAG_LENGTH || !matchString(pInfo->curr, CFXMLPlistTags[DOCTYPE_IX], DOCTYPE_TAG_LENGTH)) {
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Malformed DTD on line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Malformed DTD on line %d"), lineNumber(pInfo));
         return;
     }
     pInfo->curr += DOCTYPE_TAG_LENGTH;
@@ -759,23 +806,23 @@ static void skipDTD(_CFXMLPlistParseInfo *pInfo) {
         pInfo->curr ++;
     }
     if (pInfo->curr == pInfo->end) {
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF while parsing DTD", CFStringGetSystemEncoding());
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF while parsing DTD"));
         return;
     }
 
     // *Sigh* Must parse in-line DTD
     skipInlineDTD(pInfo);
-    if (pInfo->errorString)  return;
+    if (pInfo->error)  return;
     skipWhitespace(pInfo);
-    if (pInfo->errorString) return;
+    if (pInfo->error) return;
     if (pInfo->curr < pInfo->end) {
         if (*(pInfo->curr) == '>') {
             pInfo->curr ++;
         } else {
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected character %c on line %d while parsing DTD"), *(pInfo->curr), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d while parsing DTD"), *(pInfo->curr), lineNumber(pInfo));
         }
     } else {
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF while parsing DTD", CFStringGetSystemEncoding());
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF while parsing DTD"));
     }
 }
 
@@ -788,12 +835,12 @@ static void skipPERef(_CFXMLPlistParseInfo *pInfo) {
         }
         p ++;
     }
-    pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected EOF while parsing percent-escape sequence begun on line %d"), lineNumber(pInfo));
+    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF while parsing percent-escape sequence begun on line %d"), lineNumber(pInfo));
 }
 
 // First character should be just past '['
 static void skipInlineDTD(_CFXMLPlistParseInfo *pInfo) {
-    while (!pInfo->errorString && pInfo->curr < pInfo->end) {
+    while (!pInfo->error && pInfo->curr < pInfo->end) {
         UniChar ch;
         skipWhitespace(pInfo);
         ch = *pInfo->curr;
@@ -803,7 +850,7 @@ static void skipInlineDTD(_CFXMLPlistParseInfo *pInfo) {
         } else if (ch == '<') {
             pInfo->curr ++;
             if (pInfo->curr >= pInfo->end) {
-                pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF while parsing inline DTD", CFStringGetSystemEncoding());
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF while parsing inline DTD"));
                 return;
             }
             ch = *(pInfo->curr);
@@ -822,26 +869,26 @@ static void skipInlineDTD(_CFXMLPlistParseInfo *pInfo) {
                         pInfo->curr ++;
                     }
                     if (*(pInfo->curr) != '>') {
-                        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF while parsing inline DTD", CFStringGetSystemEncoding());
+                        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF while parsing inline DTD"));
                         return;
-                 
-   }
+                    }
                     pInfo->curr ++;
                 }
             } else {
-                pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected character %c on line %d while parsing inline DTD"), ch, lineNumber(pInfo));
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d while parsing inline DTD"), ch, lineNumber(pInfo));
                 return;
             }
         } else if (ch == ']') {
             pInfo->curr ++;
             return;
         } else {
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected character %c on line %d while parsing inline DTD"), ch, lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d while parsing inline DTD"), ch, lineNumber(pInfo));
             return;
         }
     }
-    if (!pInfo->errorString)
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF while parsing inline DTD", CFStringGetSystemEncoding());
+    if (!pInfo->error) {
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF while parsing inline DTD"));
+    }
 }
 
 /* A bit wasteful to do everything with unichars (since we know all the characters we're going to see are 7-bit ASCII), but since our data is coming from or going to a CFString, this prevents the extra cost of converting formats. */
@@ -924,19 +971,19 @@ static CFDataRef __CFPLDataDecode(_CFXMLPlistParseInfo *pInfo, Boolean isMutable
 // In the context of a plist, CharData, Reference and CDSect are not legal (they all resolve to strings).  Skipping whitespace, then, the next character should be '<'.  From there, we figure out which of the three remaining cases we have (element, PI, or Comment).
 static CFTypeRef getContentObject(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
     if (isKey) *isKey = false;
-    while (!pInfo->errorString && pInfo->curr < pInfo->end) {
+    while (!pInfo->error && pInfo->curr < pInfo->end) {
         skipWhitespace(pInfo);
         if (pInfo->curr >= pInfo->end) {
-            pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
             return NULL;
         }
         if (*(pInfo->curr) != '<') {
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
             return NULL;
         }
         pInfo->curr ++;
         if (pInfo->curr >= pInfo->end) {
-            pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
             return NULL;
         }
         switch (*(pInfo->curr)) {
@@ -947,14 +994,14 @@ static CFTypeRef getContentObject(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
             case '!':
                 // Could be a comment
                 if (pInfo->curr+2 >= pInfo->end) {
-                    pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+                    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
                     return NULL;
                 }
                 if (*(pInfo->curr+1) == '-' && *(pInfo->curr+2) == '-') {
                     pInfo->curr += 2;
                     skipXMLComment(pInfo);
                 } else {
-                    pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+                    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
                     return NULL;
                 }
                 break;
@@ -981,11 +1028,11 @@ static void _catFromMarkToBuf(const UniChar *mark, const UniChar *buf, CFMutable
 static void parseCDSect_pl(_CFXMLPlistParseInfo *pInfo, CFMutableStringRef string) {
     const UniChar *end, *begin;
     if (pInfo->end - pInfo->curr < CDSECT_TAG_LENGTH) {
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
         return;
     }
     if (!matchString(pInfo->curr, CFXMLPlistTags[CDSECT_IX], CDSECT_TAG_LENGTH)) {
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered improper CDATA opening at line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered improper CDATA opening at line %d"), lineNumber(pInfo));
         return;
     }
     pInfo->curr += CDSECT_TAG_LENGTH;
@@ -1002,7 +1049,7 @@ static void parseCDSect_pl(_CFXMLPlistParseInfo *pInfo, CFMutableStringRef strin
     }
     // Never found the end mark
     pInfo->curr = begin;
-    pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Could not find end of CDATA started on line %d"), lineNumber(pInfo));
+    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Could not find end of CDATA started on line %d"), lineNumber(pInfo));
 }
 
 // Only legal references are {lt, gt, amp, apos, quote, #ddd, #xAAA}
@@ -1012,7 +1059,7 @@ static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableString
     pInfo->curr ++; // move past the '&';
     len = pInfo->end - pInfo->curr; // how many characters we can safely scan
     if (len < 1) {
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
         return;
     }
     switch (*(pInfo->curr)) {
@@ -1022,7 +1069,7 @@ static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableString
                 pInfo->curr += 3;
                 break;
             }
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
             return;
         case 'g': // "gt"
             if (len >= 3 && *(pInfo->curr+1) == 't' && *(pInfo->curr+2) == ';') {
@@ -1030,11 +1077,11 @@ static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableString
                 pInfo->curr += 3;
                 break;
             }
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
             return;
         case 'a': // "apos" or "amp"
             if (len < 4) {   // Not enough characters for either conversion
-                pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
                 return;
             }
             if (*(pInfo->curr+1) == 'm') {
@@ -1052,7 +1099,7 @@ static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableString
                     break;
                 }
             }
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
             return;
         case 'q':  // "quote"
             if (len >= 5 && *(pInfo->curr+1) == 'u' && *(pInfo->curr+2) == 'o' && *(pInfo->curr+3) == 't' && *(pInfo->curr+4) == ';') {
@@ -1060,14 +1107,14 @@ static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableString
                 pInfo->curr += 5;
                 break;
             }
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
             return;
         case '#':
         {
             uint16_t num = 0;
             Boolean isHex = false;
             if ( len < 4) {  // Not enough characters to make it all fit!  Need at least "&#d;"
-                pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
                 return;
             }
             pInfo->curr ++;
@@ -1087,76 +1134,76 @@ static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableString
                 if (ch <= '9' && ch >= '0') {
                     num += (ch - '0');
                 } else if (!isHex) {
-                    pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected character %c at line %d"), ch, lineNumber(pInfo));
+                    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c at line %d"), ch, lineNumber(pInfo));
                     return;
                 } else if (ch >= 'a' && ch <= 'f') {
                     num += 10 + (ch - 'a');
                 } else if (ch >= 'A' && ch <= 'F') {
                     num += 10 + (ch - 'A');
                 } else {
-                    pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected character %c at line %d"), ch, lineNumber(pInfo));
+                    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c at line %d"), ch, lineNumber(pInfo));
                     return;                    
                 }
             }
-            pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
             return;
         }
         default:
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
             return;
     }
     CFStringAppendCharacters(string, &ch, 1);
 }
 
+extern void _CFStrSetDesiredCapacity(CFMutableStringRef str, CFIndex len);
+
 static CFStringRef _uniqueStringForString(_CFXMLPlistParseInfo *pInfo, CFStringRef stringToUnique) {
-    if (!pInfo->stringSet) {
-        pInfo->stringSet = CFSetCreateMutable(pInfo->allocator, 0, &kCFCopyStringSetCallBacks);
-       _CFSetSetCapacity(pInfo->stringSet, 160);       // set capacity high to avoid lots of rehashes, though waste some memory
+    CFStringRef uniqued = (CFStringRef)CFSetGetValue(pInfo->stringSet, stringToUnique);
+    if (!uniqued) {
+        uniqued = (CFStringRef)__CFStringCollectionCopy(pInfo->allocator, stringToUnique);
+        CFSetAddValue(pInfo->stringSet, uniqued);
+        CFRelease(uniqued);
     }
-    CFSetAddValue(pInfo->stringSet, stringToUnique);
-    return (CFStringRef)CFSetGetValue(pInfo->stringSet, stringToUnique);
+    return uniqued;
 }
 
-extern void _CFStrSetDesiredCapacity(CFMutableStringRef str, CFIndex len);
-
 static CFStringRef _uniqueStringForCharacters(_CFXMLPlistParseInfo *pInfo, const UniChar *base, CFIndex length) {
-    CFIndex idx;
-    uint8_t *ascii, buffer[1024];
-    bool isASCII;
-    if (!pInfo->stringSet) {
-        pInfo->stringSet = CFSetCreateMutable(pInfo->allocator, 0, &kCFCopyStringSetCallBacks);
-       _CFSetSetCapacity(pInfo->stringSet, 160);       // set capacity high to avoid lots of rehashes, though waste some memory
-    }
-    if (pInfo->tmpString) {
-       CFStringDelete(pInfo->tmpString, CFRangeMake(0, CFStringGetLength(pInfo->tmpString)));
-    } else {
-        pInfo->tmpString = CFStringCreateMutable(pInfo->allocator, 0);
-       _CFStrSetDesiredCapacity(pInfo->tmpString, 512);
-    }
+    if (0 == length) return CFSTR("");
     // This is to avoid having to promote the buffers of all the strings compared against
     // during the set probe; if a Unicode string is passed in, that's what happens.
-    isASCII = true;
-    for (idx = 0; isASCII && idx < length; idx++) isASCII = isASCII && (base[idx] < 0x80);
-    if (isASCII) {
-       ascii = (length < (CFIndex)sizeof(buffer)) ? buffer : (uint8_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, length + 1, 0);
-       for (idx = 0; idx < length; idx++) ascii[idx] = (uint8_t)base[idx];
-       ascii[length] = '\0';
-       CFStringAppendCString(pInfo->tmpString, (char *)ascii, kCFStringEncodingASCII);
-       if (ascii != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, ascii);
-    } else {
-       CFStringAppendCharacters(pInfo->tmpString, base, length);
+    CFStringRef stringToUnique = NULL;
+    Boolean use_stack = (length < 2048);
+    STACK_BUFFER_DECL(uint8_t, buffer, use_stack ? length + 1 : 1);
+    uint8_t *ascii = use_stack ? buffer : (uint8_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, length + 1, 0);
+    for (CFIndex idx = 0; idx < length; idx++) {
+        UniChar ch = base[idx];
+       if (ch < 0x80) {
+           ascii[idx] = (uint8_t)ch;
+        } else {
+           stringToUnique = CFStringCreateWithCharacters(pInfo->allocator, base, length);
+           break;
+       }
     }
-    CFSetAddValue(pInfo->stringSet, pInfo->tmpString);
-    return (CFStringRef)CFSetGetValue(pInfo->stringSet, pInfo->tmpString);
+    if (!stringToUnique) {
+        ascii[length] = '\0';
+        stringToUnique = CFStringCreateWithBytes(pInfo->allocator, ascii, length, kCFStringEncodingASCII, false);
+    }
+    if (ascii != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, ascii);
+    CFStringRef uniqued = (CFStringRef)CFSetGetValue(pInfo->stringSet, stringToUnique);
+    if (!uniqued) {
+        CFSetAddValue(pInfo->stringSet, stringToUnique);
+       uniqued = stringToUnique;
+    }
+    CFRelease(stringToUnique);
+    return uniqued;
 }
 
-
 // String could be comprised of characters, CDSects, or references to one of the "well-known" entities ('<', '>', '&', ''', '"')
 // returns a retained object in *string.
 static CFStringRef getString(_CFXMLPlistParseInfo *pInfo) {
     const UniChar *mark = pInfo->curr; // At any time in the while loop below, the characters between mark and p have not yet been added to *string
     CFMutableStringRef string = NULL;
-    while (!pInfo->errorString && pInfo->curr < pInfo->end) {
+    while (!pInfo->error && pInfo->curr < pInfo->end) {
         UniChar ch = *(pInfo->curr);
         if (ch == '<') {
            if (pInfo->curr + 1 >= pInfo->end) break;
@@ -1174,7 +1221,7 @@ static CFStringRef getString(_CFXMLPlistParseInfo *pInfo) {
         }
     }
 
-    if (pInfo->errorString) {
+    if (pInfo->error) {
         if (string) CFRelease(string);
         return NULL;
     }
@@ -1201,28 +1248,38 @@ static CFStringRef getString(_CFXMLPlistParseInfo *pInfo) {
 
 static Boolean checkForCloseTag(_CFXMLPlistParseInfo *pInfo, const UniChar *tag, CFIndex tagLen) {
     if (pInfo->end - pInfo->curr < tagLen + 3) {
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+        if (!pInfo->error) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
+        }
         return false;
     }
     if (*(pInfo->curr) != '<' || *(++pInfo->curr) != '/') {
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
+        if (!pInfo->error) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
+        }
         return false;
     }
     pInfo->curr ++;
     if (!matchString(pInfo->curr, tag, tagLen)) {
         CFStringRef str = CFStringCreateWithCharactersNoCopy(pInfo->allocator, tag, tagLen, kCFAllocatorNull);
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Close tag on line %d does not match open tag %@"), lineNumber(pInfo), str);
+        if (!pInfo->error) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Close tag on line %d does not match open tag %@"), lineNumber(pInfo), str);
+        }
         CFRelease(str);
         return false;
     }
     pInfo->curr += tagLen;
     skipWhitespace(pInfo);
     if (pInfo->curr == pInfo->end) {
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+        if (!pInfo->error) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
+        }
         return false;
     }
     if (*(pInfo->curr) != '>') {
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
+        if (!pInfo->error) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
+        }
         return false;
     }
     pInfo->curr ++;
@@ -1235,7 +1292,7 @@ static CFTypeRef parsePListTag(_CFXMLPlistParseInfo *pInfo) {
     const UniChar *save;
     result = getContentObject(pInfo, NULL);
     if (!result) {
-        if (!pInfo->errorString) pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered empty plist tag", CFStringGetSystemEncoding());
+        if (!pInfo->error) pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered empty plist tag"));
         return NULL;
     }
     save = pInfo->curr; // Save this in case the next step fails
@@ -1245,10 +1302,10 @@ static CFTypeRef parsePListTag(_CFXMLPlistParseInfo *pInfo) {
         CFRelease(tmp);
         CFRelease(result);
         pInfo->curr = save;
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unexpected element at line %d (plist can only include one object)"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected element at line %d (plist can only include one object)"), lineNumber(pInfo));
         return NULL;
     }
-    if (pInfo->errorString) {
+    if (pInfo->error) {
         // Parse failed catastrophically
         CFRelease(result);
         return NULL;
@@ -1263,7 +1320,7 @@ static CFTypeRef parsePListTag(_CFXMLPlistParseInfo *pInfo) {
 static int allowImmutableCollections = -1;
 
 static void checkImmutableCollections(void) {
-    allowImmutableCollections = (NULL == getenv("CFPropertyListAllowImmutableCollections")) ? 0 : 1;
+    allowImmutableCollections = (NULL == __CFgetenv("CFPropertyListAllowImmutableCollections")) ? 0 : 1;
 }
 
 static CFTypeRef parseArrayTag(_CFXMLPlistParseInfo *pInfo) {
@@ -1274,7 +1331,7 @@ static CFTypeRef parseArrayTag(_CFXMLPlistParseInfo *pInfo) {
         CFRelease(tmp);
         tmp = getContentObject(pInfo, NULL);
     }
-    if (pInfo->errorString) { // getContentObject encountered a parse error
+    if (pInfo->error) { // getContentObject encountered a parse error
         CFRelease(array);
         return NULL;
     }
@@ -1304,15 +1361,18 @@ static CFTypeRef parseDictTag(_CFXMLPlistParseInfo *pInfo) {
             if (key) CFRelease(key);
             if (dict) CFRelease(dict);
             pInfo->curr = base;
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Found non-key inside <dict> at line %d"), lineNumber(pInfo));
+            if (!pInfo->error) {
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Found non-key inside <dict> at line %d"), lineNumber(pInfo));
+            }
             return NULL;
         }
         value = getContentObject(pInfo, NULL);
         if (!value) {
             if (key) CFRelease(key);
             if (dict) CFRelease(dict);
-            if (!pInfo->errorString)
-                pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Value missing for key inside <dict> at line %d"), lineNumber(pInfo));
+            if (!pInfo->error) {
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Value missing for key inside <dict> at line %d"), lineNumber(pInfo));
+            }
             return NULL;
         }
        if (NULL == dict) {
@@ -1336,7 +1396,6 @@ static CFTypeRef parseDictTag(_CFXMLPlistParseInfo *pInfo) {
            }
        } else {
            CFIndex cnt = CFDictionaryGetCount(dict);
-#if DEPLOYMENT_TARGET_MACOSX
            if (1 == cnt) {
                CFTypeRef val = CFDictionaryGetValue(dict, CFSTR("CF$UID"));
                if (val && CFGetTypeID(val) == numbertype) {
@@ -1348,7 +1407,6 @@ static CFTypeRef parseDictTag(_CFXMLPlistParseInfo *pInfo) {
                    return uid;
                }
            }
-#endif
            if (-1 == allowImmutableCollections) checkImmutableCollections();
            if (1 == allowImmutableCollections) {
                if (pInfo->mutabilityOption == kCFPropertyListImmutable) {
@@ -1370,7 +1428,7 @@ static CFTypeRef parseDataTag(_CFXMLPlistParseInfo *pInfo) {
     result = __CFPLDataDecode(pInfo, pInfo->mutabilityOption == kCFPropertyListMutableContainersAndLeaves);
     if (!result) {
         pInfo->curr = base;
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Could not interpret <data> at line %d (should be base64-encoded)"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Could not interpret <data> at line %d (should be base64-encoded)"), lineNumber(pInfo));
         return NULL;
     }
     if (checkForCloseTag(pInfo, CFXMLPlistTags[DATA_IX], DATA_TAG_LENGTH)) return result;
@@ -1437,7 +1495,7 @@ static CFTypeRef parseDateTag(_CFXMLPlistParseInfo *pInfo) {
     }
 
     if (badForm) {
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Could not interpret <date> at line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Could not interpret <date> at line %d"), lineNumber(pInfo));
         return NULL;
     }
     if (!checkForCloseTag(pInfo, CFXMLPlistTags[DATE_IX], DATE_TAG_LENGTH)) return NULL;
@@ -1447,7 +1505,7 @@ static CFTypeRef parseDateTag(_CFXMLPlistParseInfo *pInfo) {
     CFGregorianDate date = {year, month, day, hour, minute, second};
     at = CFGregorianDateGetAbsoluteTime(date, NULL);
 #else
-    CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFGregorianCalendar);
+    CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFCalendarIdentifierGregorian);
     CFTimeZoneRef tz = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, CFSTR("GMT"), true);
     CFCalendarSetTimeZone(calendar, tz);
     CFCalendarComposeAbsoluteTime(calendar, &at, (const uint8_t *)"yMdHms", year, month, day, hour, minute, second);
@@ -1464,8 +1522,9 @@ static CFTypeRef parseRealTag(_CFXMLPlistParseInfo *pInfo) {
     CFNumberRef result;
     CFStringInlineBuffer buf;
     if (!str) {
-        if (!pInfo->errorString)
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered empty <real> on line %d"), lineNumber(pInfo));
+        if (!pInfo->error) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered empty <real> on line %d"), lineNumber(pInfo));
+        }
         return NULL;
     }
     
@@ -1503,7 +1562,7 @@ static CFTypeRef parseRealTag(_CFXMLPlistParseInfo *pInfo) {
     idx = 0;
     if (!__CFStringScanDouble(&buf, NULL, &idx, &val) || idx != len) {
         CFRelease(str);
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered misformatted real on line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered misformatted real on line %d"), lineNumber(pInfo));
         return NULL;
     }
     CFRelease(str);
@@ -1514,7 +1573,7 @@ static CFTypeRef parseRealTag(_CFXMLPlistParseInfo *pInfo) {
 }
 
 #define GET_CH if (pInfo->curr == pInfo->end) {        \
-                       pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Premature end of file after <integer> on line %d"), lineNumber(pInfo)); \
+                       pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Premature end of file after <integer> on line %d"), lineNumber(pInfo)); \
                        return NULL;                    \
                }                                       \
                ch = *(pInfo->curr)
@@ -1531,15 +1590,15 @@ enum {
 static CFTypeRef parseIntegerTag(_CFXMLPlistParseInfo *pInfo) {
     bool isHex = false, isNeg = false, hadLeadingZero = false;
     UniChar ch = 0;
-
-       // decimal_constant     S*(-|+)?S*[0-9]+                (S == space)
-       // hex_constant         S*(-|+)?S*0[xX][0-9a-fA-F]+     (S == space)
-
+    
+    // decimal_constant         S*(-|+)?S*[0-9]+               (S == space)
+    // hex_constant            S*(-|+)?S*0[xX][0-9a-fA-F]+     (S == space)
+    
     while (pInfo->curr < pInfo->end && __CFIsWhitespace(*(pInfo->curr))) pInfo->curr++;
     GET_CH;
     if ('<' == ch) {
-       pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered empty <integer> on line %d"), lineNumber(pInfo));
-       return NULL;
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered empty <integer> on line %d"), lineNumber(pInfo));
+        return NULL;
     }
     if ('-' == ch || '+' == ch) {
        isNeg = ('-' == ch);
@@ -1571,7 +1630,7 @@ static CFTypeRef parseIntegerTag(_CFXMLPlistParseInfo *pInfo) {
        return CFNumberCreate(pInfo->allocator, kCFNumberSInt32Type, &val);
     }
     if ('<' == ch) {
-       pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Incomplete <integer> on line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Incomplete <integer> on line %d"), lineNumber(pInfo));
        return NULL;
     }
     uint64_t value = 0;
@@ -1579,35 +1638,35 @@ static CFTypeRef parseIntegerTag(_CFXMLPlistParseInfo *pInfo) {
     while ('<' != ch) {
        uint32_t new_digit = 0;
        switch (ch) {
-       case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
-           new_digit = (ch - '0');
-           break;
-       case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-           new_digit = (ch - 'a' + 10);
-           break;
-       case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
-           new_digit = (ch - 'A' + 10);
-           break;
-       default:        // other character
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unknown character '%c' (0x%x) in <integer> on line %d"), ch, ch, lineNumber(pInfo));
-           return NULL;
+            case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+                new_digit = (ch - '0');
+                break;
+            case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+                new_digit = (ch - 'a' + 10);
+                break;
+            case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+                new_digit = (ch - 'A' + 10);
+                break;
+            default:   // other character
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unknown character '%c' (0x%x) in <integer> on line %d"), ch, ch, lineNumber(pInfo));
+                return NULL;
        }
        if (!isHex && new_digit > 9) {
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Hex digit in non-hex <integer> on line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Hex digit in non-hex <integer> on line %d"), lineNumber(pInfo));
            return NULL;
        }
        if (UINT64_MAX / multiplier < value) {
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Integer overflow in <integer> on line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Integer overflow in <integer> on line %d"), lineNumber(pInfo));
            return NULL;
        }
        value = multiplier * value;
        if (UINT64_MAX - new_digit < value) {
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Integer overflow in <integer> on line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Integer overflow in <integer> on line %d"), lineNumber(pInfo));
            return NULL;
        }
        value = value + new_digit;
        if (isNeg && (uint64_t)INT64_MAX + 1 < value) {
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Integer underflow in <integer> on line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Integer underflow in <integer> on line %d"), lineNumber(pInfo));
            return NULL;
        }
        pInfo->curr++;
@@ -1655,7 +1714,7 @@ static CFTypeRef parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
     if (markerLength == 0) {
         // Back up to the beginning of the marker
         pInfo->curr = marker;
-        pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Malformed tag on line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Malformed tag on line %d"), lineNumber(pInfo));
         return NULL;
     }
     switch (*marker) {
@@ -1707,14 +1766,14 @@ static CFTypeRef parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
     }
 
     if (!pInfo->allowNewTypes && markerIx != PLIST_IX && markerIx != ARRAY_IX && markerIx != DICT_IX && markerIx != STRING_IX && markerIx != KEY_IX && markerIx != DATA_IX) {
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered new tag when expecting only old-style property list objects", CFStringGetSystemEncoding());
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered new tag when expecting only old-style property list objects"));
         return NULL;
     }
 
     switch (markerIx) {
         case PLIST_IX:
             if (isEmpty) {
-                pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered empty plist tag", CFStringGetSystemEncoding());
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered empty plist tag"));
                 return NULL;
             }
             return parsePListTag(pInfo);
@@ -1752,14 +1811,14 @@ static CFTypeRef parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
         }
         case DATA_IX:
             if (isEmpty) {
-                pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered empty <data> on line %d"), lineNumber(pInfo));
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered empty <data> on line %d"), lineNumber(pInfo));
                 return NULL;
             } else {
                 return parseDataTag(pInfo);
             }
         case DATE_IX:
             if (isEmpty) {
-                pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered empty <date> on line %d"), lineNumber(pInfo));
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered empty <date> on line %d"), lineNumber(pInfo));
                 return NULL;
             } else {
                 return parseDateTag(pInfo);
@@ -1776,14 +1835,14 @@ static CFTypeRef parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
             return CFRetain(kCFBooleanFalse);
         case REAL_IX:
             if (isEmpty) {
-                pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered empty <real> on line %d"), lineNumber(pInfo));
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered empty <real> on line %d"), lineNumber(pInfo));
                 return NULL;
             } else {
                 return parseRealTag(pInfo);
             }
         case INTEGER_IX:
             if (isEmpty) {
-                pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered empty <integer> on line %d"), lineNumber(pInfo));
+                pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered empty <integer> on line %d"), lineNumber(pInfo));
                 return NULL;
             } else {
                 return parseIntegerTag(pInfo);
@@ -1791,7 +1850,7 @@ static CFTypeRef parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
         default:  {
             CFStringRef markerStr = CFStringCreateWithCharacters(pInfo->allocator, marker, markerLength);
             pInfo->curr = marker;
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Encountered unknown tag %@ on line %d"), markerStr, lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unknown tag %@ on line %d"), markerStr, lineNumber(pInfo));
             CFRelease(markerStr);
             return NULL;
         }
@@ -1799,15 +1858,15 @@ static CFTypeRef parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
 }
 
 static CFTypeRef parseXMLPropertyList(_CFXMLPlistParseInfo *pInfo) {
-    while (!pInfo->errorString && pInfo->curr < pInfo->end) {
+    while (!pInfo->error && pInfo->curr < pInfo->end) {
         UniChar ch;
         skipWhitespace(pInfo);
         if (pInfo->curr+1 >= pInfo->end) {
-            pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "No XML content found", CFStringGetSystemEncoding());
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("No XML content found"));
             return NULL;
         }
         if (*(pInfo->curr) != '<') {
-            pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unexpected character %c at line %d"), *(pInfo->curr), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unexpected character %c at line %d"), *(pInfo->curr), lineNumber(pInfo));
             return NULL;
         }
         ch = *(++ pInfo->curr);
@@ -1832,12 +1891,13 @@ static CFTypeRef parseXMLPropertyList(_CFXMLPlistParseInfo *pInfo) {
         }
     }
     // Should never get here
-    if (!(pInfo->errorString))
-        pInfo->errorString = CFStringCreateWithCString(pInfo->allocator, "Encountered unexpected EOF", CFStringGetSystemEncoding());
+    if (!(pInfo->error)) {
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
+    }
     return NULL;
 }
 
-static CFStringEncoding encodingForXMLData(CFDataRef data, CFStringRef *error) {
+static CFStringEncoding encodingForXMLData(CFDataRef data, CFErrorRef *error) {
     const uint8_t *bytes = (uint8_t *)CFDataGetBytePtr(data);
     UInt32 length = CFDataGetLength(data);
     const uint8_t *idx, *end;
@@ -1889,15 +1949,15 @@ static CFStringEncoding encodingForXMLData(CFDataRef data, CFStringRef *error) {
         }
 
         if (error) {
-            *error = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Encountered unknown encoding (%@)"), encodingName);
+            *error = __CFPropertyListCreateError(kCFAllocatorSystemDefault, kCFPropertyListReadCorruptError, CFSTR("Encountered unknown encoding (%@)"), encodingName);
             CFRelease(encodingName);
         }
         return 0;
     }
 }
 
-extern bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFPropertyListRef *plist, CFStringRef *errorString);
-int32_t _CFPropertyListAllowNonUTF8 = 0;
+bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFPropertyListRef *plist, CFStringRef *errorString);
+unsigned long _CFPropertyListAllowNonUTF8 = 0;
 
 #define SAVE_PLISTS 0
 
@@ -1934,27 +1994,218 @@ static Boolean __savePlistData(CFDataRef data, CFOptionFlags opt) {
 }
 #endif
 
-CFTypeRef _CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags option, CFStringRef *errorString, Boolean allowNewTypes, CFPropertyListFormat *format) {
+
+CFTypeRef _CFPropertyListCreateFromXMLStringError(CFAllocatorRef allocator, CFStringRef xmlString, CFOptionFlags option, CFErrorRef *error, Boolean allowNewTypes, CFPropertyListFormat *format) {
     initStatics();
-    CFStringEncoding encoding;
-    CFStringRef xmlString;
+    
+    CFAssert1(xmlString != NULL, __kCFLogAssertion, "%s(): NULL string not allowed", __PRETTY_FUNCTION__);
+    CFAssert2(option == kCFPropertyListImmutable || option == kCFPropertyListMutableContainers || option == kCFPropertyListMutableContainersAndLeaves, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, option);
+    
     UInt32 length;
-    CFPropertyListRef plist;
+    Boolean createdBuffer = false;
+    length = xmlString ? CFStringGetLength(xmlString) : 0;
+    
+    if (!length) {
+        if (error) {
+            *error = __CFPropertyListCreateError(allocator, kCFPropertyListReadCorruptError, CFSTR("Conversion of string failed. The string is empty."));
+        }
+        return NULL;
+    }
+    
+    _CFXMLPlistParseInfo pInfoBuf;
+    _CFXMLPlistParseInfo *pInfo = &pInfoBuf;
+    CFTypeRef result;
+    
+    // Ensure that xmlString is not collected while we are using it
+    CFRetain(xmlString);
+    UniChar *buf = (UniChar *)CFStringGetCharactersPtr(xmlString);
+    
+    allocator = allocator ? allocator : __CFGetDefaultAllocator();
+    CFRetain(allocator);
+    
+    if (!buf) {
+        buf = (UniChar *)CFAllocatorAllocate(allocator, length * sizeof(UniChar), 0);
+        CFStringGetCharacters(xmlString, CFRangeMake(0, length), buf);
+        createdBuffer = true;
+    }
+    pInfo->begin = buf;
+    pInfo->end = buf+length;
+    pInfo->curr = buf;
+    pInfo->allocator = allocator;
+    pInfo->error = NULL;
+    pInfo->stringSet = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
+    _CFSetSetCapacity(pInfo->stringSet, CFStringGetLength(xmlString) / 250); // avoid lots of rehashes, may waste some memory; simple heuristic
+    pInfo->mutabilityOption = option;
+    pInfo->allowNewTypes = allowNewTypes;
+    
+    result = parseXMLPropertyList(pInfo);
+    if (result && format) *format = kCFPropertyListXMLFormat_v1_0;
+    if (!result) {
+        CFErrorRef xmlParserErr = pInfo->error;
+        // Reset pInfo so we can try again
+        pInfo->curr = pInfo->begin;
+        pInfo->error = NULL;
+        
+        // Try pList
+        result = parseOldStylePropertyListOrStringsFile(pInfo);
+        if (result && format) {
+            *format = kCFPropertyListOpenStepFormat;
+        }
+        
+        if (!result && xmlParserErr && error) {
+            // Add the new error from the old-style property list parser to the user info of the original error
+            CFDictionaryRef xmlUserInfo = CFErrorCopyUserInfo(xmlParserErr);
+            CFMutableDictionaryRef userInfo = CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault, CFDictionaryGetCount(xmlUserInfo) + 1, xmlUserInfo);
+            CFDictionaryAddValue(userInfo, CFPropertyListOldStyleParserErrorKey, pInfo->error);
+            
+            // Re-create the xml parser error with this new user info dictionary
+            CFErrorRef newError = CFErrorCreate(kCFAllocatorSystemDefault, CFErrorGetDomain(xmlParserErr), CFErrorGetCode(xmlParserErr), userInfo);
+            
+            CFRelease(xmlUserInfo);
+            CFRelease(userInfo);
+                        
+            // It is the responsibility of the caller to release this newly created error
+            *error = newError;
+        }
+        
+        if (xmlParserErr) {
+            CFRelease(xmlParserErr);
+        }
+    }
+    
+    if (createdBuffer) {
+        CFAllocatorDeallocate(allocator, (void *)pInfo->begin);
+    }
+    if (pInfo->stringSet) CFRelease(pInfo->stringSet);
+    if (pInfo->error) CFRelease(pInfo->error);
+    CFRelease(allocator);
+    CFRelease(xmlString);
+    return result;
+}
 
+CFTypeRef _CFPropertyListCreateFromXMLString(CFAllocatorRef allocator, CFStringRef xmlString, CFOptionFlags option, CFStringRef *errorString, Boolean allowNewTypes, CFPropertyListFormat *format) {
+    initStatics();
     if (errorString) *errorString = NULL;
-    if (!xmlData || CFDataGetLength(xmlData) == 0) {
-        if (errorString) {
-            *errorString = CFSTR("Cannot parse a NULL or zero-length data");
-            CFRetain(*errorString); // Caller expects to release
+    CFErrorRef error = NULL;
+    CFTypeRef result = _CFPropertyListCreateFromXMLStringError(allocator, xmlString, option, &error, allowNewTypes, format);
+
+    if (errorString && error) {
+        // The caller is interested in receiving an error message. Pull the debug string out of the CFError returned above
+        CFDictionaryRef userInfo = CFErrorCopyUserInfo(error);
+        CFStringRef debugString = NULL;
+        
+        // Handle a special-case for compatibility - if the XML parse failed and the old-style plist parse failed, construct a special string
+        CFErrorRef underlyingError = NULL;
+
+        Boolean oldStyleFailed = CFDictionaryGetValueIfPresent(userInfo, CFPropertyListOldStyleParserErrorKey, (const void **)&underlyingError);
+        
+        if (oldStyleFailed) {
+            CFStringRef xmlParserErrorString, oldStyleParserErrorString;
+            xmlParserErrorString = (CFStringRef)CFDictionaryGetValue(userInfo, kCFErrorDebugDescriptionKey);
+            
+            CFDictionaryRef oldStyleParserUserInfo = CFErrorCopyUserInfo(underlyingError);
+            oldStyleParserErrorString = (CFStringRef)CFDictionaryGetValue(userInfo, kCFErrorDebugDescriptionKey);
+            
+            // Combine the two strings into a single one that matches the previous implementation
+            debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("XML parser error:\n\t%@\nOld-style plist parser error:\n\t%@\n"), xmlParserErrorString, oldStyleParserErrorString);
+            
+            CFRelease(oldStyleParserUserInfo);
+        } else {
+            debugString = (CFStringRef)CFDictionaryGetValue(userInfo, kCFErrorDebugDescriptionKey); 
+            CFRetain(debugString);
         }
-        return NULL;
+        
+        // Give the debugString to the caller, who is responsible for releasing it
+        CFRelease(userInfo);
+        *errorString = debugString;
+    }
+    
+    if (error) {
+        CFRelease(error);
     }
+    
+    return result;
+}
+
+
+/* Get a single value for a given key in a top-level dictionary in a property list.
+ @param allocator The allocator to use.
+ @param data The property list data.
+ @param option Currently unused, set to 0.
+ @param key The key to search for in the top-level dictionary. If the top-level data structure is not a dictionary, the return value will be false.
+ @param value If the key is found and the parameter is non-NULL, this will be set to a reference to the value. It is the caller's responsibility to release the object. If no object is found, will be set to NULL. If this parameter is NULL, this function can be used to check for the existence of a key without creating it by just checking the return value.
+ @param error If an error occurs, will be set to a valid CFErrorRef. It is the caller's responsibility to release this value.
+ @return True if the key is found, false otherwise.
+ */
+bool _CFPropertyListCreateSingleValue(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFStringRef key, CFPropertyListRef *value, CFErrorRef *error) {
+    
+    initStatics();
+    
+    uint8_t marker;    
+    CFBinaryPlistTrailer trailer;
+    uint64_t offset;
+    const uint8_t *databytes = CFDataGetBytePtr(data);
+    uint64_t datalen = CFDataGetLength(data);
+    bool result = false;
+    
+    // First check to see if it is a binary property list
+    if (8 <= datalen && __CFBinaryPlistGetTopLevelInfo(databytes, datalen, &marker, &offset, &trailer)) {
+       // Create a dictionary to cache objects in
+        CFMutableDictionaryRef objects = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
+        _CFDictionarySetCapacity(objects, 1);
+       
+       // Look for the value in the top-level dictionary
+       uint64_t keyOffset, valueOffset;
+       result = __CFBinaryPlistGetOffsetForValueFromDictionary3(databytes, datalen, offset, &trailer, (CFTypeRef)key, &keyOffset, &valueOffset, false, objects);
+       
+       // value could be null if the caller wanted to check for the existence of a key but not bother creating it
+       if (result && value) {
+           CFPropertyListRef pl;
+           result = __CFBinaryPlistCreateObject2(databytes, datalen, valueOffset, &trailer, allocator, option, objects, NULL, 0, &pl);
+           if (result) {
+               // caller's responsibility to release the created object
+               *value = pl;
+           }
+       }
+       
+       CFRelease(objects);
+    } else {
+       // Try an XML property list
+       // Note: This is currently not any more efficient than grabbing the whole thing. This could be improved in the future.
+       CFPropertyListRef plist = CFPropertyListCreateWithData(allocator, data, option, NULL, error);
+       if (!(*error) && plist && CFGetTypeID((CFTypeRef)plist) == dicttype) {
+           CFPropertyListRef pl = (CFPropertyListRef)CFDictionaryGetValue((CFDictionaryRef)plist, key);
+           if (pl) {
+               *value = pl;
+               // caller's responsibility to release the created object
+               CFRetain(*value);
+               result = true;
+           }
+       }
+       if (plist) CFRelease(plist);
+    }
+    
+    return result;
+}
 
+CFTypeRef _CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFErrorRef *error, Boolean allowNewTypes, CFPropertyListFormat *format) {
+    initStatics();
+    CFStringEncoding encoding;
+    CFPropertyListRef plist;
+    
+    if (!data || CFDataGetLength(data) == 0) {
+        if (error) {
+            *error = __CFPropertyListCreateError(allocator, kCFPropertyListReadCorruptError, CFSTR("Cannot parse a NULL or zero-length data"));
+        }
+        return NULL;
+    }
+    
 #if SAVE_PLISTS
-    __savePlistData(xmlData, option);
+    __savePlistData(data, option);
 #endif
-
-    if (__CFTryParseBinaryPlist(allocator, xmlData, option, &plist, errorString)) {
+    
+    // Ignore the error from CFTryParseBinaryPlist -- if it doesn't work, we're going to try again anyway using the XML parser
+    if (__CFTryParseBinaryPlist(allocator, data, option, &plist, NULL)) {
        if (format) *format = kCFPropertyListBinaryFormat_v1_0;
        return plist;
     }
@@ -1962,122 +2213,156 @@ CFTypeRef _CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef x
     allocator = allocator ? allocator : __CFGetDefaultAllocator();
     CFRetain(allocator);
     
-    encoding = encodingForXMLData(xmlData, errorString); // 0 is an error return, NOT MacRoman.
-
+    // Use our own error variable here so we can check it against NULL later
+    CFErrorRef subError = NULL;
+    encoding = encodingForXMLData(data, &subError); // 0 is an error return, NOT MacRoman.
+    
     if (encoding == 0) {
-        // Couldn't find an encoding; encodingForXMLData already set *errorString if necessary
+        // Couldn't find an encoding
         // Note that encodingForXMLData() will give us the right values for a standard plist, too.
-        if (errorString) *errorString = CFStringCreateWithFormat(allocator, NULL, CFSTR("Could not determine the encoding of the XML data"));
+        if (error && subError == NULL) {
+           // encodingForXMLData didn't set an error, so we create a new one here
+            *error = __CFPropertyListCreateError(allocator, kCFPropertyListReadCorruptError, CFSTR("Could not determine the encoding of the XML data"));
+        } else if (error && subError) {
+           // give the caller the subError, they will release
+           *error = subError;
+       }
         return NULL;
     }
-
-    xmlString = CFStringCreateWithBytes(allocator, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData), encoding, true);
+    
+    CFStringRef xmlString = CFStringCreateWithBytes(allocator, CFDataGetBytePtr(data), CFDataGetLength(data), encoding, true);
     if (NULL == xmlString && (!_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard) || _CFPropertyListAllowNonUTF8)) { // conversion failed, probably because not in proper encoding
         // Call __CFStringCreateImmutableFunnel3() the same way CFStringCreateWithBytes() does, except with the addt'l flag
-               if (encoding == kCFStringEncodingUTF8) xmlString = __CFStringCreateImmutableFunnel3(allocator, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData), kCFStringEncodingUTF8, true, true, false, false, false, (CFAllocatorRef)-1  /* ALLOCATORSFREEFUNC */, kCFStringEncodingLenientUTF8Conversion);
+        if (encoding == kCFStringEncodingUTF8) xmlString = __CFStringCreateImmutableFunnel3(allocator, CFDataGetBytePtr(data), CFDataGetLength(data), kCFStringEncodingUTF8, true, true, false, false, false, (CFAllocatorRef)-1  /* ALLOCATORSFREEFUNC */, kCFStringEncodingLenientUTF8Conversion);
     }
-    length = xmlString ? CFStringGetLength(xmlString) : 0;
+    
+    // Haven't done anything XML-specific to this point.  However, the encoding we used to translate the bytes should be kept in mind; we used Unicode if the byte-order mark was present; UTF-8 otherwise.  If the system encoding is not UTF-8 or some variant of 7-bit ASCII, we'll be in trouble.....
+    plist = _CFPropertyListCreateFromXMLStringError(allocator, xmlString, option, error, allowNewTypes, format);
+    
+    if (xmlString) {
+        CFRelease(xmlString);
+        xmlString = NULL;
+    }
+    
+    return plist;
+}
 
-    if (length) {
-        _CFXMLPlistParseInfo pInfoBuf;
-        _CFXMLPlistParseInfo *pInfo = &pInfoBuf;
-        CFTypeRef result;
-        UniChar *buf = (UniChar *)CFStringGetCharactersPtr(xmlString);
-
-        if (errorString) *errorString = NULL;
-        if (!buf) {
-            buf = (UniChar *)CFAllocatorAllocate(allocator, length * sizeof(UniChar), 0);
-            CFStringGetCharacters(xmlString, CFRangeMake(0, length), buf);
-            CFRelease(xmlString);
-            xmlString = NULL;
-        }
-        pInfo->begin = buf;
-        pInfo->end = buf+length;
-        pInfo->curr = buf;
-        pInfo->allocator = allocator;
-        pInfo->errorString = NULL;
-        pInfo->stringSet = NULL;
-        pInfo->tmpString = NULL;
-        pInfo->mutabilityOption = option;
-        pInfo->allowNewTypes = allowNewTypes;
-        
-        // Haven't done anything XML-specific to this point.  However, the encoding we used to translate the bytes should be kept in mind; we used Unicode if the byte-order mark was present; UTF-8 otherwise.  If the system encoding is not UTF-8 or some variant of 7-bit ASCII, we'll be in trouble.....
-        result = parseXMLPropertyList(pInfo);
-        if (result && format) *format = kCFPropertyListXMLFormat_v1_0;
-        if (!result) {
-           CFStringRef err = pInfo->errorString;
-            // Reset pInfo so we can try again
-            pInfo->curr = pInfo->begin;
-            pInfo->errorString = NULL;
-            // Try pList
-            result = parseOldStylePropertyListOrStringsFile(pInfo);
-           if (result && format) *format = kCFPropertyListOpenStepFormat;
-            if (!result) {
-               if (errorString) *errorString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("XML parser error:\n\t%@\nOld-style plist parser error:\n\t%@\n"), err, pInfo->errorString);
-            }
-           if (err) CFRelease(err);
-           if (pInfo->errorString) CFRelease(pInfo->errorString);
-        }
-        if (xmlString) {
-            CFRelease(xmlString);
-        } else {
-            CFAllocatorDeallocate(allocator, (void *)pInfo->begin);
-        }
-        if (pInfo->stringSet) CFRelease(pInfo->stringSet);
-        if (pInfo->tmpString) CFRelease(pInfo->tmpString);
-        CFRelease(allocator);
-        return result;
-    } else {
-        if (errorString)
-            *errorString = (CFStringRef)CFRetain(CFSTR("Conversion of data failed. The file is not UTF-8, or in the encoding specified in XML header if XML."));
-        return NULL;
+
+CFTypeRef _CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags option, CFStringRef *errorString, Boolean allowNewTypes, CFPropertyListFormat *format) {
+    initStatics();
+    CFTypeRef result;
+    if (errorString) *errorString = NULL;
+    CFErrorRef error = NULL;
+    result = _CFPropertyListCreateWithData(allocator, xmlData, option, &error, allowNewTypes, format);
+    if (error && errorString) {
+        *errorString = __CFPropertyListCopyErrorDebugDescription(error);
     }
+    if (error) CFRelease(error);
+    return result;
 }
 
-CFTypeRef CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags option, CFStringRef *errorString) {
+CFPropertyListRef CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags options, CFPropertyListFormat *format, CFErrorRef *error) {
     initStatics();
-    CFAssert1(xmlData != NULL, __kCFLogAssertion, "%s(): NULL data not allowed", __PRETTY_FUNCTION__);
-    CFAssert2(option == kCFPropertyListImmutable || option == kCFPropertyListMutableContainers || option == kCFPropertyListMutableContainersAndLeaves, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, option);
-    return _CFPropertyListCreateFromXMLData(allocator, xmlData, option, errorString, true, NULL);
+    CFAssert1(data != NULL, __kCFLogAssertion, "%s(): NULL data not allowed", __PRETTY_FUNCTION__);
+    CFAssert2(options == kCFPropertyListImmutable || options == kCFPropertyListMutableContainers || options == kCFPropertyListMutableContainersAndLeaves, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, options);
+    return _CFPropertyListCreateWithData(allocator, data, options, error, true, format);
 }
 
-CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStreamRef stream, CFPropertyListFormat format, CFStringRef *errorString) {
+CFPropertyListRef CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags option, CFStringRef *errorString) {
+    initStatics();
+    if (errorString) *errorString = NULL;
+    CFErrorRef error = NULL;
+    CFPropertyListRef result = CFPropertyListCreateWithData(allocator, xmlData, option, NULL, &error);
+    if (error && errorString) {
+        *errorString = __CFPropertyListCopyErrorDebugDescription(error);
+    }
+    if (error) CFRelease(error);
+    return result;
+}
+
+CFDataRef CFPropertyListCreateData(CFAllocatorRef allocator, CFPropertyListRef propertyList, CFPropertyListFormat format, CFOptionFlags options, CFErrorRef *error) {
+    initStatics();
+    CFAssert1(format != kCFPropertyListOpenStepFormat, __kCFLogAssertion, "%s(): kCFPropertyListOpenStepFormat not supported for writing", __PRETTY_FUNCTION__);
+    CFAssert2(format == kCFPropertyListXMLFormat_v1_0 || format == kCFPropertyListBinaryFormat_v1_0, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, format);
+    CFAssert1(propertyList != NULL, __kCFLogAssertion, "%s(): Cannot be called with a NULL property list", __PRETTY_FUNCTION__);
+    __CFAssertIsPList(propertyList);
+    
+    CFDataRef data = NULL;
+    
+    
+    allocator = allocator ? allocator : __CFGetDefaultAllocator();
+    CFRetain(allocator);
+    
+    if (!CFPropertyListIsValid(propertyList, format)) {
+        CFLog(kCFLogLevelError, CFSTR("Property list invalid for format: %d"), format);
+        CFRelease(allocator);
+        return NULL;
+    }
+    
+    if (format == kCFPropertyListOpenStepFormat) {
+        CFLog(kCFLogLevelError, CFSTR("Property list format kCFPropertyListOpenStepFormat not supported for writing"));
+        CFRelease(allocator);
+        return NULL;
+    } else if (format == kCFPropertyListXMLFormat_v1_0) {
+        data = _CFPropertyListCreateXMLData(kCFAllocatorSystemDefault, propertyList, true);
+    } else if (format == kCFPropertyListBinaryFormat_v1_0) {
+        CFWriteStreamRef stream = CFWriteStreamCreateWithAllocatedBuffers(allocator, allocator);
+        CFWriteStreamOpen(stream);
+        CFIndex len = CFPropertyListWrite(propertyList, stream, format, options, error);
+        if (0 < len) {
+            data = (CFDataRef)CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten);
+        }
+        CFWriteStreamClose(stream);
+       CFRelease(stream);
+    } else {
+       CFLog(kCFLogLevelError, CFSTR("Unknown format option"));
+    }
+    
+    CFRelease(allocator);
+    return data;
+}
+
+CFIndex CFPropertyListWrite(CFPropertyListRef propertyList, CFWriteStreamRef stream, CFPropertyListFormat format, CFOptionFlags options, CFErrorRef *error) {
     initStatics();
     CFAssert1(stream != NULL, __kCFLogAssertion, "%s(): NULL stream not allowed", __PRETTY_FUNCTION__);
-    CFAssert2(format == kCFPropertyListOpenStepFormat || format == kCFPropertyListXMLFormat_v1_0 || format == kCFPropertyListBinaryFormat_v1_0, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, format);
+    CFAssert1(format != kCFPropertyListOpenStepFormat, __kCFLogAssertion, "%s(): kCFPropertyListOpenStepFormat not supported for writing", __PRETTY_FUNCTION__);
+    CFAssert2(format == kCFPropertyListXMLFormat_v1_0 || format == kCFPropertyListBinaryFormat_v1_0, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, format);
     CFAssert1(propertyList != NULL, __kCFLogAssertion, "%s(): Cannot be called with a NULL property list", __PRETTY_FUNCTION__);
     __CFAssertIsPList(propertyList);
     CFAssert1(CFWriteStreamGetTypeID() == CFGetTypeID(stream), __kCFLogAssertion, "%s(): stream argument is not a write stream", __PRETTY_FUNCTION__);
     CFAssert1(kCFStreamStatusOpen == CFWriteStreamGetStatus(stream) || kCFStreamStatusWriting == CFWriteStreamGetStatus(stream), __kCFLogAssertion, "%s():  stream is not open", __PRETTY_FUNCTION__);
-
-    if (errorString) *errorString = NULL;
+    
     if (!CFPropertyListIsValid(propertyList, format)) {
-        if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("Property list invalid for format"));
+        CFLog(kCFLogLevelError, CFSTR("Property list invalid for format: %d"), format);
         return 0;
     }
     if (format == kCFPropertyListOpenStepFormat) {
-        if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("Property list format kCFPropertyListOpenStepFormat not supported for writing"));
+        CFLog(kCFLogLevelError, CFSTR("Property list format kCFPropertyListOpenStepFormat not supported for writing"));
         return 0;
     }
     if (format == kCFPropertyListXMLFormat_v1_0) {
-        CFDataRef data = CFPropertyListCreateXMLData(kCFAllocatorSystemDefault, propertyList);
-       if (!data) {
-           if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("Property list in XML format could not be created for unknown reasons."));
-           return 0;
-       }
+        CFDataRef data = _CFPropertyListCreateXMLData(kCFAllocatorSystemDefault, propertyList, true);
         CFIndex len = CFDataGetLength(data);
        const uint8_t *ptr = CFDataGetBytePtr(data);
        while (0 < len) {
            CFIndex ret = CFWriteStreamWrite(stream, ptr, len);
            if (ret == 0) {
-               if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("Property list writing could not be completed because stream is full."));
+                if (error) *error = __CFPropertyListCreateError(kCFAllocatorSystemDefault, kCFPropertyListWriteStreamError, CFSTR("Property list writing could not be completed because stream is full."));
                return 0;
            }
            if (ret < 0) {
-               CFErrorRef err = CFWriteStreamCopyError(stream);
-               CFStringRef str = err ? CFErrorCopyDescription(err) : NULL;
-               if (errorString) *errorString = str ? str : (CFStringRef)CFRetain(CFSTR("Property list writing could not be completed because the stream had an unknown error."));
-               if (err) CFRelease(err);
+               CFErrorRef underlyingError = CFWriteStreamCopyError(stream);
+                if (underlyingError) {
+                    if (error) {
+                        // Wrap the error from CFWriteStreamCopy in a new error
+                        CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 
+                        CFDictionarySetValue(userInfo, kCFErrorDebugDescriptionKey, CFSTR("Property list writing could not be completed because the stream had an unknown error."));
+                        CFDictionarySetValue(userInfo, kCFErrorUnderlyingErrorKey, underlyingError);
+                        *error = CFErrorCreate(kCFAllocatorSystemDefault, kCFErrorDomainCocoa, kCFPropertyListWriteStreamError, userInfo);
+                        CFRelease(userInfo);
+                    }
+                    CFRelease(underlyingError);
+                }
                return 0;
            }
            ptr += ret;
@@ -2088,21 +2373,54 @@ CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStrea
         return len;
     }
     if (format == kCFPropertyListBinaryFormat_v1_0) {
-       CFIndex len = __CFBinaryPlistWriteToStream(propertyList, stream);
+        CFIndex len = __CFBinaryPlistWrite(propertyList, stream, 0, options, error);
         return len;
     }
-    if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("Unknown format option"));
+    CFLog(kCFLogLevelError, CFSTR("Unknown format option"));
     return 0;
 }
 
-static void __CFConvertReadStreamToBytes(CFReadStreamRef stream, CFIndex max, uint8_t **buffer, CFIndex *length) {
+CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStreamRef stream, CFPropertyListFormat format, CFStringRef *errorString) {
+    initStatics();
+    if (errorString) *errorString = NULL;
+    CFErrorRef error = NULL;
+    
+    // For backwards compatibility, we check the format parameter up front since these do not have CFError counterparts in the newer API
+    if (!CFPropertyListIsValid(propertyList, format)) {
+        if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("Property list invalid for format"));
+        return 0;
+    }
+    if (format == kCFPropertyListOpenStepFormat) {
+        if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("Property list format kCFPropertyListOpenStepFormat not supported for writing"));
+        return 0;
+    }
+    if (format != kCFPropertyListBinaryFormat_v1_0 && format != kCFPropertyListXMLFormat_v1_0) {
+        if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("Unknown format option"));
+        return 0;
+    }
+    
+    CFIndex result = CFPropertyListWrite(propertyList, stream, format, 0, &error);
+    if (error && errorString) {
+        *errorString = __CFPropertyListCopyErrorDebugDescription(error);
+    }
+    if (error) CFRelease(error);
+    return result;    
+}
+
+static void __CFConvertReadStreamToBytes(CFReadStreamRef stream, CFIndex max, uint8_t **buffer, CFIndex *length, CFErrorRef *error) {
     int32_t buflen = 0, bufsize = 0, retlen;
     uint8_t *buf = NULL, sbuf[8192];
     for (;;) {
        retlen = CFReadStreamRead(stream, sbuf, __CFMin(8192, max));
-       if (retlen <= 0) {
-           *buffer = buf;
-           *length = buflen;
+        if (retlen <= 0) {
+            *buffer = buf;
+            *length = buflen;
+            
+            if (retlen < 0 && error) {
+                // Copy the error out
+                *error = CFReadStreamCopyError(stream);
+            }
+            
            return;
        }
         if (bufsize < buflen + retlen) {
@@ -2130,7 +2448,7 @@ static void __CFConvertReadStreamToBytes(CFReadStreamRef stream, CFIndex max, ui
     }
 }
 
-CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex length, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFStringRef *errorString) {
+CFPropertyListRef CFPropertyListCreateWithStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFErrorRef *error) {
     initStatics();
     CFPropertyListRef pl;
     CFDataRef data;
@@ -2140,21 +2458,46 @@ CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFRea
     CFAssert1(CFReadStreamGetTypeID() == CFGetTypeID(stream), __kCFLogAssertion, "%s(): stream argument is not a read stream", __PRETTY_FUNCTION__);
     CFAssert1(kCFStreamStatusOpen == CFReadStreamGetStatus(stream) || kCFStreamStatusReading == CFReadStreamGetStatus(stream), __kCFLogAssertion, "%s():  stream is not open", __PRETTY_FUNCTION__);
     CFAssert2(mutabilityOption == kCFPropertyListImmutable || mutabilityOption == kCFPropertyListMutableContainers || mutabilityOption == kCFPropertyListMutableContainersAndLeaves, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, mutabilityOption);
-
-    if (errorString) *errorString = NULL;
-    if (0 == length) length = INT_MAX;
-    __CFConvertReadStreamToBytes(stream, length, &buffer, &buflen);
+    
+    if (0 == streamLength) streamLength = INT_MAX;
+    CFErrorRef underlyingError = NULL;
+    __CFConvertReadStreamToBytes(stream, streamLength, &buffer, &buflen, &underlyingError);
+    if (underlyingError) {
+        if (error) {
+            // Wrap the error from CFReadStream in a new error in the cocoa domain
+            CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 
+            CFDictionarySetValue(userInfo, kCFErrorDebugDescriptionKey, CFSTR("Property list reading could not be completed because the stream had an unknown error."));
+            CFDictionarySetValue(userInfo, kCFErrorUnderlyingErrorKey, underlyingError);
+            *error = CFErrorCreate(kCFAllocatorSystemDefault, kCFErrorDomainCocoa, kCFPropertyListReadStreamError, userInfo);
+            CFRelease(userInfo);
+        }
+        CFRelease(underlyingError);
+        return NULL;
+    }
+    
     if (!buffer || buflen < 6) {
         if (buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, buffer);
-        if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("stream had too few bytes"));
+        if (error) *error = __CFPropertyListCreateError(allocator, kCFPropertyListReadCorruptError, CFSTR("stream had too few bytes"));
         return NULL;
     }
     data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, buffer, buflen, kCFAllocatorSystemDefault);
-    pl = _CFPropertyListCreateFromXMLData(allocator, data, mutabilityOption, errorString, true, format);
+    pl = _CFPropertyListCreateWithData(allocator, data, mutabilityOption, error, true, format);
     CFRelease(data);
     return pl;
 }
 
+CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex length, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFStringRef *errorString) {
+    initStatics();
+    if (errorString) *errorString = NULL;
+    CFErrorRef error = NULL;
+    CFPropertyListRef result = CFPropertyListCreateWithStream(allocator, stream, length, mutabilityOption, format, &error);
+    if (error && errorString) {
+        *errorString = __CFPropertyListCopyErrorDebugDescription(error);
+    }
+    if (error) CFRelease(error);
+    return result;
+}
+
 // ========================================================================
 
 //
@@ -2165,7 +2508,8 @@ static CFTypeRef parsePlistObject(_CFXMLPlistParseInfo *pInfo, bool requireObjec
 
 #define isValidUnquotedStringCharacter(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || ((x) >= '0' && (x) <= '9') || (x) == '_' || (x) == '$' || (x) == '/' || (x) == ':' || (x) == '.' || (x) == '-')
 
-static void advanceToNonSpace(_CFXMLPlistParseInfo *pInfo) {
+// Returns true if the advance found something before the end of the buffer, false otherwise
+static Boolean advanceToNonSpace(_CFXMLPlistParseInfo *pInfo) {
     UniChar ch2;
     while (pInfo->curr < pInfo->end) {
        ch2 = *(pInfo->curr);
@@ -2176,7 +2520,7 @@ static void advanceToNonSpace(_CFXMLPlistParseInfo *pInfo) {
             if (pInfo->curr >= pInfo->end) {
                 // whoops; back up and return
                 pInfo->curr --;
-                return;
+                return true;
             } else if (*(pInfo->curr) == '/') {
                 pInfo->curr ++;
                 while (pInfo->curr < pInfo->end) {     // go to end of comment line
@@ -2196,13 +2540,14 @@ static void advanceToNonSpace(_CFXMLPlistParseInfo *pInfo) {
                 }
             } else {
                 pInfo->curr --;
-                return;
+                return true;
            }
         } else {
             pInfo->curr --;
-            return;
+            return true;
         }
     }
+    return false;
 }
 
 static UniChar getSlashedChar(_CFXMLPlistParseInfo *pInfo) {
@@ -2275,8 +2620,8 @@ static CFStringRef parseQuotedPlistString(_CFXMLPlistParseInfo *pInfo, UniChar q
     }
     if (pInfo->end <= pInfo->curr) {
         if (str) CFRelease(str);
-           pInfo->curr = startMark;
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unterminated quoted string starting on line %d"), lineNumber(pInfo));
+        pInfo->curr = startMark;
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unterminated quoted string starting on line %d"), lineNumber(pInfo));
         return NULL;
     }
     if (!str) {
@@ -2298,9 +2643,9 @@ static CFStringRef parseQuotedPlistString(_CFXMLPlistParseInfo *pInfo, UniChar q
         }
     }
     pInfo->curr ++;  // Advance past the quote character before returning.
-    if (pInfo->errorString) {
-       CFRelease(pInfo->errorString);
-       pInfo->errorString = NULL;
+    if (pInfo->error) {
+        CFRelease(pInfo->error);
+        pInfo->error = NULL;
     }
     return str;
 }
@@ -2324,17 +2669,17 @@ static CFStringRef parseUnquotedPlistString(_CFXMLPlistParseInfo *pInfo) {
             return str;
         }
     }
-       pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unexpected EOF"));
+    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF"));
     return NULL;
 }
 
 static CFStringRef parsePlistString(_CFXMLPlistParseInfo *pInfo, bool requireObject) {
     UniChar ch;
-    advanceToNonSpace(pInfo);
-    if (pInfo->curr >= pInfo->end) {
-       if (requireObject) {
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unexpected EOF while parsing string"));
-       }
+    Boolean foundChar = advanceToNonSpace(pInfo);
+    if (!foundChar) {
+        if (requireObject) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF while parsing string"));
+        }
         return NULL;
     }
     ch = *(pInfo->curr);
@@ -2344,8 +2689,8 @@ static CFStringRef parsePlistString(_CFXMLPlistParseInfo *pInfo, bool requireObj
     } else if (isValidUnquotedStringCharacter(ch)) {
         return parseUnquotedPlistString(pInfo);
     } else {
-       if (requireObject) {
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Invalid string character at line %d"), lineNumber(pInfo));
+        if (requireObject) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Invalid string character at line %d"), lineNumber(pInfo));
        }
         return NULL;
     }
@@ -2354,10 +2699,16 @@ static CFStringRef parsePlistString(_CFXMLPlistParseInfo *pInfo, bool requireObj
 static CFTypeRef parsePlistArray(_CFXMLPlistParseInfo *pInfo) {
     CFMutableArrayRef array = CFArrayCreateMutable(pInfo->allocator, 0, &kCFTypeArrayCallBacks);
     CFTypeRef tmp = parsePlistObject(pInfo, false);
+    Boolean foundChar;
     while (tmp) {
         CFArrayAppendValue(array, tmp);
         CFRelease(tmp);
-        advanceToNonSpace(pInfo);
+        foundChar = advanceToNonSpace(pInfo);
+       if (!foundChar) {
+           CFRelease(array);
+           pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Expected ',' for array at line %d"), lineNumber(pInfo));
+           return NULL;
+       }
         if (*pInfo->curr != ',') {
             tmp = NULL;
         } else {
@@ -2365,15 +2716,15 @@ static CFTypeRef parsePlistArray(_CFXMLPlistParseInfo *pInfo) {
             tmp = parsePlistObject(pInfo, false);
         }
     }
-    advanceToNonSpace(pInfo);
-    if (*pInfo->curr != ')') {
+    foundChar = advanceToNonSpace(pInfo);
+    if (!foundChar || *pInfo->curr != ')') {
         CFRelease(array);
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Expected terminating ')' for array at line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Expected terminating ')' for array at line %d"), lineNumber(pInfo));
         return NULL;
     }
-    if (pInfo->errorString) {
-       CFRelease(pInfo->errorString);
-       pInfo->errorString = NULL;
+    if (pInfo->error) {
+        CFRelease(pInfo->error);
+        pInfo->error = NULL;
     }
     pInfo->curr ++;
     return array;
@@ -2386,7 +2737,14 @@ static CFDictionaryRef parsePlistDictContent(_CFXMLPlistParseInfo *pInfo) {
     key = parsePlistString(pInfo, false);
     while (key) {
         CFTypeRef value;
-        advanceToNonSpace(pInfo);
+        Boolean foundChar = advanceToNonSpace(pInfo);
+        if (!foundChar) {
+            CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListCreateFromXMLData(): Unexpected end of file. Missing semicolon or value in dictionary."));
+            failedParse = true;
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Missing ';' on line %d"), lineNumber(pInfo));
+            break;
+        }
+       
        if (*pInfo->curr == ';') {
            /* This is a strings file using the shortcut format */
            /* although this check here really applies to all plists. */
@@ -2399,7 +2757,7 @@ static CFDictionaryRef parsePlistDictContent(_CFXMLPlistParseInfo *pInfo) {
                break;
            }
        } else {
-               pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unexpected ';' or '=' after key at line %d"), lineNumber(pInfo));
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unexpected ';' or '=' after key at line %d"), lineNumber(pInfo));
            failedParse = true;
            break;
        }
@@ -2408,14 +2766,14 @@ static CFDictionaryRef parsePlistDictContent(_CFXMLPlistParseInfo *pInfo) {
        key = NULL;
        CFRelease(value);
        value = NULL;
-       advanceToNonSpace(pInfo);
-       if (*pInfo->curr == ';') {
+       foundChar = advanceToNonSpace(pInfo);
+       if (foundChar && *pInfo->curr == ';') {
            pInfo->curr ++;
            key = parsePlistString(pInfo, false);
-       } else if (!allowMissingSemi && _CFExecutableLinkedOnOrAfter(CFSystemVersionJaguar)) {
-               CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary."));
+       } else if ((!allowMissingSemi && _CFExecutableLinkedOnOrAfter(CFSystemVersionJaguar)) || !foundChar) {
+           CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary."));
            failedParse = true;
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Missing ';' on line %d"), lineNumber(pInfo));
+           pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Missing ';' on line %d"), lineNumber(pInfo));
        } else {
            // on pre-Jaguar systems, do nothing except silently ignore the rest
            // of the dictionary, which is what happened on those systems.
@@ -2427,9 +2785,9 @@ static CFDictionaryRef parsePlistDictContent(_CFXMLPlistParseInfo *pInfo) {
         CFRelease(dict);
         return NULL;
     }
-    if (pInfo->errorString) {
-       CFRelease(pInfo->errorString);
-       pInfo->errorString = NULL;
+    if (pInfo->error) {
+        CFRelease(pInfo->error);
+        pInfo->error = NULL;
     }
     return dict;
 }
@@ -2437,10 +2795,10 @@ static CFDictionaryRef parsePlistDictContent(_CFXMLPlistParseInfo *pInfo) {
 static CFTypeRef parsePlistDict(_CFXMLPlistParseInfo *pInfo) {
     CFDictionaryRef dict = parsePlistDictContent(pInfo);
     if (!dict) return NULL;
-    advanceToNonSpace(pInfo);
-    if (*pInfo->curr != '}') {
+    Boolean foundChar = advanceToNonSpace(pInfo);
+    if (!foundChar || *pInfo->curr != '}') {
         CFRelease(dict);
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Expected terminating '}' for dictionary at line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Expected terminating '}' for dictionary at line %d"), lineNumber(pInfo));
         return NULL;
     }
     pInfo->curr ++;
@@ -2491,19 +2849,23 @@ static CFTypeRef parsePlistData(_CFXMLPlistParseInfo *pInfo) {
        int numBytesRead = getDataBytes(pInfo, bytes, numBytes);
        if (numBytesRead < 0) {
            CFRelease(result);
-               switch (numBytesRead) {
-                   case -2: pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Malformed data byte group at line %d; uneven length"), lineNumber(pInfo)); break;
-                   default: pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Malformed data byte group at line %d; invalid hex"), lineNumber(pInfo)); break;
-               }
+            switch (numBytesRead) {
+                case -2: 
+                    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Malformed data byte group at line %d; uneven length"), lineNumber(pInfo));
+                    break;
+                default: 
+                    pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Malformed data byte group at line %d; invalid hex"), lineNumber(pInfo));
+                    break;
+            }
            return NULL;
        }
        if (numBytesRead == 0) break;
        CFDataAppendBytes(result, bytes, numBytesRead);
     }
 
-    if (pInfo->errorString) {
-       CFRelease(pInfo->errorString);
-       pInfo->errorString = NULL;
+    if (pInfo->error) {
+        CFRelease(pInfo->error);
+        pInfo->error = NULL;
     }
 
     if (*(pInfo->curr) == '>') {
@@ -2511,7 +2873,7 @@ static CFTypeRef parsePlistData(_CFXMLPlistParseInfo *pInfo) {
         return result;
     } else {
         CFRelease(result);
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Expected terminating '>' for data at line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Expected terminating '>' for data at line %d"), lineNumber(pInfo));
         return NULL;
     }
 }
@@ -2520,11 +2882,11 @@ static CFTypeRef parsePlistData(_CFXMLPlistParseInfo *pInfo) {
 // Returned object is retained; caller must free.
 static CFTypeRef parsePlistObject(_CFXMLPlistParseInfo *pInfo, bool requireObject) {
     UniChar ch;
-    advanceToNonSpace(pInfo);
-    if (pInfo->curr + 1 >= pInfo->end) {
-       if (requireObject) {
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unexpected EOF while parsing plist"));
-       }
+    Boolean foundChar = advanceToNonSpace(pInfo);
+    if (!foundChar) {
+        if (requireObject) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF while parsing plist"));
+        }
         return NULL;
     }
     ch = *(pInfo->curr);
@@ -2542,9 +2904,9 @@ static CFTypeRef parsePlistObject(_CFXMLPlistParseInfo *pInfo, bool requireObjec
         return parseUnquotedPlistString(pInfo);
     } else {
         pInfo->curr --;  // Must back off the charcter we just read
-       if (requireObject) {
-           pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Unexpected character '0x%x' at line %d"), ch, lineNumber(pInfo));
-       }
+        if (requireObject) {
+            pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Unexpected character '0x%x' at line %d"), ch, lineNumber(pInfo));
+        }
         return NULL;
     }
 }
@@ -2552,16 +2914,16 @@ static CFTypeRef parsePlistObject(_CFXMLPlistParseInfo *pInfo, bool requireObjec
 static CFTypeRef parseOldStylePropertyListOrStringsFile(_CFXMLPlistParseInfo *pInfo) {
     const UniChar *begin = pInfo->curr;
     CFTypeRef result;
-    advanceToNonSpace(pInfo);
+    Boolean foundChar = advanceToNonSpace(pInfo);
     // A file consisting only of whitespace (or empty) is now defined to be an empty dictionary
-    if (pInfo->curr >= pInfo->end) return CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    if (!foundChar) return CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
     result = parsePlistObject(pInfo, true);
-    advanceToNonSpace(pInfo);
-    if (pInfo->curr >= pInfo->end) return result;
+    foundChar = advanceToNonSpace(pInfo);
+    if (!foundChar) return result;
     if (!result) return NULL;
     if (CFGetTypeID(result) != stringtype) {
         CFRelease(result);
-       pInfo->errorString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("Junk after plist at line %d"), lineNumber(pInfo));
+        pInfo->error = __CFPropertyListCreateError(pInfo->allocator, kCFPropertyListReadCorruptError, CFSTR("Junk after plist at line %d"), lineNumber(pInfo));
         return NULL;
     }
     CFRelease(result);
index 9058434c7ce30c62897ed60fa869e5e387634359..f61a87a1e3614b3f45c4387ab39aae8caa2fa80d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFPropertyList.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFPROPERTYLIST__)
@@ -40,7 +40,7 @@ enum {
     kCFPropertyListMutableContainersAndLeaves
 };
 typedef CFOptionFlags CFPropertyListMutabilityOptions;
-    
+
 /*
        Creates a property list object from its XML description; xmlData should
        be the raw bytes of that description, possibly the contents of an XML
@@ -48,6 +48,8 @@ typedef CFOptionFlags CFPropertyListMutabilityOptions;
        and errorString is non-NULL, a human-readable description of the failure
        is returned in errorString. It is the caller's responsibility to release
        either the returned object or the error string, whichever is applicable.
+        This function is obsolete and will be deprecated soon. See CFPropertyListCreateWithData() for a replacement.
 */
 CF_EXPORT
 CFPropertyListRef CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags mutabilityOption, CFStringRef *errorString);
@@ -61,6 +63,8 @@ CFPropertyListRef CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDa
        appropriate for writing out to an XML file. Note that a data, not a
        string, is returned because the bytes contain in them a description
        of the string encoding used.
+        This function is obsolete and will be deprecated soon. See CFPropertyListCreateData() for a replacement.
 */
 CF_EXPORT
 CFDataRef CFPropertyListCreateXMLData(CFAllocatorRef allocator, CFPropertyListRef propertyList);
@@ -83,17 +87,13 @@ enum {
 };
 typedef CFIndex CFPropertyListFormat;
 
-CF_EXPORT
-Boolean CFPropertyListIsValid(CFPropertyListRef plist, CFPropertyListFormat format);
-
 /* Returns true if the object graph rooted at plist is a valid property list
  * graph -- that is, no cycles, containing only plist objects, and dictionary
  * keys are strings. The debugging library version spits out some messages
  * to be helpful. The plist structure which is to be allowed is given by
  * the format parameter. */
-
 CF_EXPORT
-CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStreamRef stream, CFPropertyListFormat format, CFStringRef *errorString);
+Boolean CFPropertyListIsValid(CFPropertyListRef plist, CFPropertyListFormat format);
 
 /* Writes the bytes of a plist serialization out to the stream.  The
  * stream must be opened and configured -- the function simply writes
@@ -102,10 +102,12 @@ CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStrea
  * reading stream to end wherever the writing ended, so that the
  * end of the plist data can be identified. Returns the number of bytes
  * written, or 0 on error. Error messages are not currently localized, but
- * may be in the future, so they are not suitable for comparison. */
-
+ * may be in the future, so they are not suitable for comparison. 
+ *
+ * This function is obsolete and will be deprecated soon. See CFPropertyListWrite() for a replacement. */
 CF_EXPORT
-CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFStringRef *errorString);
+CFIndex CFPropertyListWriteToStream(CFPropertyListRef propertyList, CFWriteStreamRef stream, CFPropertyListFormat format, CFStringRef *errorString);
+
 
 /* Same as current function CFPropertyListCreateFromXMLData()
  * but takes a stream instead of data, and works on any plist file format.
@@ -115,10 +117,44 @@ CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFRea
  * of the stream, which is expected to be the end of the plist, or up to the
  * number of bytes given by the length parameter if it is not 0. Error messages
  * are not currently localized, but may be in the future, so they are not
- * suitable for comparison. */
+ * suitable for comparison. 
+ *
+ * This function is obsolete and will be deprecated soon. See CFPropertyListCreateWithStream() for a replacement. */
+CF_EXPORT
+CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFStringRef *errorString);
+
+#endif
 
+#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED
+enum {
+    kCFPropertyListReadCorruptError = 3840,              // Error parsing a property list
+    kCFPropertyListReadUnknownVersionError = 3841,       // The version number in the property list is unknown
+    kCFPropertyListReadStreamError = 3842,               // Stream error reading a property list
+    kCFPropertyListWriteStreamError = 3851,              // Stream error writing a property list
+};
 #endif
 
+/* Create a property list with a CFData input. If the format parameter is non-NULL, it will be set to the format of the data after parsing is complete. The options parameter is used to specify CFPropertyListMutabilityOptions. If an error occurs while parsing the data, the return value will be NULL. Additionally, if an error occurs and the error parameter is non-NULL, the error parameter will be set to a CFError describing the problem, which the caller must release. If the parse succeeds, the returned value is a reference to the new property list. It is the responsibility of the caller to release this value.
+ */
+CF_EXPORT
+CFPropertyListRef CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags options, CFPropertyListFormat *format, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+/* Create and return a property list with a CFReadStream input. TIf the format parameter is non-NULL, it will be set to the format of the data after parsing is complete. The options parameter is used to specify CFPropertyListMutabilityOptions. The streamLength parameter specifies the number of bytes to read from the stream. Set streamLength to 0 to read until the end of the stream is detected. If an error occurs while parsing the data, the return value will be NULL. Additionally, if an error occurs and the error parameter is non-NULL, the error parameter will be set to a CFError describing the problem, which the caller must release. If the parse succeeds, the returned value is a reference to the new property list. It is the responsibility of the caller to release this value.
+ */
+CF_EXPORT
+CFPropertyListRef CFPropertyListCreateWithStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags options, CFPropertyListFormat *format, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+/* Write the bytes of a serialized property list out to a stream. The stream must be opened and configured. The format of the property list can be chosen with the format parameter. The options parameter is currently unused and should be set to 0. The return value is the number of bytes written or 0 in the case of an error. If an error occurs and the error parameter is non-NULL, the error parameter will be set to a CFError describing the problem, which the caller must release.
+ */
+CF_EXPORT
+CFIndex CFPropertyListWrite(CFPropertyListRef propertyList, CFWriteStreamRef stream, CFPropertyListFormat format, CFOptionFlags options, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+/* Create a CFData with the bytes of a serialized property list. The format of the property list can be chosen with the format parameter. The options parameter is currently unused and should be set to 0. If an error occurs while parsing the data, the return value will be NULL. Additionally, if an error occurs and the error parameter is non-NULL, the error parameter will be set to a CFError describing the problem, which the caller must release. If the conversion succeeds, the returned value is a reference to the created data. It is the responsibility of the caller to release this value.
+ */
+CF_EXPORT
+CFDataRef CFPropertyListCreateData(CFAllocatorRef allocator, CFPropertyListRef propertyList, CFPropertyListFormat format, CFOptionFlags options, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
 CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFPROPERTYLIST__ */
index 824f077fe13feeaa64867e04003ad86f4897daad..4527d19cbcdfeba41c6ccaf0624a956f6987dc3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFRunLoop.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
-#if (DEPLOYMENT_TARGET_MACOSX) || defined(__WIN32__)
-
 #include <CoreFoundation/CFRunLoop.h>
 #include <CoreFoundation/CFSet.h>
 #include <CoreFoundation/CFBag.h>
 #include <math.h>
 #include <stdio.h>
 #include <limits.h>
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#include <dispatch/dispatch.h>
 #include <mach/mach.h>
 #include <mach/clock_types.h>
 #include <mach/clock.h>
 #include <unistd.h>
 #include <dlfcn.h>
+extern mach_port_t _dispatch_get_main_queue_port_4CF(void);
+extern void _dispatch_main_queue_callback_4CF(mach_msg_header_t *msg);
 #else
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-// With the MS headers, turning off Standard-C gets you macros for stat vs _stat.
-// Strictly speaking, this is supposed to control traditional vs ANSI C features.
-#undef __STDC__
-#endif
-#include <windows.h>
-#include <pthread.h>
 #include <process.h>
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define __STDC__
-#endif
+#define __CFReadTSR() mach_absolute_time()
 #endif
+#include <Block.h>
 
 static int _LogCFRunLoop = 0;
 
-#if 0 || 0
+// for conservative arithmetic safety, such that (TIMER_DATE_LIMIT + TIMER_INTERVAL_LIMIT + kCFAbsoluteTimeIntervalSince1970) * 10^9 < 2^63
+#define TIMER_DATE_LIMIT       4039289856.0
+#define TIMER_INTERVAL_LIMIT   504911232.0
+
+#define HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY 0
+
+#if DEPLOYMENT_TARGET_WINDOWS
 static pthread_t kNilPthreadT = { nil, nil };
 #define pthreadPointer(a) a.p
-#define lockCount(a) a.LockCount
+
+static DWORD __CFTSDKeyRunLoopKey = ~0;
+
+// See function below.
+bool gMARRY_MESSAGE_QUEUE = FALSE;
+//
+// vod __CFSetNonMachRunLoopMarryMsgQueueMode(bool bEnabled)
+//
+//  This function will exist for a while until code is written
+//  by the WebKit folks to handle the new RunLoop message-queue
+//  model.
+CF_EXPORT void __CFSetNonMachRunLoopMarryMsgQueueMode(bool bEnabled) {
+    gMARRY_MESSAGE_QUEUE = bEnabled;
+}
+bool __CFIsNonMachRunLoopMarryMsgQueueEnabled(void) {
+    return gMARRY_MESSAGE_QUEUE;
+}
+
 #else
+
 static pthread_t kNilPthreadT = (pthread_t)0;
 #define pthreadPointer(a) a
 #define lockCount(a) a
 #endif
 
-
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <sys/types.h>
 #include <sys/event.h>
 
@@ -91,28 +107,34 @@ typedef struct {
 // There is no way to reset the state in a kevent (such as clearing the EV_EOF state for fifos).
 #endif
 
-extern bool CFDictionaryGetKeyIfPresent(CFDictionaryRef dict, const void *key, const void **actualkey);
+CF_EXPORT bool CFDictionaryGetKeyIfPresent(CFDictionaryRef dict, const void *key, const void **actualkey);
 
 // In order to reuse most of the code across Mach and Windows v1 RunLoopSources, we define a
 // simple abstraction layer spanning Mach ports and Windows HANDLES
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 
 typedef mach_port_t __CFPort;
 #define CFPORT_NULL MACH_PORT_NULL
 typedef mach_port_t __CFPortSet;
 
+static void __THE_SYSTEM_HAS_NO_PORTS_AVAILABLE__(kern_return_t ret) __attribute__((noinline));
+static void __THE_SYSTEM_HAS_NO_PORTS_AVAILABLE__(kern_return_t ret) { HALT; };
+
 static __CFPort __CFPortAllocate(void) {
-    __CFPort result;
+    __CFPort result = CFPORT_NULL;
     kern_return_t ret;
     ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &result);
     if (KERN_SUCCESS == ret) {
         ret = mach_port_insert_right(mach_task_self(), result, result, MACH_MSG_TYPE_MAKE_SEND);
+    } else {
+        __THE_SYSTEM_HAS_NO_PORTS_AVAILABLE__(ret);
     }
     if (KERN_SUCCESS == ret) {
         mach_port_limits_t limits;
         limits.mpl_qlimit = 1;
         ret = mach_port_set_attributes(mach_task_self(), result, MACH_PORT_LIMITS_INFO, (mach_port_info_t)&limits, MACH_PORT_LIMITS_INFO_COUNT);
     }
+    if (KERN_SUCCESS != ret) mach_port_destroy(mach_task_self(), result);
     return (KERN_SUCCESS == ret) ? result : CFPORT_NULL;
 }
 
@@ -120,9 +142,13 @@ CF_INLINE void __CFPortFree(__CFPort port) {
     mach_port_destroy(mach_task_self(), port);
 }
 
+static void __THE_SYSTEM_HAS_NO_PORT_SETS_AVAILABLE__(kern_return_t ret) __attribute__((noinline));
+static void __THE_SYSTEM_HAS_NO_PORT_SETS_AVAILABLE__(kern_return_t ret) { HALT; };
+
 CF_INLINE __CFPortSet __CFPortSetAllocate(void) {
     __CFPortSet result;
     kern_return_t ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &result);
+    if (KERN_SUCCESS != ret) { __THE_SYSTEM_HAS_NO_PORT_SETS_AVAILABLE__(ret); }
     return (KERN_SUCCESS == ret) ? result : CFPORT_NULL;
 }
 
@@ -151,7 +177,7 @@ CF_INLINE void __CFPortSetFree(__CFPortSet portSet) {
     mach_port_destroy(mach_task_self(), portSet);
 }
 
-#elif defined(__WIN32__)
+#elif DEPLOYMENT_TARGET_WINDOWS
 
 typedef HANDLE __CFPort;
 #define CFPORT_NULL NULL
@@ -165,7 +191,7 @@ typedef struct ___CFPortSet {
 } *__CFPortSet;
 
 CF_INLINE __CFPort __CFPortAllocate(void) {
-    return CreateEvent(NULL, true, false, NULL);
+    return CreateEventA(NULL, true, false, NULL);
 }
 
 CF_INLINE void __CFPortFree(__CFPort port) {
@@ -173,10 +199,10 @@ CF_INLINE void __CFPortFree(__CFPort port) {
 }
 
 static __CFPortSet __CFPortSetAllocate(void) {
-    __CFPortSet result = CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(struct ___CFPortSet), 0);
+    __CFPortSet result = (__CFPortSet)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(struct ___CFPortSet), 0);
     result->used = 0;
     result->size = 4;
-    result->handles = CFAllocatorAllocate(kCFAllocatorSystemDefault, result->size * sizeof(HANDLE), 0);
+    result->handles = (HANDLE *)CFAllocatorAllocate(kCFAllocatorSystemDefault, result->size * sizeof(HANDLE), 0);
     CF_SPINLOCK_INIT_FOR_STRUCTS(result->lock);
     return result;
 }
@@ -190,8 +216,15 @@ static void __CFPortSetFree(__CFPortSet portSet) {
 static __CFPort *__CFPortSetGetPorts(__CFPortSet portSet, __CFPort *portBuf, uint32_t bufSize, uint32_t *portsUsed) {
     __CFSpinLock(&(portSet->lock));
     __CFPort *result = portBuf;
-    if (bufSize > portSet->used)
-        result = CFAllocatorAllocate(kCFAllocatorSystemDefault, portSet->used * sizeof(HANDLE), 0);
+    if (bufSize < portSet->used)
+       result = (__CFPort *)CFAllocatorAllocate(kCFAllocatorSystemDefault, portSet->used * sizeof(HANDLE), 0);
+    if (portSet->used > 1) {
+       // rotate the ports to vaguely simulate round-robin behaviour
+       uint16_t lastPort = portSet->used - 1;
+       HANDLE swapHandle = portSet->handles[0];
+       memmove(portSet->handles, &portSet->handles[1], lastPort * sizeof(HANDLE));
+       portSet->handles[lastPort] = swapHandle;
+    }
     memmove(result, portSet->handles, portSet->used * sizeof(HANDLE));
     *portsUsed = portSet->used;
     __CFSpinUnlock(&(portSet->lock));
@@ -202,7 +235,7 @@ static Boolean __CFPortSetInsert(__CFPort port, __CFPortSet portSet) {
     __CFSpinLock(&(portSet->lock));
     if (portSet->used >= portSet->size) {
         portSet->size += 4;
-        portSet->handles = CFAllocatorReallocate(kCFAllocatorSystemDefault, portSet->handles, portSet->size * sizeof(HANDLE), 0);
+        portSet->handles = (HANDLE *)CFAllocatorReallocate(kCFAllocatorSystemDefault, portSet->handles, portSet->size * sizeof(HANDLE), 0);
     }
     if (portSet->used >= MAXIMUM_WAIT_OBJECTS)
         CFLog(kCFLogLevelWarning, CFSTR("*** More than MAXIMUM_WAIT_OBJECTS (%d) ports add to a port set.  The last ones will be ignored."), MAXIMUM_WAIT_OBJECTS);
@@ -230,7 +263,7 @@ static Boolean __CFPortSetRemove(__CFPort port, __CFPortSet portSet) {
 
 #endif
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 extern mach_port_name_t mk_timer_create(void);
 extern kern_return_t mk_timer_destroy(mach_port_name_t name);
 extern kern_return_t mk_timer_arm(mach_port_name_t name, AbsoluteTime expire_time);
@@ -268,6 +301,12 @@ static CFTypeID __kCFRunLoopSourceTypeID = _kCFRuntimeNotATypeID;
 static CFTypeID __kCFRunLoopObserverTypeID = _kCFRuntimeNotATypeID;
 static CFTypeID __kCFRunLoopTimerTypeID = _kCFRuntimeNotATypeID;
 
+#if DEPLOYMENT_TARGET_WINDOWS
+// The MSG identifier for the  Windows message injected in the message queue to wake the run loop
+static unsigned int __kCFRunLoopWakeUpMessage = 0;
+static unsigned int __kCFRunLoopV1SourceReadyMessage = 0;
+#endif
+
 typedef struct __CFRunLoopMode *CFRunLoopModeRef;
 
 struct __CFRunLoopMode {
@@ -279,15 +318,18 @@ struct __CFRunLoopMode {
     CFMutableSetRef _sources;
     CFMutableSetRef _observers;
     CFMutableSetRef _timers;
+    CFMutableDictionaryRef _portToV1SourceMap;
     CFMutableArrayRef _submodes; // names of the submodes
     __CFPortSet _portSet;
-#if DEPLOYMENT_TARGET_MACOSX
+    CFIndex _observerMask;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     int _kq;
 #endif
+#if DEPLOYMENT_TARGET_WINDOWS
+    DWORD _msgQMask;
+#endif
 };
 
-static int64_t __CFRunLoopGetNextTimerFireTSR(CFRunLoopRef rl, CFRunLoopModeRef rlm);
-
 CF_INLINE void __CFRunLoopModeLock(CFRunLoopModeRef rlm) {
     __CFSpinLock(&(rlm->_lock));
 }
@@ -311,9 +353,16 @@ static CFStringRef __CFRunLoopModeCopyDescription(CFTypeRef cf) {
     CFRunLoopModeRef rlm = (CFRunLoopModeRef)cf;
     CFMutableStringRef result;
     result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
+#if DEPLOYMENT_TARGET_WINDOWS
+    CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoopMode %p [%p]>{name = %@, locked = %s, "), rlm, CFGetAllocator(rlm), rlm->_name, "unknown");
+#else
     CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoopMode %p [%p]>{name = %@, locked = %s, "), rlm, CFGetAllocator(rlm), rlm->_name, lockCount(rlm->_lock) ? "true" : "false");
+#endif
     CFStringAppendFormat(result, NULL, CFSTR("port set = %p,"), rlm->_portSet);
-    CFStringAppendFormat(result, NULL, CFSTR("\n\tsources = %@,\n\tobservers == %@,\n\ttimers = %@\n},\n"), rlm->_sources, rlm->_observers, rlm->_timers);
+#if DEPLOYMENT_TARGET_WINDOWS
+    CFStringAppendFormat(result, NULL, CFSTR("MSGQ mask = %p,"), rlm->_msgQMask);
+#endif
+    CFStringAppendFormat(result, NULL, CFSTR("\n\tsources = %@,\n\tobservers = %@,\n\ttimers = %@\n},\n"), rlm->_sources, rlm->_observers, rlm->_timers);
     return result;
 }
 
@@ -323,25 +372,47 @@ static void __CFRunLoopModeDeallocate(CFTypeRef cf) {
     if (NULL != rlm->_observers) CFRelease(rlm->_observers);
     if (NULL != rlm->_timers) CFRelease(rlm->_timers);
     if (NULL != rlm->_submodes) CFRelease(rlm->_submodes);
+    if (NULL != rlm->_portToV1SourceMap) CFRelease(rlm->_portToV1SourceMap);
     CFRelease(rlm->_name);
     __CFPortSetFree(rlm->_portSet);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (-1 != rlm->_kq) close(rlm->_kq);
 #endif
+    memset((char *)cf + sizeof(CFRuntimeBase), 0x7C, sizeof(struct __CFRunLoopMode) - sizeof(CFRuntimeBase));
 }
 
+struct _block_item {
+    struct _block_item *_next;
+    CFTypeRef _mode;   // CFString or CFSet or CFRunLoopTimer
+    void (^_block)(void);
+};
+
 struct __CFRunLoop {
     CFRuntimeBase _base;
     CFSpinLock_t _lock;                        /* locked for accessing mode list */
     __CFPort _wakeUpPort;                      // used for CFRunLoopWakeUp 
     volatile uint32_t *_stopped;
+    pthread_t _pthread;
     CFMutableSetRef _commonModes;
     CFMutableSetRef _commonModeItems;
     CFRunLoopModeRef _currentMode;
     CFMutableSetRef _modes;
-    void *_counterpart;
+    struct _block_item *_blocks_head;
+    struct _block_item *_blocks_tail;
+#if DEPLOYMENT_TARGET_WINDOWS
+    DWORD _threadID;
+    __CFPort _msgUpdatePort;
+#endif
+    CFTypeRef _counterpart;
 };
 
+#if DEPLOYMENT_TARGET_WINDOWS
+void __CFRunLoopUpdateMsgWait(CFRunLoopRef rl);
+void __CFRunLoopUpdateMsgWaitMarryMsgQueue(CFRunLoopRef rl);
+static Boolean __CFRunLoopDoSource1(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopSourceRef rls);
+CF_EXPORT LRESULT CALLBACK pumpRunLoopFromMessageQueue(int nCode, WPARAM wParam, LPARAM lParam);
+#endif
+
 /* Bit 0 of the base reserved bits is used for stopped state */
 /* Bit 1 of the base reserved bits is used for sleeping state */
 /* Bit 2 of the base reserved bits is used for deallocating state */
@@ -351,6 +422,13 @@ CF_INLINE Boolean __CFRunLoopIsStopped(CFRunLoopRef rl) {
 }
 
 CF_INLINE void __CFRunLoopSetStopped(CFRunLoopRef rl) {
+    if (!rl->_stopped) {
+        rl->_stopped = (uint32_t volatile *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 4 * sizeof(uint32_t), 0);
+        rl->_stopped[0] = 0x4346524C;
+        rl->_stopped[1] = 0x4346524C; // 'CFRL'
+        rl->_stopped[2] = 0x00000000; // here the value is stored
+        rl->_stopped[3] = 0x4346524C;
+    }
     if (rl->_stopped) rl->_stopped[2] = 0x53544F50;    // 'STOP'
 }
 
@@ -390,18 +468,26 @@ static CFStringRef __CFRunLoopCopyDescription(CFTypeRef cf) {
     CFRunLoopRef rl = (CFRunLoopRef)cf;
     CFMutableStringRef result;
     result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
-    CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoop %p [%p]>{locked = %s, wait port = 0x%x, stopped = %s,\ncurrent mode = %@,\n"), cf, CFGetAllocator(cf), lockCount(rl->_lock) ? "true" : "false", rl->_wakeUpPort, (rl->_stopped && (rl->_stopped[2] == 0x53544F50)) ? "true" : "false", rl->_currentMode ? rl->_currentMode->_name : CFSTR("(none)"));
+#if DEPLOYMENT_TARGET_WINDOWS
+    CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoop %p [%p]>{locked = %s, wakeup port = 0x%x, stopped = %s,\ncurrent mode = %@,\n"), cf, CFGetAllocator(cf), "unknown", rl->_wakeUpPort, (rl->_stopped && *(rl->_stopped)) ? "true" : "false", rl->_currentMode ? rl->_currentMode->_name : CFSTR("(none)"));
+#else
+    CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoop %p [%p]>{locked = %s, wakeup port = 0x%x, stopped = %s,\ncurrent mode = %@,\n"), cf, CFGetAllocator(cf), lockCount(rl->_lock) ? "true" : "false", rl->_wakeUpPort, (rl->_stopped && (rl->_stopped[2] == 0x53544F50)) ? "true" : "false", rl->_currentMode ? rl->_currentMode->_name : CFSTR("(none)"));
+#endif
     CFStringAppendFormat(result, NULL, CFSTR("common modes = %@,\ncommon mode items = %@,\nmodes = %@}\n"), rl->_commonModes, rl->_commonModeItems, rl->_modes);
     return result;
 }
 
+__private_extern__ void __CFRunLoopDump() { // __private_extern__ to keep the compiler from discarding it
+    CFShow(CFCopyDescription(CFRunLoopGetCurrent()));
+}
+
 /* call with rl locked */
 static CFRunLoopModeRef __CFRunLoopFindMode(CFRunLoopRef rl, CFStringRef modeName, Boolean create) {
     CHECK_FOR_FORK();
     CFRunLoopModeRef rlm;
     struct __CFRunLoopMode srlm;
+    memset(&srlm, 0, sizeof(srlm));
     srlm._base._cfisa = __CFISAForTypeID(__kCFRunLoopModeTypeID);
-    srlm._base._cfinfo[CF_INFO_BITS] = 0;
     _CFRuntimeSetInstanceTypeID(&srlm, __kCFRunLoopModeTypeID);
     srlm._name = modeName;
     rlm = (CFRunLoopModeRef)CFSetGetValue(rl->_modes, &srlm);
@@ -412,22 +498,26 @@ static CFRunLoopModeRef __CFRunLoopFindMode(CFRunLoopRef rl, CFStringRef modeNam
     if (!create) {
        return NULL;
     }
-    rlm = (CFRunLoopModeRef)_CFRuntimeCreateInstance(CFGetAllocator(rl), __kCFRunLoopModeTypeID, sizeof(struct __CFRunLoopMode) - sizeof(CFRuntimeBase), NULL);
+    rlm = (CFRunLoopModeRef)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault, __kCFRunLoopModeTypeID, sizeof(struct __CFRunLoopMode) - sizeof(CFRuntimeBase), NULL);
     if (NULL == rlm) {
        return NULL;
     }
     CF_SPINLOCK_INIT_FOR_STRUCTS(rlm->_lock);
-    rlm->_name = CFStringCreateCopy(CFGetAllocator(rlm), modeName);
+    rlm->_name = CFStringCreateCopy(kCFAllocatorSystemDefault, modeName);
     rlm->_stopped = false;
+    rlm->_portToV1SourceMap = NULL;
     rlm->_sources = NULL;
     rlm->_observers = NULL;
     rlm->_timers = NULL;
     rlm->_submodes = NULL;
+    rlm->_observerMask = 0;
     rlm->_portSet = __CFPortSetAllocate();
-    if (CFPORT_NULL == rlm->_portSet) HALT;
     if (!__CFPortSetInsert(rl->_wakeUpPort, rlm->_portSet)) HALT;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     rlm->_kq = -1;
+#endif
+#if DEPLOYMENT_TARGET_WINDOWS
+    rlm->_msgQMask = 0;
 #endif
     CFSetAddValue(rl->_modes, rlm);
     CFRelease(rlm);
@@ -437,11 +527,32 @@ static CFRunLoopModeRef __CFRunLoopFindMode(CFRunLoopRef rl, CFStringRef modeNam
 
 
 // expects rl and rlm locked
-static Boolean __CFRunLoopModeIsEmpty(CFRunLoopRef rl, CFRunLoopModeRef rlm) {
+static Boolean __CFRunLoopModeIsEmpty(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopModeRef previousMode) {
     CHECK_FOR_FORK();
     if (NULL == rlm) return true;
+#if DEPLOYMENT_TARGET_WINDOWS
+    if (0 != rlm->_msgQMask) return false;
+#endif
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    Boolean libdispatchQSafe = pthread_main_np() && ((HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && NULL == previousMode) || (!HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && 0 == pthread_getspecific(__CFTSDKeyIsInGCDMainQ)));
+    if (libdispatchQSafe && (CFRunLoopGetMain() == rl) && CFSetContainsValue(rl->_commonModes, rlm->_name)) return false; // represents the libdispatch main queue
+#endif
     if (NULL != rlm->_sources && 0 < CFSetGetCount(rlm->_sources)) return false;
     if (NULL != rlm->_timers && 0 < CFSetGetCount(rlm->_timers)) return false;
+#if 1
+    struct _block_item *item = rl->_blocks_head;
+    while (item) {
+        struct _block_item *curr = item;
+        item = item->_next;
+        Boolean doit = false;
+        if (CFStringGetTypeID() == CFGetTypeID(curr->_mode)) {
+            doit = CFEqual(curr->_mode, rlm->_name) || (CFEqual(curr->_mode, kCFRunLoopCommonModes) && CFSetContainsValue(rl->_commonModes, rlm->_name));
+        } else {
+            doit = CFSetContainsValue((CFSetRef)curr->_mode, rlm->_name) || (CFSetContainsValue((CFSetRef)curr->_mode, kCFRunLoopCommonModes) && CFSetContainsValue(rl->_commonModes, rlm->_name));
+        }
+        if (doit) return false;
+    }
+#endif
     if (NULL != rlm->_submodes) {
        CFIndex idx, cnt;
        for (idx = 0, cnt = CFArrayGetCount(rlm->_submodes); idx < cnt; idx++) {
@@ -449,7 +560,7 @@ static Boolean __CFRunLoopModeIsEmpty(CFRunLoopRef rl, CFRunLoopModeRef rlm) {
            CFRunLoopModeRef subrlm;
            Boolean subIsEmpty;
            subrlm = __CFRunLoopFindMode(rl, modeName, false);
-           subIsEmpty = (NULL != subrlm) ? __CFRunLoopModeIsEmpty(rl, subrlm) : true;
+           subIsEmpty = (NULL != subrlm) ? __CFRunLoopModeIsEmpty(rl, subrlm, previousMode) : true;
            if (NULL != subrlm) __CFRunLoopModeUnlock(subrlm);
            if (!subIsEmpty) return false;
        }
@@ -457,6 +568,30 @@ static Boolean __CFRunLoopModeIsEmpty(CFRunLoopRef rl, CFRunLoopModeRef rlm) {
     return true;
 }
 
+#if DEPLOYMENT_TARGET_WINDOWS
+DWORD __CFRunLoopGetWindowsMessageQueueMask(CFRunLoopRef rl, CFStringRef modeName) {
+    CFRunLoopModeRef rlm;
+    DWORD result = 0;
+    __CFRunLoopLock(rl);
+    rlm = __CFRunLoopFindMode(rl, modeName, false);
+    if (rlm) {
+       result = rlm->_msgQMask;
+       __CFRunLoopModeUnlock(rlm);
+    }
+    __CFRunLoopUnlock(rl);
+    return result;
+}
+
+void __CFRunLoopSetWindowsMessageQueueMask(CFRunLoopRef rl, DWORD mask, CFStringRef modeName) {
+    CFRunLoopModeRef rlm;
+    __CFRunLoopLock(rl);
+    rlm = __CFRunLoopFindMode(rl, modeName, true);
+    rlm->_msgQMask = mask;
+    __CFRunLoopModeUnlock(rlm);
+    __CFRunLoopUnlock(rl);
+}
+#endif
+
 /* Bit 3 in the base reserved bits is used for invalid state in run loop objects */
 
 CF_INLINE Boolean __CFIsValid(const void *cf) {
@@ -507,9 +642,10 @@ CF_INLINE void __CFRunLoopSourceUnlock(CFRunLoopSourceRef rls) {
 
 /* rlm is not locked */
 static void __CFRunLoopSourceSchedule(CFRunLoopSourceRef rls, CFRunLoopRef rl, CFRunLoopModeRef rlm) { /* DOES CALLOUT */
+//printf("Scheduling source %p with mode %s in loop %p\n", rls, CFStringGetCStringPtr(rlm->_name, 0), rl);
     __CFRunLoopSourceLock(rls);
     if (NULL == rls->_runLoops) {
-       rls->_runLoops = CFBagCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
+       rls->_runLoops = CFBagCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeBagCallBacks); // sources retain run loops!
     }
     CFBagAddValue(rls->_runLoops, rl);
     __CFRunLoopSourceUnlock(rls);      // have to unlock before the callout -- cannot help clients with safety
@@ -522,11 +658,28 @@ static void __CFRunLoopSourceSchedule(CFRunLoopSourceRef rls, CFRunLoopRef rl, C
        if (CFPORT_NULL != port) {
             __CFPortSetInsert(port, rlm->_portSet);
        }
+#if DEPLOYMENT_TARGET_WINDOWS
+        __CFRunLoopLock(rl);
+        //#warning Bug here - if rl->_currentMode is NULL and rlm == the default mode, we should also update
+        if (rl->_currentMode == rlm) {
+            if (__CFIsNonMachRunLoopMarryMsgQueueEnabled())
+                __CFRunLoopUpdateMsgWaitMarryMsgQueue(rl);
+            else
+                __CFRunLoopUpdateMsgWait(rl);
+        }
+        __CFRunLoopUnlock(rl);
+#endif
     }
 }
 
 /* rlm is not locked */
 static void __CFRunLoopSourceCancel(CFRunLoopSourceRef rls, CFRunLoopRef rl, CFRunLoopModeRef rlm) {   /* DOES CALLOUT */
+//printf("Cancelling source %p from mode %s in loop %p\n", rls, CFStringGetCStringPtr(rlm->_name, 0), rl);
+    __CFRunLoopSourceLock(rls);
+    if (NULL != rls->_runLoops) {
+        CFBagRemoveValue(rls->_runLoops, rl);
+    }
+    __CFRunLoopSourceUnlock(rls);
     if (0 == rls->_context.version0.version) {
        if (NULL != rls->_context.version0.cancel) {
            rls->_context.version0.cancel(rls->_context.version0.info, rl, rlm->_name); /* CALLOUT */
@@ -536,12 +689,18 @@ static void __CFRunLoopSourceCancel(CFRunLoopSourceRef rls, CFRunLoopRef rl, CFR
         if (CFPORT_NULL != port) {
             __CFPortSetRemove(port, rlm->_portSet);
        }
+#if DEPLOYMENT_TARGET_WINDOWS
+        __CFRunLoopLock(rl);
+        //#warning Bug here - must also update if rl->_currentMode == NULL and rlm == default mode
+        if (rl->_currentMode == rlm && rl->_msgUpdatePort != CFPORT_NULL) {
+            if (__CFIsNonMachRunLoopMarryMsgQueueEnabled())
+                __CFRunLoopUpdateMsgWaitMarryMsgQueue(rl);
+            else
+                __CFRunLoopUpdateMsgWait(rl);
+        }
+        __CFRunLoopUnlock(rl);
+#endif
     }
-    __CFRunLoopSourceLock(rls);
-    if (NULL != rls->_runLoops) {
-        CFBagRemoveValue(rls->_runLoops, rl);
-    }
-    __CFRunLoopSourceUnlock(rls);
 }
 
 struct __CFRunLoopObserver {
@@ -612,13 +771,19 @@ struct __CFRunLoopTimer {
     CFRuntimeBase _base;
     CFSpinLock_t _lock;
     CFRunLoopRef _runLoop;
-    CFIndex _rlCount;
-#if DEPLOYMENT_TARGET_MACOSX
+    CFMutableSetRef _rlModes;
+    CFAbsoluteTime _nextFireDate;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     mach_port_name_t _port;
-#endif
-    CFIndex _order;                    /* immutable */
     int64_t _fireTSR;                  /* TSR units */
     int64_t _intervalTSR;              /* immutable; 0 means non-repeating; TSR units */
+#elif DEPLOYMENT_TARGET_WINDOWS
+    CFIndex _rlCount;
+    int64_t _fireTSR;                  /* TSR units */
+    int64_t _intervalTSR;              /* immutable; 0 means non-repeating; TSR units */
+#endif
+    CFTimeInterval _interval;          /* immutable */
+    CFIndex _order;                    /* immutable */
     CFRunLoopTimerCallBack _callout;   /* immutable */
     CFRunLoopTimerContext _context;    /* immutable, except invalidation */
 };
@@ -650,6 +815,14 @@ CF_INLINE void __CFRunLoopTimerUnsetDidFire(CFRunLoopTimerRef rlt) {
     __CFBitfieldSetValue(((CFRuntimeBase *)rlt)->_cfinfo[CF_INFO_BITS], 1, 1, 0);
 }
 
+CF_INLINE Boolean __CFRunLoopTimerIsDeallocating(CFRunLoopTimerRef rlt) {
+    return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)rlt)->_cfinfo[CF_INFO_BITS], 2, 2);
+}
+
+CF_INLINE void __CFRunLoopTimerSetDeallocating(CFRunLoopTimerRef rlt) {
+    __CFBitfieldSetValue(((CFRuntimeBase *)rlt)->_cfinfo[CF_INFO_BITS], 2, 2, 1);
+}
+
 CF_INLINE void __CFRunLoopTimerLock(CFRunLoopTimerRef rlt) {
     __CFSpinLock(&(rlt->_lock));
 }
@@ -668,7 +841,7 @@ CF_INLINE void __CFRunLoopTimerFireTSRUnlock(void) {
     __CFSpinUnlock(&__CFRLTFireTSRLock);
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static CFMutableDictionaryRef __CFRLTPortMap = NULL;
 static CFSpinLock_t __CFRLTPortMapLock = CFSpinLockInit;
 
@@ -681,10 +854,20 @@ CF_INLINE void __CFRunLoopTimerPortMapUnlock(void) {
 }
 #endif
 
+static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopTimerRef rlt);
+
+// called with timer locked in libdispatch mode
+static void __CFRunLoopTimerRescheduleWithAllModes(CFRunLoopTimerRef rlt) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    mk_timer_arm(rlt->_port, __CFUInt64ToAbsoluteTime(rlt->_fireTSR));
+#endif
+}
+
 static void __CFRunLoopTimerSchedule(CFRunLoopTimerRef rlt, CFRunLoopRef rl, CFRunLoopModeRef rlm) {
-#if DEPLOYMENT_TARGET_MACOSX
+//CFLog(4, CFSTR("__CFRunLoopTimerSchedule(%p, loop %p, mode %@)  [%p, %p]"), rlt, rl, rlm->_name, rlt->_runLoop, rlt->_port);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     __CFRunLoopTimerLock(rlt);
-    if (0 == rlt->_rlCount) {
+    if (NULL == rlt->_runLoop) {
        rlt->_runLoop = rl;
        if (MACH_PORT_NULL == rlt->_port) {
            rlt->_port = mk_timer_create();
@@ -695,91 +878,114 @@ static void __CFRunLoopTimerSchedule(CFRunLoopTimerRef rlt, CFRunLoopRef rl, CFR
        }
        CFDictionarySetValue(__CFRLTPortMap, (void *)(uintptr_t)rlt->_port, rlt);
        __CFRunLoopTimerPortMapUnlock();
+       __CFRunLoopTimerRescheduleWithAllModes(rlt);
     }
-    rlt->_rlCount++;
     mach_port_insert_member(mach_task_self(), rlt->_port, rlm->_portSet);
-    mk_timer_arm(rlt->_port, __CFUInt64ToAbsoluteTime(rlt->_fireTSR));
+    CFSetAddValue(rlt->_rlModes, rlm->_name);
     __CFRunLoopTimerUnlock(rlt);
+#elif DEPLOYMENT_TARGET_WINDOWS
+    if (0 == rlt->_rlCount) {
+        rlt->_runLoop = rl;        
+    }
+    rlt->_rlCount++;
 #endif
 }
 
 static void __CFRunLoopTimerCancel(CFRunLoopTimerRef rlt, CFRunLoopRef rl, CFRunLoopModeRef rlm) {
-#if DEPLOYMENT_TARGET_MACOSX
+//CFLog(6, CFSTR("__CFRunLoopTimerCancel(rlt %p, rl %p, rlm %@)"), rlt, rl, rlm->_name);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     __CFRunLoopTimerLock(rlt);
+    CFSetRemoveValue(rlt->_rlModes, rlm->_name);
     __CFPortSetRemove(rlt->_port, rlm->_portSet);
-    rlt->_rlCount--;
-    if (0 == rlt->_rlCount) {
+    if (0 == CFSetGetCount(rlt->_rlModes)) {
        __CFRunLoopTimerPortMapLock();
        if (NULL != __CFRLTPortMap) {
            CFDictionaryRemoveValue(__CFRLTPortMap, (void *)(uintptr_t)rlt->_port);
        }
        __CFRunLoopTimerPortMapUnlock();
-       rlt->_runLoop = NULL;
        mk_timer_cancel(rlt->_port, NULL);
+       rlt->_runLoop = NULL;
     }
     __CFRunLoopTimerUnlock(rlt);
+#elif DEPLOYMENT_TARGET_WINDOWS
+    CFRunLoopWakeUp(rl);
 #endif
 }
 
-// Caller must hold the Timer lock for safety
-static void __CFRunLoopTimerRescheduleWithAllModes(CFRunLoopTimerRef rlt, CFRunLoopRef rl) {
-#if DEPLOYMENT_TARGET_MACOSX
-    mk_timer_arm(rlt->_port, __CFUInt64ToAbsoluteTime(rlt->_fireTSR));
-#endif
+#if DEPLOYMENT_TARGET_WINDOWS
+
+struct _collectTimersContext {
+    CFMutableArrayRef results;
+    int64_t cutoffTSR;
+};
+
+static void __CFRunLoopCollectTimers(const void *value, void *ctx) {
+    CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)value;
+    struct _collectTimersContext *context = (struct _collectTimersContext *)ctx;
+    if (rlt->_fireTSR <= context->cutoffTSR) {
+        if (NULL == context->results)
+            context->results = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+        CFArrayAppendValue(context->results, rlt);
+    }
+}
+
+// RunLoop and RunLoopMode must be locked
+static void __CFRunLoopTimersToFireRecursive(CFRunLoopRef rl, CFRunLoopModeRef rlm, struct _collectTimersContext *ctxt) {
+    if (NULL != rlm->_timers && 0 < CFSetGetCount(rlm->_timers)) {
+        __CFRunLoopTimerFireTSRLock();
+        CFSetApplyFunction(rlm->_timers, __CFRunLoopCollectTimers, ctxt);
+        __CFRunLoopTimerFireTSRUnlock();
+    }
+    if (NULL != rlm->_submodes) {
+        CFIndex idx, cnt;
+        for (idx = 0, cnt = CFArrayGetCount(rlm->_submodes); idx < cnt; idx++) {
+            CFStringRef modeName = (CFStringRef)CFArrayGetValueAtIndex(rlm->_submodes, idx);
+            CFRunLoopModeRef subrlm;
+            subrlm = __CFRunLoopFindMode(rl, modeName, false);
+            if (NULL != subrlm) {
+                __CFRunLoopTimersToFireRecursive(rl, subrlm, ctxt);
+                __CFRunLoopModeUnlock(subrlm);
+            }
+        }
+    }
 }
 
+// RunLoop and RunLoopMode must be locked
+static CFArrayRef __CFRunLoopTimersToFire(CFRunLoopRef rl, CFRunLoopModeRef rlm) {
+    struct _collectTimersContext ctxt = {NULL, __CFReadTSR()};
+    __CFRunLoopTimersToFireRecursive(rl, rlm, &ctxt);
+    return ctxt.results;
+}
+#endif
+
 /* CFRunLoop */
 
 CONST_STRING_DECL(kCFRunLoopDefaultMode, "kCFRunLoopDefaultMode")
 CONST_STRING_DECL(kCFRunLoopCommonModes, "kCFRunLoopCommonModes")
 
-struct _findsource {
-    __CFPort port;
-    CFRunLoopSourceRef result;
-};
-
-static void __CFRunLoopFindSource(const void *value, void *ctx) {
-    CFRunLoopSourceRef rls = (CFRunLoopSourceRef)value;
-    struct _findsource *context = (struct _findsource *)ctx;
-    __CFPort port;
-    if (NULL != context->result) return;
-    if (1 != rls->_context.version0.version) return;
-    __CFRunLoopSourceLock(rls);
-    port = rls->_context.version1.getPort(rls->_context.version1.info);
-    if (port == context->port) {
-       context->result = rls;
-    }
-    __CFRunLoopSourceUnlock(rls);
-}
-
 // call with rl and rlm locked
 static CFRunLoopSourceRef __CFRunLoopModeFindSourceForMachPort(CFRunLoopRef rl, CFRunLoopModeRef rlm, __CFPort port) { /* DOES CALLOUT */
     CHECK_FOR_FORK();
-    struct _findsource context = {port, NULL};
-    if (NULL != rlm->_sources) {
-       CFSetApplyFunction(rlm->_sources, (__CFRunLoopFindSource), &context);
-    }
-    if (NULL == context.result && NULL != rlm->_submodes) {
+    CFRunLoopSourceRef found = rlm->_portToV1SourceMap ? (CFRunLoopSourceRef)CFDictionaryGetValue(rlm->_portToV1SourceMap, (const void *)(uintptr_t)port) : NULL;
+    if (NULL == found && NULL != rlm->_submodes) {
        CFIndex idx, cnt;
        for (idx = 0, cnt = CFArrayGetCount(rlm->_submodes); idx < cnt; idx++) {
-           CFRunLoopSourceRef source = NULL;
            CFStringRef modeName = (CFStringRef)CFArrayGetValueAtIndex(rlm->_submodes, idx);
            CFRunLoopModeRef subrlm;
             subrlm = __CFRunLoopFindMode(rl, modeName, false);
            if (NULL != subrlm) {
-               source = __CFRunLoopModeFindSourceForMachPort(rl, subrlm, port);
+               found = __CFRunLoopModeFindSourceForMachPort(rl, subrlm, port);
                __CFRunLoopModeUnlock(subrlm);
            }
-           if (NULL != source) {
-               context.result = source;
+           if (NULL != found) {
                break;
            }
        }
     }
-    return context.result;
+    return found;
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 // call with rl and rlm locked
 static CFRunLoopTimerRef __CFRunLoopModeFindTimerForMachPort(CFRunLoopModeRef rlm, __CFPort port) {
     CHECK_FOR_FORK();
@@ -806,7 +1012,7 @@ static void __CFRunLoopCleanseSources(const void *value, void *context) {
     const void **list, *buffer[256];
     if (NULL == rlm->_sources) return;
     cnt = CFSetGetCount(rlm->_sources);
-    list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0);
+    list = (const void **)((cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0));
     CFSetGetValues(rlm->_sources, list);
     for (idx = 0; idx < cnt; idx++) {
        CFRunLoopSourceRef rls = (CFRunLoopSourceRef)list[idx];
@@ -826,7 +1032,7 @@ static void __CFRunLoopDeallocateSources(const void *value, void *context) {
     const void **list, *buffer[256];
     if (NULL == rlm->_sources) return;
     cnt = CFSetGetCount(rlm->_sources);
-    list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0);
+    list = (const void **)((cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0));
     CFSetGetValues(rlm->_sources, list);
     for (idx = 0; idx < cnt; idx++) {
        CFRetain(list[idx]);
@@ -846,7 +1052,7 @@ static void __CFRunLoopDeallocateObservers(const void *value, void *context) {
     const void **list, *buffer[256];
     if (NULL == rlm->_observers) return;
     cnt = CFSetGetCount(rlm->_observers);
-    list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0);
+    list = (const void **)((cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0));
     CFSetGetValues(rlm->_observers, list);
     for (idx = 0; idx < cnt; idx++) {
        CFRetain(list[idx]);
@@ -866,7 +1072,7 @@ static void __CFRunLoopDeallocateTimers(const void *value, void *context) {
     const void **list, *buffer[256];
     if (NULL == rlm->_timers) return;
     cnt = CFSetGetCount(rlm->_timers);
-    list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0);
+    list = (const void **)((cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0));
     CFSetGetValues(rlm->_timers, list);
     for (idx = 0; idx < cnt; idx++) {
        CFRetain(list[idx]);
@@ -879,8 +1085,14 @@ static void __CFRunLoopDeallocateTimers(const void *value, void *context) {
     if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
 }
 
+CF_EXPORT pthread_t _CFMainPThread;
+CF_EXPORT CFRunLoopRef _CFRunLoopGet0b(pthread_t t);
+
 static void __CFRunLoopDeallocate(CFTypeRef cf) {
     CFRunLoopRef rl = (CFRunLoopRef)cf;
+
+    if (_CFRunLoopGet0b(_CFMainPThread) == cf) HALT;
+
     /* We try to keep the run loop in a valid state as long as possible,
        since sources may have non-retained references to the run loop.
        Another reason is that we don't want to lock the run loop for
@@ -897,6 +1109,14 @@ static void __CFRunLoopDeallocate(CFTypeRef cf) {
        CFSetApplyFunction(rl->_modes, (__CFRunLoopDeallocateTimers), rl);
     }
     __CFRunLoopLock(rl);
+    struct _block_item *item = rl->_blocks_head;
+    while (item) {
+       struct _block_item *curr = item;
+       item = item->_next;
+       CFRelease(curr->_mode);
+       Block_release(curr->_block);
+       free(curr);
+    }
     if (NULL != rl->_commonModeItems) {
        CFRelease(rl->_commonModeItems);
     }
@@ -908,7 +1128,12 @@ static void __CFRunLoopDeallocate(CFTypeRef cf) {
     }
     __CFPortFree(rl->_wakeUpPort);
     rl->_wakeUpPort = CFPORT_NULL;
+#if DEPLOYMENT_TARGET_WINDOWS
+    __CFPortFree(rl->_msgUpdatePort);
+    rl->_msgUpdatePort = CFPORT_NULL;
+#endif
     __CFRunLoopUnlock(rl);
+    memset((char *)cf + sizeof(CFRuntimeBase), 0x8C, sizeof(struct __CFRunLoop) - sizeof(CFRuntimeBase));
 }
 
 static const CFRuntimeClass __CFRunLoopModeClass = {
@@ -935,16 +1160,28 @@ static const CFRuntimeClass __CFRunLoopClass = {
     __CFRunLoopCopyDescription
 };
 
+static void __CFFinalizeRunLoop(uintptr_t data);
+
 __private_extern__ void __CFRunLoopInitialize(void) {
     __kCFRunLoopTypeID = _CFRuntimeRegisterClass(&__CFRunLoopClass);
     __kCFRunLoopModeTypeID = _CFRuntimeRegisterClass(&__CFRunLoopModeClass);
+#if DEPLOYMENT_TARGET_WINDOWS
+    __kCFRunLoopWakeUpMessage = RegisterWindowMessageW((LPCWSTR)L"CFRunLoopWakeup");
+    __kCFRunLoopV1SourceReadyMessage = RegisterWindowMessageW((LPCWSTR)L"CFRunLoopV1Ready");
+#endif
+#if DEPLOYMENT_TARGET_WINDOWS
+    if (~0 == __CFTSDKeyRunLoopKey) __CFTSDKeyRunLoopKey = TlsAlloc();
+#else
+    pthread_key_init_np(__CFTSDKeyRunLoop, NULL);
+    pthread_key_init_np(__CFTSDKeyRunLoopCntr, (void *)__CFFinalizeRunLoop);
+#endif
 }
  
 CFTypeID CFRunLoopGetTypeID(void) {
     return __kCFRunLoopTypeID;
 }
 
-static CFRunLoopRef __CFRunLoopCreate(void) {
+static CFRunLoopRef __CFRunLoopCreate(pthread_t t) {
     CFRunLoopRef loop = NULL;
     CFRunLoopModeRef rlm;
     uint32_t size = sizeof(struct __CFRunLoop) - sizeof(CFRuntimeBase);
@@ -956,52 +1193,49 @@ static CFRunLoopRef __CFRunLoopCreate(void) {
     CF_SPINLOCK_INIT_FOR_STRUCTS(loop->_lock);
     loop->_wakeUpPort = __CFPortAllocate();
     if (CFPORT_NULL == loop->_wakeUpPort) HALT;
-    loop->_commonModes = CFSetCreateMutable(CFGetAllocator(loop), 0, &kCFTypeSetCallBacks);
+#if DEPLOYMENT_TARGET_WINDOWS
+    loop->_msgUpdatePort = CFPORT_NULL;
+#endif
+    loop->_commonModes = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
     CFSetAddValue(loop->_commonModes, kCFRunLoopDefaultMode);
     loop->_commonModeItems = NULL;
     loop->_currentMode = NULL;
-    loop->_modes = CFSetCreateMutable(CFGetAllocator(loop), 0, &kCFTypeSetCallBacks);
+    loop->_modes = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
     _CFSetSetCapacity(loop->_modes, 10);
+    loop->_blocks_head = NULL;
+    loop->_blocks_tail = NULL;
     loop->_counterpart = NULL;
+    loop->_pthread = t;
     rlm = __CFRunLoopFindMode(loop, kCFRunLoopDefaultMode, true);
     if (NULL != rlm) __CFRunLoopModeUnlock(rlm);
     return loop;
 }
 
-static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl, CFStringRef modeName);
-
 static CFMutableDictionaryRef __CFRunLoops = NULL;
-static char setMainLoop = 0;
 static CFSpinLock_t loopsLock = CFSpinLockInit;
 
-// If this is called on a non-main thread, and the main thread pthread_t is passed in,
-// and this has not yet beed called on the main thread (since the last fork(), this will
-// produce a different run loop that will probably be tossed away eventually, than the
-// main thread run loop. There's nothing much we can do about that, without a call to
-// fetch the main thread's pthread_t from the pthreads subsystem.
-
+// should only be called by Foundation
 // t==0 is a synonym for "main thread" that always works
-static CFRunLoopRef _CFRunLoop0(pthread_t t) {
-    CFRunLoopRef loop;
+CF_EXPORT CFRunLoopRef _CFRunLoopGet0(pthread_t t) {
+    if (pthread_equal(t, kNilPthreadT)) {
+       t = _CFMainPThread;
+    }
     __CFSpinLock(&loopsLock);
     if (!__CFRunLoops) {
         __CFSpinUnlock(&loopsLock);
        CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
-       CFRunLoopRef mainLoop = __CFRunLoopCreate();
-       CFDictionarySetValue(dict, pthreadPointer(kNilPthreadT), mainLoop);
+       CFRunLoopRef mainLoop = __CFRunLoopCreate(_CFMainPThread);
+       CFDictionarySetValue(dict, pthreadPointer(_CFMainPThread), mainLoop);
        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) {
            CFRelease(dict);
        }
        CFRelease(mainLoop);
         __CFSpinLock(&loopsLock);
     }
-    if (pthread_main_np() && pthread_equal(t, pthread_self())) {
-       t = kNilPthreadT;
-    }
-    loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
+    CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
     if (!loop) {
         __CFSpinUnlock(&loopsLock);
-       CFRunLoopRef newLoop = __CFRunLoopCreate();
+       CFRunLoopRef newLoop = __CFRunLoopCreate(t);
         __CFSpinLock(&loopsLock);
        loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
        if (!loop) {
@@ -1010,67 +1244,148 @@ static CFRunLoopRef _CFRunLoop0(pthread_t t) {
        }
        CFRelease(newLoop);
     }
-    if (!setMainLoop && pthread_main_np()) {
-       if (pthread_equal(t, kNilPthreadT)) {
-           CFDictionarySetValue(__CFRunLoops, pthreadPointer(pthread_self()), loop);
-       } else {
-           CFRunLoopRef mainLoop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(kNilPthreadT));
-           CFDictionarySetValue(__CFRunLoops, pthreadPointer(pthread_self()), mainLoop);
-       }
-        setMainLoop = 1;
+    if (pthread_equal(t, pthread_self())) {
+#if DEPLOYMENT_TARGET_WINDOWS
+        TlsSetValue(__CFTSDKeyRunLoopKey, (LPVOID)(PTHREAD_DESTRUCTOR_ITERATIONS-1));
+#else
+        pthread_setspecific(__CFTSDKeyRunLoop, (void *)loop);
+        if (0 == pthread_getspecific(__CFTSDKeyRunLoopCntr)) {
+            pthread_setspecific(__CFTSDKeyRunLoopCntr, (void *)(PTHREAD_DESTRUCTOR_ITERATIONS-1));
+        }
+#endif
+#if DEPLOYMENT_TARGET_WINDOWS
+        // Install our message hook so we can spin the runloop
+        loop->_threadID = GetCurrentThreadId();
+        //#if MARRY_MESSAGE_QUEUE
+        if (__CFIsNonMachRunLoopMarryMsgQueueEnabled()) {
+#ifdef _DEBUG
+            __CFGetThreadSpecificData_inline()->_messageHook = SetWindowsHookExW(WH_GETMESSAGE, (HOOKPROC)pumpRunLoopFromMessageQueue, GetModuleHandleW((LPCWSTR)L"CoreFoundation_debug.dll"), loop->_threadID); 
+#else
+            __CFGetThreadSpecificData_inline()->_messageHook = SetWindowsHookExW(WH_GETMESSAGE, (HOOKPROC)pumpRunLoopFromMessageQueue, GetModuleHandleW((LPCWSTR)L"CoreFoundation.dll"), loop->_threadID); 
+#endif
+        }
+        //#endif
+#endif
     }
     __CFSpinUnlock(&loopsLock);
     return loop;
 }
 
-// Called for each thread as it exits
-static void __CFFinalizeRunLoop(void *arg) {
-    CFRunLoopRef rl = NULL;
+// should only be called by Foundation
+CFRunLoopRef _CFRunLoopGet0b(pthread_t t) {
+    if (pthread_equal(t, kNilPthreadT)) {
+       t = _CFMainPThread;
+    }
     __CFSpinLock(&loopsLock);
+    CFRunLoopRef loop = NULL;
     if (__CFRunLoops) {
-       rl = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(pthread_self()));
-       if (rl) CFRetain(rl);
-       CFDictionaryRemoveValue(__CFRunLoops, pthreadPointer(pthread_self()));
-       }
+        loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
+    }
     __CFSpinUnlock(&loopsLock);
-    if (rl && CFRunLoopGetMain() != rl) {
-        // purge all sources before deallocation
+    return loop;
+}
+
+static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl, CFStringRef modeName);
+
+// Called for each thread as it exits
+static void __CFFinalizeRunLoop(uintptr_t data) {
+    CFRunLoopRef rl = NULL;
+    if (data <= 1) {
+       __CFSpinLock(&loopsLock);
+       if (__CFRunLoops) {
+           rl = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(pthread_self()));
+           if (rl) CFRetain(rl);
+           CFDictionaryRemoveValue(__CFRunLoops, pthreadPointer(pthread_self()));
+       }
+       __CFSpinUnlock(&loopsLock);
+    } else {
+#if DEPLOYMENT_TARGET_WINDOWS
+        TlsSetValue(__CFTSDKeyRunLoopKey, (LPVOID)(data - 1));
+#else
+        pthread_setspecific(__CFTSDKeyRunLoopCntr, (void *)(data - 1));
+#endif
+    }
+    if (rl && CFRunLoopGetMain() != rl) { // protect against cooperative threads
+        if (NULL != rl->_counterpart) {
+            CFRelease(rl->_counterpart);
+           rl->_counterpart = NULL;
+        }
+       // purge all sources before deallocation
         CFArrayRef array = CFRunLoopCopyAllModes(rl);
         for (CFIndex idx = CFArrayGetCount(array); idx--;) {
-            CFStringRef modeName = CFArrayGetValueAtIndex(array, idx);
+            CFStringRef modeName = (CFStringRef)CFArrayGetValueAtIndex(array, idx);
             __CFRunLoopRemoveAllSources(rl, modeName);
         }
         __CFRunLoopRemoveAllSources(rl, kCFRunLoopCommonModes);
         CFRelease(array);
     }
-    if (rl) {
-       CFRelease(rl);
+    if (rl) CFRelease(rl);
+}
+
+pthread_t _CFRunLoopGet1(CFRunLoopRef rl) {
+    return rl->_pthread;
+}
+
+// should only be called by Foundation
+CF_EXPORT CFTypeRef _CFRunLoopGet2(CFRunLoopRef rl) {
+    CFTypeRef ret = NULL;
+    __CFSpinLock(&loopsLock);
+    if (NULL == rl->_counterpart) {
+        Class cls = (Class)objc_lookUpClass("NSRunLoop");
+       if (cls) {
+            char hasMethod;
+            CF_OBJC_CALL1(char, hasMethod, cls, "respondsToSelector:", sel_registerName("_new:"));
+            if (hasMethod) {
+                void *ns;
+               CF_OBJC_CALL1(void *, ns, cls, "_new:", rl);
+                rl->_counterpart = ns ? CFRetain(ns) : NULL;
+            }
+        }
     }
+    ret = rl->_counterpart;
+    __CFSpinUnlock(&loopsLock);
+    return ret;
 }
 
-__private_extern__ void _CFRunLoop1(void) { __CFFinalizeRunLoop(0); }
+// should only be called by Foundation
+CF_EXPORT CFTypeRef _CFRunLoopGet2b(CFRunLoopRef rl) {
+    return rl->_counterpart;
+}
 
+#if DEPLOYMENT_TARGET_MACOSX
 void _CFRunLoopSetCurrent(CFRunLoopRef rl) {
+    if (pthread_main_np()) return;
     CFRunLoopRef currentLoop = CFRunLoopGetCurrent();
     if (rl != currentLoop) {
+        CFRetain(currentLoop); // avoid a deallocation of the currentLoop inside the lock
         __CFSpinLock(&loopsLock);
        if (rl) {
            CFDictionarySetValue(__CFRunLoops, pthreadPointer(pthread_self()), rl);
        } else {
            CFDictionaryRemoveValue(__CFRunLoops, pthreadPointer(pthread_self()));
-    }
-    __CFSpinUnlock(&loopsLock);
+       }
+        __CFSpinUnlock(&loopsLock);
+       CFRelease(currentLoop);
+        pthread_setspecific(__CFTSDKeyRunLoop, NULL);
+        pthread_setspecific(__CFTSDKeyRunLoopCntr, 0);
     }
 }
+#endif
 
 CFRunLoopRef CFRunLoopGetMain(void) {
     CHECK_FOR_FORK();
-    return _CFRunLoop0(kNilPthreadT);
+    static CFRunLoopRef __main = NULL; // no retain needed
+    if (!__main) __main = _CFRunLoopGet0(_CFMainPThread); // no CAS needed
+    return __main;
 }
 
 CFRunLoopRef CFRunLoopGetCurrent(void) {
     CHECK_FOR_FORK();
-    return _CFRunLoop0(pthread_self());
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    CFRunLoopRef rl = (CFRunLoopRef)pthread_getspecific(__CFTSDKeyRunLoop);
+    if (rl) return rl;
+#endif
+    return _CFRunLoopGet0(pthread_self());
 }
 
 CFStringRef CFRunLoopCopyCurrentMode(CFRunLoopRef rl) {
@@ -1078,7 +1393,7 @@ CFStringRef CFRunLoopCopyCurrentMode(CFRunLoopRef rl) {
     CFStringRef result = NULL;
     __CFRunLoopLock(rl);
     if (NULL != rl->_currentMode) {
-       result = CFRetain(rl->_currentMode->_name);
+       result = (CFStringRef)CFRetain(rl->_currentMode->_name);
     }
     __CFRunLoopUnlock(rl);
     return result;
@@ -1139,21 +1454,13 @@ static void __CFRunLoopRemoveItemFromCommonModes(const void *value, void *ctx) {
     }
 }
 
-Boolean _CFRunLoop01(CFRunLoopRef rl, CFStringRef modeName) {
+CF_EXPORT Boolean _CFRunLoop01(CFRunLoopRef rl, CFStringRef modeName) {
     __CFRunLoopLock(rl);
     Boolean present = CFSetContainsValue(rl->_commonModes, modeName);
     __CFRunLoopUnlock(rl);
     return present; 
 }
 
-void *_CFRunLoop02(CFRunLoopRef rl) {
-    return rl->_counterpart;
-}
-
-void _CFRunLoop03(CFRunLoopRef rl, void *ns) {
-    rl->_counterpart = ns;
-}
-
 void CFRunLoopAddCommonMode(CFRunLoopRef rl, CFStringRef modeName) {
     CHECK_FOR_FORK();
     if (__CFRunLoopIsDeallocating(rl)) return;
@@ -1173,6 +1480,52 @@ void CFRunLoopAddCommonMode(CFRunLoopRef rl, CFStringRef modeName) {
     }
 }
 
+static Boolean __CFRunLoopDoBlocks(CFRunLoopRef rl, CFStringRef curMode) { // Call with rl locked
+    if (!rl->_blocks_head) return false;
+    if (!curMode) return false;
+    Boolean did = false;
+    CFAbsoluteTime deadline = CFAbsoluteTimeGetCurrent() + 0.0009765625;
+    struct _block_item *head = rl->_blocks_head;
+    struct _block_item *tail = rl->_blocks_tail;
+    rl->_blocks_head = NULL;
+    rl->_blocks_tail = NULL;
+    CFSetRef commonModes = rl->_commonModes;
+    __CFRunLoopUnlock(rl);
+    struct _block_item *prev = NULL;
+    struct _block_item *item = head;
+    while (item && CFAbsoluteTimeGetCurrent() < deadline) {
+        struct _block_item *curr = item;
+        item = item->_next;
+       Boolean doit = false;
+       if (CFStringGetTypeID() == CFGetTypeID(curr->_mode)) {
+           doit = CFEqual(curr->_mode, curMode) || (CFEqual(curr->_mode, kCFRunLoopCommonModes) && CFSetContainsValue(commonModes, curMode));
+        } else {
+           doit = CFSetContainsValue((CFSetRef)curr->_mode, curMode) || (CFSetContainsValue((CFSetRef)curr->_mode, kCFRunLoopCommonModes) && CFSetContainsValue(commonModes, curMode));
+       }
+       if (!doit) prev = curr;
+       if (doit) {
+           if (prev) prev->_next = item;
+           if (curr == head) head = item;
+           if (curr == tail) tail = prev;
+           void (^block)(void) = curr->_block;
+            CFRelease(curr->_mode);
+            free(curr);
+           if (doit) {
+               block();        // rl is not locked, mode is not locked
+               did = true;
+           }
+            Block_release(block); // do this before relocking to prevent deadlocks where some yahoo wants to run the run loop reentrantly from their dealloc
+       }
+    }
+    __CFRunLoopLock(rl);
+    if (head) {
+       tail->_next = rl->_blocks_head;
+       rl->_blocks_head = head;
+        if (!rl->_blocks_tail) rl->_blocks_tail = tail;
+    }
+    return did;
+}
+
 static CFComparisonResult __CFRunLoopObserverQSortComparator(const void *val1, const void *val2, void *context) {
     CFRunLoopObserverRef o1 = *((CFRunLoopObserverRef *)val1);
     CFRunLoopObserverRef o2 = *((CFRunLoopObserverRef *)val2);
@@ -1202,8 +1555,8 @@ static void __CFRunLoopDoObservers(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunL
     if (NULL != rlm->_observers) {
        cnt = CFSetGetCount(rlm->_observers);
        if (0 < cnt) {
-           CFRunLoopObserverRef buffer[(cnt <= 1024) ? cnt : 1];
-           CFRunLoopObserverRef *collectedObservers = (cnt <= 1024) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(CFRunLoopObserverRef), 0);
+           STACK_BUFFER_DECL(CFRunLoopObserverRef, buffer, (cnt <= 1024) ? cnt : 1);
+           CFRunLoopObserverRef *collectedObservers = (CFRunLoopObserverRef *)((cnt <= 1024) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(CFRunLoopObserverRef), 0));
            CFSetGetValues(rlm->_observers, (const void **)collectedObservers);
            for (idx = 0; idx < cnt; idx++) {
                CFRunLoopObserverRef rlo = collectedObservers[idx];
@@ -1314,6 +1667,9 @@ static Boolean __CFRunLoopDoSources0(CFRunLoopRef rl, CFRunLoopModeRef rlm, Bool
        if (CFGetTypeID(sources) == __kCFRunLoopSourceTypeID) {
            CFRunLoopSourceRef rls = (CFRunLoopSourceRef)sources;
            __CFRunLoopSourceLock(rls);
+#if DEPLOYMENT_TARGET_WINDOWS
+            if (__CFRunLoopSourceIsSignaled(rls)) {
+#endif
            __CFRunLoopSourceUnsetSignaled(rls);
            if (__CFIsValid(rls)) {
                __CFRunLoopSourceUnlock(rls);
@@ -1325,12 +1681,20 @@ static Boolean __CFRunLoopDoSources0(CFRunLoopRef rl, CFRunLoopModeRef rlm, Bool
            } else {
                __CFRunLoopSourceUnlock(rls);
            }
+#if DEPLOYMENT_TARGET_WINDOWS
+            } else {
+                __CFRunLoopSourceUnlock(rls);
+            }
+#endif
        } else {
-           cnt = CFArrayGetCount(sources);
+           cnt = CFArrayGetCount((CFArrayRef)sources);
            CFArraySortValues((CFMutableArrayRef)sources, CFRangeMake(0, cnt), (__CFRunLoopSourceComparator), NULL);
            for (idx = 0; idx < cnt; idx++) {
-               CFRunLoopSourceRef rls = (CFRunLoopSourceRef)CFArrayGetValueAtIndex(sources, idx);
+               CFRunLoopSourceRef rls = (CFRunLoopSourceRef)CFArrayGetValueAtIndex((CFArrayRef)sources, idx);
                __CFRunLoopSourceLock(rls);
+#if DEPLOYMENT_TARGET_WINDOWS
+                if (__CFRunLoopSourceIsSignaled(rls)) {
+#endif
                __CFRunLoopSourceUnsetSignaled(rls);
                if (__CFIsValid(rls)) {
                    __CFRunLoopSourceUnlock(rls);
@@ -1342,6 +1706,11 @@ static Boolean __CFRunLoopDoSources0(CFRunLoopRef rl, CFRunLoopModeRef rlm, Bool
                } else {
                    __CFRunLoopSourceUnlock(rls);
                }
+#if DEPLOYMENT_TARGET_WINDOWS
+                } else {
+                    __CFRunLoopSourceUnlock(rls);
+                }
+#endif
                if (stopAfterHandle && sourceHandled) {
                    break;
                }
@@ -1355,7 +1724,7 @@ static Boolean __CFRunLoopDoSources0(CFRunLoopRef rl, CFRunLoopModeRef rlm, Bool
 
 // msg, size and reply are unused on Windows
 static Boolean __CFRunLoopDoSource1(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopSourceRef rls
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
                                     , mach_msg_header_t *msg, CFIndex size, mach_msg_header_t **reply
 #endif
                                     ) {        /* DOES CALLOUT */
@@ -1370,7 +1739,7 @@ static Boolean __CFRunLoopDoSource1(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRun
        __CFRunLoopSourceUnsetSignaled(rls);
        __CFRunLoopSourceUnlock(rls);
        if (NULL != rls->_context.version1.perform) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
            *reply = rls->_context.version1.perform(msg, size, kCFAllocatorSystemDefault, rls->_context.version1.info); /* CALLOUT */
            CHECK_FOR_FORK();
 #else
@@ -1391,25 +1760,41 @@ static Boolean __CFRunLoopDoSource1(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRun
     return sourceHandled;
 }
 
+// mode is locked on entry and exit
 static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopTimerRef rlt) {      /* DOES CALLOUT */
-    Boolean timerHandled = false;
+    Boolean timerHandled = false, timerEarly = false;
     int64_t oldFireTSR = 0;
 
     /* Fire a timer */
     CFRetain(rlt);
     __CFRunLoopModeUnlock(rlm);
-    __CFRunLoopTimerLock(rlt);
     if (__CFIsValid(rlt) && !__CFRunLoopTimerIsFiring(rlt)) {
+        void *context_info = NULL;
+        void (*context_release)(const void *) = NULL;
+        if (rlt->_context.retain) {
+            context_info = (void *)rlt->_context.retain(rlt->_context.info);
+            context_release = rlt->_context.release;
+        } else {
+            context_info = rlt->_context.info;
+        }
        __CFRunLoopTimerUnsetDidFire(rlt);
        __CFRunLoopTimerSetFiring(rlt);
-       __CFRunLoopTimerUnlock(rlt);
+//CFLog(4, CFSTR("Firing timer %p from loop %p in mode %@"), rlt, rl, rlm->_name);
        __CFRunLoopTimerFireTSRLock();
        oldFireTSR = rlt->_fireTSR;
        __CFRunLoopTimerFireTSRUnlock();
-       rlt->_callout(rlt, rlt->_context.info); /* CALLOUT */
-       CHECK_FOR_FORK();
+       if (0 && CFAbsoluteTimeGetCurrent() < rlt->_nextFireDate) { // not enabled at this time -- causes trouble when clock goes backwards
+           timerEarly = true;
+       } else {
+           rlt->_callout(rlt, context_info);   /* CALLOUT */
+           CHECK_FOR_FORK();
+           timerHandled = true;
+        }
+//CFLog(4, CFSTR("Done firing timer %p from loop %p in mode %@"), rlt, rl, rlm->_name);
        __CFRunLoopTimerUnsetFiring(rlt);
-       timerHandled = true;
+        if (context_release) {
+            context_release(context_info);
+        }
     } else {
        // If the timer fires while it is firing in a higher activiation,
        // it is not allowed to fire, but we have to remember that fact.
@@ -1418,24 +1803,22 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo
        // fired (this firing which is being skipped, say) and the timer
        // will permanently stop if we completely drop this firing.
        if (__CFRunLoopTimerIsFiring(rlt)) __CFRunLoopTimerSetDidFire(rlt);
-       __CFRunLoopTimerUnlock(rlt);
     }
     if (__CFIsValid(rlt) && timerHandled) {
-       if (0 == rlt->_intervalTSR) {
+       if (0.0 == rlt->_interval) {
            CFRunLoopTimerInvalidate(rlt);      /* DOES CALLOUT */
        } else {
            /* This is just a little bit tricky: we want to support calling
             * CFRunLoopTimerSetNextFireDate() from within the callout and
             * honor that new time here if it is a later date, otherwise
             * it is completely ignored. */
-           int64_t currentFireTSR;
            __CFRunLoopTimerFireTSRLock();
-           currentFireTSR = rlt->_fireTSR;
+           int64_t currentFireTSR = rlt->_fireTSR;
            if (oldFireTSR < currentFireTSR) {
                /* Next fire TSR was set, and set to a date after the previous
                 * fire date, so we honor it. */
                if (__CFRunLoopTimerDidFire(rlt)) {
-                   __CFRunLoopTimerRescheduleWithAllModes(rlt, rl);
+                   __CFRunLoopTimerRescheduleWithAllModes(rlt);
                    __CFRunLoopTimerUnsetDidFire(rlt);
                }
            } else {
@@ -1449,11 +1832,25 @@ static Boolean __CFRunLoopDoTimer(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLo
                    }
                }
                rlt->_fireTSR = currentFireTSR;
-               __CFRunLoopTimerRescheduleWithAllModes(rlt, rl);
+               __CFRunLoopTimerRescheduleWithAllModes(rlt);
            }
            __CFRunLoopTimerFireTSRUnlock();
        }
     }
+    if (__CFIsValid(rlt) && timerEarly) {
+       int64_t now2 = (int64_t)mach_absolute_time();
+       CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent();
+       __CFRunLoopTimerFireTSRLock();
+       if (rlt->_nextFireDate < now1) {
+           rlt->_fireTSR = now2;
+       } else if (now1 + __CFTSRToTimeInterval(LLONG_MAX) < rlt->_nextFireDate) {
+           rlt->_fireTSR = LLONG_MAX;
+       } else {
+           rlt->_fireTSR = now2 + __CFTimeIntervalToTSR(rlt->_nextFireDate - now1);
+       }
+       __CFRunLoopTimerRescheduleWithAllModes(rlt);
+       __CFRunLoopTimerFireTSRUnlock();
+    }
     CFRelease(rlt);
     __CFRunLoopModeLock(rlm);
     return timerHandled;
@@ -1465,7 +1862,7 @@ CF_EXPORT Boolean _CFRunLoopFinished(CFRunLoopRef rl, CFStringRef modeName) {
     Boolean result = false;
     __CFRunLoopLock(rl);
     rlm = __CFRunLoopFindMode(rl, modeName, false);
-    if (NULL == rlm || __CFRunLoopModeIsEmpty(rl, rlm)) {
+    if (NULL == rlm || __CFRunLoopModeIsEmpty(rl, rlm, NULL)) {
        result = true;
     }
     __CFRunLoopUnlock(rl);
@@ -1481,7 +1878,7 @@ static void __CFRunLoopModeAddPortsToPortSet(CFRunLoopRef rl, CFRunLoopModeRef r
     // Timers and version 1 sources go into the portSet currently
     if (NULL != rlm->_sources) {
        cnt = CFSetGetCount(rlm->_sources);
-       list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0);
+       list = (const void **)((cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0));
        CFSetGetValues(rlm->_sources, list);
        for (idx = 0; idx < cnt; idx++) {
            CFRunLoopSourceRef rls = (CFRunLoopSourceRef)list[idx];
@@ -1494,7 +1891,7 @@ static void __CFRunLoopModeAddPortsToPortSet(CFRunLoopRef rl, CFRunLoopModeRef r
        }
        if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
     }
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (NULL != rlm->_timers) {
        cnt = CFSetGetCount(rlm->_timers);
        list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0);
@@ -1522,16 +1919,10 @@ static void __CFRunLoopModeAddPortsToPortSet(CFRunLoopRef rl, CFRunLoopModeRef r
 
 static __CFPortSet _LastMainWaitSet = 0;
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 // return NO if we're the main runloop and there are no messages waiting on the port set
 int _CFRunLoopInputsReady(void) {
     CHECK_FOR_FORK();
-    // XXX_PCB:  the following 2 lines aren't safe to call during GC, because another
-    // thread may have entered CFRunLoopGetMain(), which grabs a spink lock, and then
-    // is suspended by the GC. We can check for the main thread more directly
-    // by calling pthread_main_np().
-    // CFRunLoopRef current = CFRunLoopGetMain()
-    // if (current != CFRunLoopGetMain()) return true;
-#if DEPLOYMENT_TARGET_MACOSX
     if (!pthread_main_np()) return true;
 
     // XXX_PCB:  can't be any messages waiting if the wait set is NULL.
@@ -1548,9 +1939,9 @@ int _CFRunLoopInputsReady(void) {
     kern_return_t ret = mach_msg(&msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT | MACH_RCV_LARGE, 0, msg.msgh_size, _LastMainWaitSet, 0, MACH_PORT_NULL);
     
     return (MACH_RCV_TOO_LARGE == ret);
-#endif
     return true;
 }
+#endif
 
 #if 0
 static void print_msg_scan_header(void) {
@@ -1612,17 +2003,25 @@ static void mach_msg_scan(mach_msg_header_t *msg, int clean) {
 }
 #endif
 
+static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode, Boolean waitIfEmpty) __attribute__((noinline));
+#if DEPLOYMENT_TARGET_WINDOWS
+static int64_t __CFRunLoopGetNextTimerFireTSR(CFRunLoopRef rl, CFRunLoopModeRef rlm);
+#endif
+
 /* rl is unlocked, rlm locked on entrance and exit */
-static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, Boolean waitIfEmpty) {  /* DOES CALLOUT */
+static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode, Boolean waitIfEmpty) {  /* DOES CALLOUT */
     int64_t termTSR;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     mach_port_name_t timeoutPort = MACH_PORT_NULL;
-    Boolean timeoutPortAdded = false;
+    mach_port_name_t dispatchPort = MACH_PORT_NULL;
+    Boolean libdispatchQSafe = pthread_main_np() && ((HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && NULL == previousMode) || (!HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && 0 == pthread_getspecific(__CFTSDKeyIsInGCDMainQ)));
+    if (libdispatchQSafe && (CFRunLoopGetMain() == rl) && CFSetContainsValue(rl->_commonModes, rlm->_name)) dispatchPort = _dispatch_get_main_queue_port_4CF();
 #endif
     Boolean poll = false;
     Boolean firstPass = true;
 
     if (__CFRunLoopIsStopped(rl)) {
+        __CFRunLoopUnsetStopped(rl);
        return kCFRunLoopRunStopped;
     } else if (rlm->_stopped) {
        rlm->_stopped = false;
@@ -1630,11 +2029,11 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
     }
     if (seconds <= 0.0) {
        termTSR = 0;
-    } else if (3.1556952e+9 < seconds) {
+    } else if (TIMER_INTERVAL_LIMIT < seconds) {
        termTSR = LLONG_MAX;
     } else {
        termTSR = (int64_t)__CFReadTSR() + __CFTimeIntervalToTSR(seconds);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        timeoutPort = mk_timer_create();
        mk_timer_arm(timeoutPort, __CFUInt64ToAbsoluteTime(termTSR));
 #endif
@@ -1645,30 +2044,47 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
     if (rl == CFRunLoopGetMain()) _LastMainWaitSet = CFPORT_NULL;
     for (;;) {
         __CFPortSet waitSet = CFPORT_NULL;
-        waitSet = CFPORT_NULL;
         Boolean destroyWaitSet = false;
         CFRunLoopSourceRef rls;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        mach_msg_header_t *msg;
        kern_return_t ret;
-        uint8_t buffer[1024 + 80] = {0};       // large enough for 1k of inline payload; must be zeroed for GC
+        uint8_t buffer[2048];
 #else
         CFArrayRef timersToCall = NULL;
 #endif
        int32_t returnValue = 0;
-       Boolean sourceHandledThisLoop = false;
-
-       __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
-       __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
+        Boolean sourceHandledThisLoop = false;
+
+       // Do not handle blocks here, as there is already a handling at
+        // the end of this loop, and that just makes for two handlings
+        // in a row when the loop cycles.
+        if (rlm->_observerMask & kCFRunLoopBeforeTimers || rlm->_submodes) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
+       if (rlm->_observerMask & kCFRunLoopBeforeSources || rlm->_submodes) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
+       if (rl->_blocks_head) {
+           __CFRunLoopModeUnlock(rlm);
+            __CFRunLoopLock(rl);
+           __CFRunLoopDoBlocks(rl, rlm->_name);
+            __CFRunLoopModeLock(rlm);
+           __CFRunLoopUnlock(rl);
+       }
 
-       sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm, stopAfterHandle);
+        sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm, stopAfterHandle) || sourceHandledThisLoop;
 
        if (sourceHandledThisLoop) {
            poll = true;
+           if (rl->_blocks_head) {
+               __CFRunLoopModeUnlock(rlm);
+               __CFRunLoopLock(rl);
+               __CFRunLoopDoBlocks(rl, rlm->_name);
+               __CFRunLoopModeLock(rlm);
+               __CFRunLoopUnlock(rl);
+           }
        }
 
        if (!poll) {
-           __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
+           if (rlm->_observerMask & kCFRunLoopBeforeWaiting || rlm->_submodes) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
+           // do not do any user callouts after this point (after notifying of sleeping)
            __CFRunLoopSetSleeping(rl);
        }
        if (NULL != rlm->_submodes) {
@@ -1680,37 +2096,45 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
            __CFRunLoopModeLock(rlm);
            __CFRunLoopModeAddPortsToPortSet(rl, rlm, waitSet);
            __CFRunLoopUnlock(rl);
-#if DEPLOYMENT_TARGET_MACOSX
-            if (CFPORT_NULL != timeoutPort) {
-               __CFPortSetInsert(timeoutPort, waitSet);
-           }
-#endif
             destroyWaitSet = true;
        } else {
            waitSet = rlm->_portSet;
-#if DEPLOYMENT_TARGET_MACOSX
-           if (!timeoutPortAdded && CFPORT_NULL != timeoutPort) {
-               __CFPortSetInsert(timeoutPort, waitSet);
-               timeoutPortAdded = true;
-           }
-#endif
        }
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+       if (CFPORT_NULL != timeoutPort) {
+            __CFPortSetInsert(timeoutPort, waitSet);
+       }
+       if (CFPORT_NULL != dispatchPort) {
+            __CFPortSetInsert(dispatchPort, waitSet);
+       }
+#endif
        if (rl == CFRunLoopGetMain()) _LastMainWaitSet = waitSet;
        __CFRunLoopModeUnlock(rlm);
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+        if (kCFUseCollectableAllocator && !poll) {
+           memset(buffer, 0, sizeof(buffer));
+           objc_clear_stack(0);
+       }
+        
         msg = (mach_msg_header_t *)buffer;
        msg->msgh_size = sizeof(buffer);
 
+//static uint64_t _last_value = 0;
+//uint64_t new_val = mach_absolute_time();
+//printf(". %d before %qd (%qd)\n", getpid(), new_val, new_val - _last_value);
+//_last_value = new_val;
+
        /* In that sleep of death what nightmares may come ... */
-       try_receive:
+       try_receive:;
        msg->msgh_bits = 0;
        msg->msgh_local_port = waitSet;
        msg->msgh_remote_port = MACH_PORT_NULL;
        msg->msgh_id = 0;
-       ret = mach_msg(msg, MACH_RCV_MSG|MACH_RCV_LARGE|(poll ? MACH_RCV_TIMEOUT : 0)|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT), 0, msg->msgh_size, waitSet, 0, MACH_PORT_NULL);
+       ret = mach_msg(msg, MACH_RCV_MSG|MACH_RCV_LARGE|(poll ? MACH_RCV_TIMEOUT : 0)|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV), 0, msg->msgh_size, waitSet, 0, MACH_PORT_NULL);
+
        if (MACH_RCV_TOO_LARGE == ret) {
-           uint32_t newSize = round_msg(msg->msgh_size) + sizeof(mach_msg_audit_trailer_t);
+           uint32_t newSize = round_msg(msg->msgh_size + MAX_TRAILER_SIZE);
            if (msg == (mach_msg_header_t *)buffer) msg = NULL;
            msg = CFAllocatorReallocate(kCFAllocatorSystemDefault, msg, newSize, 0);
            msg->msgh_size = newSize;
@@ -1722,7 +2146,10 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
        } else if (MACH_MSG_SUCCESS != ret) {
            HALT;
        }
-#elif defined(__WIN32__)
+//new_val = mach_absolute_time();
+//printf(". %d after %qd (%qd)\n", getpid(), new_val, new_val - _last_value);
+//_last_value = new_val;
+#elif DEPLOYMENT_TARGET_WINDOWS
         DWORD waitResult = WAIT_TIMEOUT;
         HANDLE handleBuf[MAXIMUM_WAIT_OBJECTS];
         HANDLE *handles;
@@ -1740,45 +2167,53 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
         }
         // should msgQMask be an OR'ing of this and all submodes' masks?
        if (0 == GetQueueStatus(rlm->_msgQMask)) {
-            DWORD timeout;
-            if (poll)
-                timeout = 0;
-            else {
+           DWORD timeout;
+           if (poll)
+               timeout = 0;
+           else {
+               int64_t nextStop;
                 __CFRunLoopModeLock(rlm);
-                int64_t nextStop = __CFRunLoopGetNextTimerFireTSR(rl, rlm);
-                if (nextStop <= 0)
-                    nextStop = termTSR;
-                else if (nextStop > termTSR)
-                    nextStop = termTSR;
-                // else the next stop is dictated by the next timer
-                int64_t timeoutTSR = nextStop - __CFReadTSR();
-                if (timeoutTSR < 0)
-                    timeout = 0;
-                else {
-                    CFTimeInterval timeoutCF = __CFTSRToTimeInterval(timeoutTSR) * 1000;
-                    if (timeoutCF > MAXDWORD)
-                        timeout = INFINITE;
-                    else
-                        timeout = timeoutCF;
-                }
-            }
-        if (_LogCFRunLoop) { CFLog(kCFLogLevelDebug, CFSTR("%p (%s)- about to wait for %d objects, wakeupport is %p"), CFRunLoopGetCurrent(), *_CFGetProgname(), handleCount, rl->_wakeUpPort); }
-        if (_LogCFRunLoop) { CFLog(kCFLogLevelDebug, CFSTR("All RLM sources = %@"), rlm->_sources); }
-        waitResult = MsgWaitForMultipleObjects(__CFMin(handleCount, MAXIMUM_WAIT_OBJECTS), handles, false, timeout, rlm->_msgQMask);
-        if (_LogCFRunLoop) { CFLog(kCFLogLevelDebug, CFSTR("%p (%s)- waitResult was %d"), CFRunLoopGetCurrent(), *_CFGetProgname(), waitResult); }
+                nextStop = __CFRunLoopGetNextTimerFireTSR(rl, rlm);
+               if (nextStop <= 0)
+                   nextStop = termTSR;
+               else if (nextStop > termTSR)
+                   nextStop = termTSR;
+               // else the next stop is dictated by the next timer
+               int64_t timeoutTSR = nextStop - __CFReadTSR();
+               if (timeoutTSR < 0)
+                   timeout = 0;
+               else {
+                   CFTimeInterval timeoutCF = __CFTSRToTimeInterval(timeoutTSR) * 1000;
+                   if (timeoutCF > MAXDWORD)
+                       timeout = INFINITE;
+                   else
+                       timeout = (DWORD)timeoutCF;
+               }
+           }
+            waitResult = WaitForMultipleObjects(__CFMin(handleCount, MAXIMUM_WAIT_OBJECTS), handles, false, timeout);
        }
        ResetEvent(rl->_wakeUpPort);
 #endif
+       __CFRunLoopLock(rl);
+       __CFRunLoopModeLock(rlm);
+       __CFRunLoopUnlock(rl);
        if (destroyWaitSet) {
             __CFPortSetFree(waitSet);
            if (rl == CFRunLoopGetMain()) _LastMainWaitSet = 0;
+       } else {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+           if (CFPORT_NULL != timeoutPort) {
+               __CFPortSetRemove(timeoutPort, waitSet);
+           }
+           if (CFPORT_NULL != dispatchPort) {
+               __CFPortSetRemove(dispatchPort, waitSet);
+           }
+#endif
        }
-       __CFRunLoopLock(rl);
-       __CFRunLoopModeLock(rlm);
-       __CFRunLoopUnlock(rl);
+
        if (!poll) {
            __CFRunLoopUnsetSleeping(rl);
-           __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
+           if (rlm->_observerMask & kCFRunLoopAfterWaiting || rlm->_submodes) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
        }
        poll = false;
        __CFRunLoopModeUnlock(rlm);
@@ -1786,18 +2221,17 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
        __CFRunLoopModeLock(rlm);
 
         __CFPort livePort = CFPORT_NULL;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        if (NULL != msg) {
             livePort = msg->msgh_local_port;
         }
-#elif defined(__WIN32__)
+#elif DEPLOYMENT_TARGET_WINDOWS
         CFAssert2(waitResult != WAIT_FAILED, __kCFLogAssertion, "%s(): error %d from MsgWaitForMultipleObjects", __PRETTY_FUNCTION__, GetLastError());
         if (waitResult == WAIT_TIMEOUT) {
             // do nothing, just return to caller
         } else if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0+handleCount) {
-            // a handle was signalled
+            // a handle was signaled
             livePort = handles[waitResult-WAIT_OBJECT_0];
-            if (_LogCFRunLoop) { CFLog(kCFLogLevelDebug, CFSTR("%p (%s)- Resetting event %p"), CFRunLoopGetCurrent(), *_CFGetProgname(), livePort); }
         } else if (waitResult == WAIT_OBJECT_0+handleCount) {
             // windows message received - the CFWindowsMessageQueue will pick this up when
             // the v0 RunLoopSources get their chance
@@ -1816,13 +2250,23 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
            __CFRunLoopUnlock(rl);
        } else if (livePort == rl->_wakeUpPort) {
            // wakeup
-               if (_LogCFRunLoop) { CFLog(kCFLogLevelDebug, CFSTR("wakeupPort was signalled")); }        
-           __CFRunLoopUnlock(rl);
+               if (_LogCFRunLoop) { CFLog(kCFLogLevelDebug, CFSTR("wakeupPort was signalled")); }
+           __CFRunLoopUnlock(rl); // leave run loop unlocked
        }
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        else if (livePort == timeoutPort) {
            returnValue = kCFRunLoopRunTimedOut;
            __CFRunLoopUnlock(rl);
+       } else if (dispatchPort == livePort) {
+           __CFRunLoopModeUnlock(rlm);
+           __CFRunLoopUnlock(rl);
+            pthread_setspecific(__CFTSDKeyIsInGCDMainQ, (void *)3);
+           _dispatch_main_queue_callback_4CF(msg);
+           sourceHandledThisLoop = true;
+            pthread_setspecific(__CFTSDKeyIsInGCDMainQ, (void *)0);
+           __CFRunLoopLock(rl);
+           __CFRunLoopModeLock(rlm);
+           __CFRunLoopUnlock(rl); // leave run loop unlocked
        } else if (NULL != (rls = __CFRunLoopModeFindSourceForMachPort(rl, rlm, livePort))) {
            mach_msg_header_t *reply = NULL;
            __CFRunLoopUnlock(rl);
@@ -1855,9 +2299,22 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
        }
 #endif
 
-       __CFRunLoopModeUnlock(rlm);     // locks must be taken in order
-       __CFRunLoopLock(rl);
-       __CFRunLoopModeLock(rlm);
+#if DEPLOYMENT_TARGET_WINDOWS
+        if (NULL != timersToCall) {
+            int i;
+            for (i = CFArrayGetCount(timersToCall)-1; i >= 0; i--)
+                __CFRunLoopDoTimer(rl, rlm, (CFRunLoopTimerRef)CFArrayGetValueAtIndex(timersToCall, i));
+            CFRelease(timersToCall);
+        }
+#endif
+        
+       if (rl->_blocks_head) {
+           __CFRunLoopModeUnlock(rlm); // locks must be taken in order
+           __CFRunLoopLock(rl);
+           __CFRunLoopDoBlocks(rl, rlm->_name);
+           __CFRunLoopModeLock(rlm);
+           __CFRunLoopUnlock(rl);
+       }
        if (sourceHandledThisLoop && stopAfterHandle) {
            returnValue = kCFRunLoopRunHandledSource;
         // If we're about to timeout, but we just did a zero-timeout poll that only found our own
@@ -1866,18 +2323,17 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
         } else if (0 != returnValue || (uint64_t)termTSR <= __CFReadTSR()) {
            returnValue = kCFRunLoopRunTimedOut;
        } else if (__CFRunLoopIsStopped(rl)) {
+            __CFRunLoopUnsetStopped(rl);
            returnValue = kCFRunLoopRunStopped;
        } else if (rlm->_stopped) {
            rlm->_stopped = false;
            returnValue = kCFRunLoopRunStopped;
-       } else if (!waitIfEmpty && __CFRunLoopModeIsEmpty(rl, rlm)) {
+       } else if (!waitIfEmpty && __CFRunLoopModeIsEmpty(rl, rlm, previousMode)) {
            returnValue = kCFRunLoopRunFinished;
        }
-       __CFRunLoopUnlock(rl);
        if (0 != returnValue) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
            if (MACH_PORT_NULL != timeoutPort) {
-               if (!destroyWaitSet) __CFPortSetRemove(timeoutPort, waitSet);
                mk_timer_destroy(timeoutPort);
            }
 #endif
@@ -1892,30 +2348,54 @@ SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterva
     if (__CFRunLoopIsDeallocating(rl)) return kCFRunLoopRunFinished;
     __CFRunLoopLock(rl);
     CFRunLoopModeRef currentMode = __CFRunLoopFindMode(rl, modeName, false);
-    if (NULL == currentMode || __CFRunLoopModeIsEmpty(rl, currentMode)) {
+    if (NULL == currentMode || __CFRunLoopModeIsEmpty(rl, currentMode, rl->_currentMode)) {
+       Boolean did = false;
        if (currentMode) __CFRunLoopModeUnlock(currentMode);
+#if 0
+       if (rl->_blocks_head) {
+           __CFRunLoopDoBlocks(rl, modeName);
+       }
+#endif
        __CFRunLoopUnlock(rl);
-       return kCFRunLoopRunFinished;
+       return did ? kCFRunLoopRunHandledSource : kCFRunLoopRunFinished;
     }
     uint32_t *previousStopped = (uint32_t *)rl->_stopped;
-    rl->_stopped = CFAllocatorAllocate(kCFAllocatorSystemDefault, 4 * sizeof(uint32_t), 0);
-    rl->_stopped[0] = 0x4346524C;
-    rl->_stopped[1] = 0x4346524C; // 'CFRL'
-    rl->_stopped[2] = 0x00000000; // here the value is stored
-    rl->_stopped[3] = 0x4346524C;
+    rl->_stopped = NULL;
     CFRunLoopModeRef previousMode = rl->_currentMode;
     rl->_currentMode = currentMode;
+#if DEPLOYMENT_TARGET_WINDOWS
+    if (previousMode && currentMode != previousMode) {
+        if (__CFIsNonMachRunLoopMarryMsgQueueEnabled())
+            __CFRunLoopUpdateMsgWaitMarryMsgQueue(rl);
+        else
+            __CFRunLoopUpdateMsgWait(rl);
+    }
+#endif
     __CFRunLoopUnlock(rl);
     int32_t result;
-    __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
-    result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, false);
-    __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
-    __CFRunLoopModeUnlock(currentMode);
-    __CFRunLoopLock(rl);
-    CFAllocatorDeallocate(kCFAllocatorSystemDefault, (uint32_t *)rl->_stopped);
-    rl->_stopped = previousStopped;
-    rl->_currentMode = previousMode;
-    __CFRunLoopUnlock(rl);
+    @try {
+       if (currentMode->_observerMask & kCFRunLoopEntry || currentMode->_submodes) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry);
+       result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode, false);
+       if (currentMode->_observerMask & kCFRunLoopExit || currentMode->_submodes) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
+    } @finally {
+       // this kvetches if an exception was raised during a run loop callout, because the mode is not locked
+       if (0 != currentMode->_lock) {
+           __CFRunLoopModeUnlock(currentMode);
+       }
+       __CFRunLoopLock(rl);
+       if (rl->_stopped) CFAllocatorDeallocate(kCFAllocatorSystemDefault, (uint32_t *)rl->_stopped);
+       rl->_stopped = previousStopped;
+       rl->_currentMode = previousMode;
+#if DEPLOYMENT_TARGET_WINDOWS
+        if (previousMode && currentMode != previousMode) {
+            if (__CFIsNonMachRunLoopMarryMsgQueueEnabled())
+                __CFRunLoopUpdateMsgWaitMarryMsgQueue(rl);
+            else
+                __CFRunLoopUpdateMsgWait(rl);
+        }
+#endif
+       __CFRunLoopUnlock(rl);
+    }
     return result;
 }
 
@@ -1935,24 +2415,25 @@ SInt32 CFRunLoopRunInMode(CFStringRef modeName, CFTimeInterval seconds, Boolean
 static void __CFRunLoopFindMinTimer(const void *value, void *ctx) {
     CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)value;
     if (__CFIsValid(rlt)) {
-        CFRunLoopTimerRef *result = ctx;
+        CFRunLoopTimerRef *result = (CFRunLoopTimerRef *)ctx;
         if (NULL == *result || rlt->_fireTSR < (*result)->_fireTSR) {
             *result = rlt;
         }
     }
 }
 
+#if DEPLOYMENT_TARGET_WINDOWS
 static int64_t __CFRunLoopGetNextTimerFireTSR(CFRunLoopRef rl, CFRunLoopModeRef rlm) {
     CFRunLoopTimerRef result = NULL;
     int64_t fireTime = 0;
     if (rlm) {
-       if (NULL != rlm->_timers && 0 < CFSetGetCount(rlm->_timers)) {
-           __CFRunLoopTimerFireTSRLock();
-           CFSetApplyFunction(rlm->_timers, (__CFRunLoopFindMinTimer), &result);
+        if (NULL != rlm->_timers && 0 < CFSetGetCount(rlm->_timers)) {
+            __CFRunLoopTimerFireTSRLock();
+            CFSetApplyFunction(rlm->_timers, (__CFRunLoopFindMinTimer), &result);
             if (result)
                 fireTime = result->_fireTSR;
-           __CFRunLoopTimerFireTSRUnlock();
-       }
+            __CFRunLoopTimerFireTSRUnlock();
+        }
         if (NULL != rlm->_submodes) {
             CFIndex idx, cnt;
             for (idx = 0, cnt = CFArrayGetCount(rlm->_submodes); idx < cnt; idx++) {
@@ -1971,18 +2452,49 @@ static int64_t __CFRunLoopGetNextTimerFireTSR(CFRunLoopRef rl, CFRunLoopModeRef
     }
     return fireTime;
 }
+#endif
+    
+// called with rlm locked, if not NULL
+static CFAbsoluteTime __CFRunLoopGetNextTimerFireDate(CFRunLoopRef rl, CFRunLoopModeRef rlm) {
+    CFRunLoopTimerRef result = NULL;
+    CFAbsoluteTime fireDate = 0.0;
+    int64_t now2 = (int64_t)mach_absolute_time();
+    CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent();
+    if (rlm) {
+       if (NULL != rlm->_timers && 0 < CFSetGetCount(rlm->_timers)) {
+           __CFRunLoopTimerFireTSRLock();
+           CFSetApplyFunction(rlm->_timers, (__CFRunLoopFindMinTimer), &result);
+            if (result) {
+               fireDate = (0 == result->_fireTSR) ? 0.0 : (now1 + __CFTSRToTimeInterval(result->_fireTSR - now2));
+           }
+           __CFRunLoopTimerFireTSRUnlock();
+       }
+        if (NULL != rlm->_submodes) {
+            CFIndex idx, cnt;
+            for (idx = 0, cnt = CFArrayGetCount(rlm->_submodes); idx < cnt; idx++) {
+                CFStringRef modeName = (CFStringRef)CFArrayGetValueAtIndex(rlm->_submodes, idx);
+                CFRunLoopModeRef subrlm;
+                subrlm = __CFRunLoopFindMode(rl, modeName, false);
+                if (NULL != subrlm) {
+                    CFAbsoluteTime newFireDate = __CFRunLoopGetNextTimerFireDate(rl, subrlm);
+                    __CFRunLoopModeUnlock(subrlm);
+                    if (fireDate == 0 || (newFireDate != 0.0 && newFireDate < fireDate))
+                        fireDate = newFireDate;
+                }
+            }
+        }
+        __CFRunLoopModeUnlock(rlm);
+    }
+    return fireDate;
+}
 
 CFAbsoluteTime CFRunLoopGetNextTimerFireDate(CFRunLoopRef rl, CFStringRef modeName) {
     CHECK_FOR_FORK();
     CFRunLoopModeRef rlm;
-    int64_t fireTSR;
     __CFRunLoopLock(rl);
     rlm = __CFRunLoopFindMode(rl, modeName, false);
     __CFRunLoopUnlock(rl);
-    fireTSR = __CFRunLoopGetNextTimerFireTSR(rl, rlm);
-    int64_t now2 = (int64_t)mach_absolute_time();
-    CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent();
-    return (0 == fireTSR) ? 0.0 : (now1 + __CFTSRToTimeInterval(fireTSR - now2));
+    return __CFRunLoopGetNextTimerFireDate(rl, rlm);
 }
 
 Boolean CFRunLoopIsWaiting(CFRunLoopRef rl) {
@@ -1992,7 +2504,7 @@ Boolean CFRunLoopIsWaiting(CFRunLoopRef rl) {
 
 void CFRunLoopWakeUp(CFRunLoopRef rl) {
     CHECK_FOR_FORK();
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     kern_return_t ret;
     /* We unconditionally try to send the message, since we don't want
      * to lose a wakeup, but the send may fail if there is already a
@@ -2003,15 +2515,28 @@ void CFRunLoopWakeUp(CFRunLoopRef rl) {
     }
 #else
     SetEvent(rl->_wakeUpPort);
+    __CFRunLoopLock(rl);
+    if (rl->_threadID == GetCurrentThreadId()) {
+        PostMessageW(NULL, __kCFRunLoopWakeUpMessage, NULL, NULL);
+    } else {
+        PostThreadMessageW(rl->_threadID, __kCFRunLoopWakeUpMessage, NULL, NULL);
+    }
+    __CFRunLoopUnlock(rl);
 #endif
 }
 
 void CFRunLoopStop(CFRunLoopRef rl) {
+    Boolean doWake = false;
     CHECK_FOR_FORK();
     __CFRunLoopLock(rl);
-    __CFRunLoopSetStopped(rl);
+    if (rl->_currentMode) {
+        __CFRunLoopSetStopped(rl);
+        doWake = true;
+    }
     __CFRunLoopUnlock(rl);
-    CFRunLoopWakeUp(rl);
+    if (doWake) {
+        CFRunLoopWakeUp(rl);
+    }
 }
 
 CF_EXPORT void _CFRunLoopStopMode(CFRunLoopRef rl, CFStringRef modeName) {
@@ -2079,7 +2604,7 @@ CF_EXPORT void _CFRunLoopAddModeToMode(CFRunLoopRef rl, CFStringRef modeName, CF
        __CFRunLoopUnlock(rl);
        if (NULL != rlm) {
            if (NULL == rlm->_submodes) {
-               rlm->_submodes = CFArrayCreateMutable(CFGetAllocator(rlm), 0, &kCFTypeArrayCallBacks);
+               rlm->_submodes = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
            }
            if (!CFArrayContainsValue(rlm->_submodes, CFRangeMake(0, CFArrayGetCount(rlm->_submodes)), modeName)) {
                CFArrayAppendValue(rlm->_submodes, modeName);
@@ -2111,6 +2636,69 @@ CF_EXPORT void _CFRunLoopRemoveModeFromMode(CFRunLoopRef rl, CFStringRef modeNam
     }
 }
 
+void CFRunLoopPerformBlock(CFRunLoopRef rl, CFTypeRef mode, void (^block)(void)) {
+    CHECK_FOR_FORK();
+    if (CFStringGetTypeID() == CFGetTypeID(mode)) {
+       mode = CFStringCreateCopy(kCFAllocatorSystemDefault, (CFStringRef)mode);
+        __CFRunLoopLock(rl);
+       // ensure mode exists
+        CFRunLoopModeRef currentMode = __CFRunLoopFindMode(rl, (CFStringRef)mode, true);
+        if (currentMode) __CFRunLoopModeUnlock(currentMode);
+        __CFRunLoopUnlock(rl);
+    } else if (CFArrayGetTypeID() == CFGetTypeID(mode)) {
+        CFIndex cnt = CFArrayGetCount((CFArrayRef)mode);
+       const void **values = (const void **)malloc(sizeof(const void *) * cnt);
+        CFArrayGetValues((CFArrayRef)mode, CFRangeMake(0, cnt), values);
+       mode = CFSetCreate(kCFAllocatorSystemDefault, values, cnt, &kCFTypeSetCallBacks);
+        __CFRunLoopLock(rl);
+       // ensure modes exist
+       for (CFIndex idx = 0; idx < cnt; idx++) {
+            CFRunLoopModeRef currentMode = __CFRunLoopFindMode(rl, (CFStringRef)values[idx], true);
+            if (currentMode) __CFRunLoopModeUnlock(currentMode);
+       }
+        __CFRunLoopUnlock(rl);
+       free(values);
+    } else if (CFSetGetTypeID() == CFGetTypeID(mode)) {
+        CFIndex cnt = CFSetGetCount((CFSetRef)mode);
+       const void **values = (const void **)malloc(sizeof(const void *) * cnt);
+        CFSetGetValues((CFSetRef)mode, values);
+       mode = CFSetCreate(kCFAllocatorSystemDefault, values, cnt, &kCFTypeSetCallBacks);
+        __CFRunLoopLock(rl);
+       // ensure modes exist
+       for (CFIndex idx = 0; idx < cnt; idx++) {
+            CFRunLoopModeRef currentMode = __CFRunLoopFindMode(rl, (CFStringRef)values[idx], true);
+            if (currentMode) __CFRunLoopModeUnlock(currentMode);
+       }
+        __CFRunLoopUnlock(rl);
+       free(values);
+    } else {
+       mode = NULL;
+    }
+#if DEPLOYMENT_TARGET_WINDOWS
+    // <rdar://problem/6496715> Block.h uses "typeof", which is not available when using Visual Studio on Windows
+    block = (void (^)(void))_Block_copy(block);
+#else
+    block = Block_copy(block);
+#endif
+    if (!mode || !block) {
+       if (mode) CFRelease(mode);
+       if (block) Block_release(block);
+       return;
+    }
+    __CFRunLoopLock(rl);
+    struct _block_item *new_item = (struct _block_item *)malloc(sizeof(struct _block_item));
+    new_item->_next = NULL;
+    new_item->_mode = mode;
+    new_item->_block = block;
+    if (!rl->_blocks_tail) {
+       rl->_blocks_head = new_item;
+    } else {
+       rl->_blocks_tail->_next = new_item;
+    }
+    rl->_blocks_tail = new_item;
+    __CFRunLoopUnlock(rl);
+}
+
 Boolean CFRunLoopContainsSource(CFRunLoopRef rl, CFRunLoopSourceRef rls, CFStringRef modeName) {
     CHECK_FOR_FORK();
     CFRunLoopModeRef rlm;
@@ -2143,7 +2731,7 @@ void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef rls, CFStringRef mod
     if (modeName == kCFRunLoopCommonModes) {
        CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault, rl->_commonModes) : NULL;
        if (NULL == rl->_commonModeItems) {
-           rl->_commonModeItems = CFSetCreateMutable(CFGetAllocator(rl), 0, &kCFTypeSetCallBacks);
+           rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
            _CFSetSetCapacity(rl->_commonModeItems, 20);
        }
        CFSetAddValue(rl->_commonModeItems, rls);
@@ -2158,11 +2746,16 @@ void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef rls, CFStringRef mod
        rlm = __CFRunLoopFindMode(rl, modeName, true);
        __CFRunLoopUnlock(rl);
        if (NULL != rlm && NULL == rlm->_sources) {
-           rlm->_sources = CFSetCreateMutable(CFGetAllocator(rlm), 0, &kCFTypeSetCallBacks);
+           rlm->_sources = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
+           rlm->_portToV1SourceMap = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, NULL);
            _CFSetSetCapacity(rlm->_sources, 10);
        }
        if (NULL != rlm && !CFSetContainsValue(rlm->_sources, rls)) {
            CFSetAddValue(rlm->_sources, rls);
+           if (1 == rls->_context.version0.version) {
+               __CFPort src_port = rls->_context.version1.getPort(rls->_context.version1.info);
+               CFDictionarySetValue(rlm->_portToV1SourceMap, (const void *)(uintptr_t)src_port, rls);
+           }
            __CFRunLoopModeUnlock(rlm);
            __CFRunLoopSourceSchedule(rls, rl, rlm);    /* DOES CALLOUT */
        } else if (NULL != rlm) {
@@ -2194,6 +2787,10 @@ void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef rls, CFStringRef
        __CFRunLoopUnlock(rl);
        if (NULL != rlm && NULL != rlm->_sources && CFSetContainsValue(rlm->_sources, rls)) {
            CFRetain(rls);
+           if (1 == rls->_context.version0.version) {
+               __CFPort src_port = rls->_context.version1.getPort(rls->_context.version1.info);
+               CFDictionaryRemoveValue(rlm->_portToV1SourceMap, (const void *)(uintptr_t)src_port);
+           }
            CFSetRemoveValue(rlm->_sources, rls);
            __CFRunLoopModeUnlock(rlm);
            __CFRunLoopSourceCancel(rls, rl, rlm);      /* DOES CALLOUT */
@@ -2240,8 +2837,8 @@ static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl, CFStringRef modeName) {
            __CFRunLoopModeUnlock(rlm);
             CFTypeRef context[2] = {rl, modeName};
             CFSetApplyFunction(set, (__CFRunLoopRemoveSourceFromMode), (void *)context);
-            CFRelease(set);
-        } else if (NULL != rlm) {
+           CFRelease(set);
+       } else if (NULL != rlm) {
            __CFRunLoopModeUnlock(rlm);
        }
     }
@@ -2279,7 +2876,7 @@ void CFRunLoopAddObserver(CFRunLoopRef rl, CFRunLoopObserverRef rlo, CFStringRef
     if (modeName == kCFRunLoopCommonModes) {
        CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault, rl->_commonModes) : NULL;
        if (NULL == rl->_commonModeItems) {
-           rl->_commonModeItems = CFSetCreateMutable(CFGetAllocator(rl), 0, &kCFTypeSetCallBacks);
+           rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
        }
        CFSetAddValue(rl->_commonModeItems, rlo);
        __CFRunLoopUnlock(rl);
@@ -2293,10 +2890,11 @@ void CFRunLoopAddObserver(CFRunLoopRef rl, CFRunLoopObserverRef rlo, CFStringRef
        rlm = __CFRunLoopFindMode(rl, modeName, true);
        __CFRunLoopUnlock(rl);
        if (NULL != rlm && NULL == rlm->_observers) {
-           rlm->_observers = CFSetCreateMutable(CFGetAllocator(rlm), 0, &kCFTypeSetCallBacks);
+           rlm->_observers = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
        }
        if (NULL != rlm && !CFSetContainsValue(rlm->_observers, rlo)) {
            CFSetAddValue(rlm->_observers, rlo);
+           rlm->_observerMask |= rlo->_activities;
            __CFRunLoopModeUnlock(rlm);
            __CFRunLoopObserverSchedule(rlo, rl, rlm);
        } else if (NULL != rlm) {
@@ -2363,6 +2961,7 @@ Boolean CFRunLoopContainsTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringR
 
 void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeName) {
     CHECK_FOR_FORK();
+//CFLog(4, CFSTR("CFRunLoopAddTimer(%p, timer %p, %@)"), rl, rlt, modeName);
     CFRunLoopModeRef rlm;
     if (__CFRunLoopIsDeallocating(rl)) return;
     if (!__CFIsValid(rlt) || (NULL != rlt->_runLoop && rlt->_runLoop != rl)) return;
@@ -2370,7 +2969,7 @@ void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeN
     if (modeName == kCFRunLoopCommonModes) {
        CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault, rl->_commonModes) : NULL;
        if (NULL == rl->_commonModeItems) {
-           rl->_commonModeItems = CFSetCreateMutable(CFGetAllocator(rl), 0, &kCFTypeSetCallBacks);
+           rl->_commonModeItems = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
        }
        CFSetAddValue(rl->_commonModeItems, rlt);
        __CFRunLoopUnlock(rl);
@@ -2384,7 +2983,7 @@ void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeN
        rlm = __CFRunLoopFindMode(rl, modeName, true);
        __CFRunLoopUnlock(rl);
        if (NULL != rlm && NULL == rlm->_timers) {
-           rlm->_timers = CFSetCreateMutable(CFGetAllocator(rlm), 0, &kCFTypeSetCallBacks);
+           rlm->_timers = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
        }
        if (NULL != rlm && !CFSetContainsValue(rlm->_timers, rlt)) {
            CFSetAddValue(rlm->_timers, rlt);
@@ -2398,6 +2997,7 @@ void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeN
 
 void CFRunLoopRemoveTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeName) {
     CHECK_FOR_FORK();
+//CFLog(4, CFSTR("CFRunLoopRemoveTimer(%p, timer %p, %@)"), rl, rlt, modeName);
     CFRunLoopModeRef rlm;
     __CFRunLoopLock(rl);
     if (modeName == kCFRunLoopCommonModes) {
@@ -2436,6 +3036,7 @@ static Boolean __CFRunLoopSourceEqual(CFTypeRef cf1, CFTypeRef cf2) {     /* DOES CA
     CFRunLoopSourceRef rls1 = (CFRunLoopSourceRef)cf1;
     CFRunLoopSourceRef rls2 = (CFRunLoopSourceRef)cf2;
     if (rls1 == rls2) return true;
+    if (__CFIsValid(rls1) != __CFIsValid(rls2)) return false;
     if (rls1->_order != rls2->_order) return false;
     if (rls1->_context.version0.version != rls2->_context.version0.version) return false;
     if (rls1->_context.version0.hash != rls2->_context.version0.hash) return false;
@@ -2463,15 +3064,21 @@ static CFStringRef __CFRunLoopSourceCopyDescription(CFTypeRef cf) {     /* DOES CALL
     }
     if (NULL == contextDesc) {
        void *addr = rls->_context.version0.version == 0 ? (void *)rls->_context.version0.perform : (rls->_context.version0.version == 1 ? (void *)rls->_context.version1.perform : NULL);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+       contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopSource context>{version = %ld, info = %p, callout = %p}"), rls->_context.version0.version, rls->_context.version0.info, addr);
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        Dl_info info;
        const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
-       contextDesc = CFStringCreateWithFormat(CFGetAllocator(rls), NULL, CFSTR("<CFRunLoopSource context>{version = %ld, info = %p, callout = %s (%p)}"), rls->_context.version0.version, rls->_context.version0.info, name, addr);
+       contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopSource context>{version = %ld, info = %p, callout = %s (%p)}"), rls->_context.version0.version, rls->_context.version0.info, name, addr);
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     }
-result = CFStringCreateWithFormat(CFGetAllocator(rls), NULL, CFSTR("<CFRunLoopSource %p [%p]>{locked = %s, signalled = %s, valid = %s, order = %d, context = %@}"), cf, CFGetAllocator(rls), lockCount(rls->_lock) ? "Yes" : "No", __CFRunLoopSourceIsSignaled(rls) ? "Yes" : "No", __CFIsValid(rls) ? "Yes" : "No", rls->_order, contextDesc);
+#if DEPLOYMENT_TARGET_WINDOWS
+    result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopSource %p [%p]>{locked = %s, signalled = %s, valid = %s, order = %d, context = %@}"), cf, CFGetAllocator(rls), "unknown", __CFRunLoopSourceIsSignaled(rls) ? "Yes" : "No", __CFIsValid(rls) ? "Yes" : "No", rls->_order, contextDesc);
+#else
+    result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopSource %p [%p]>{locked = %s, signalled = %s, valid = %s, order = %d, context = %@}"), cf, CFGetAllocator(rls), lockCount(rls->_lock) ? "Yes" : "No", __CFRunLoopSourceIsSignaled(rls) ? "Yes" : "No", __CFIsValid(rls) ? "Yes" : "No", rls->_order, contextDesc);
+#endif
     CFRelease(contextDesc);
     return result;
 }
@@ -2482,6 +3089,7 @@ static void __CFRunLoopSourceDeallocate(CFTypeRef cf) {   /* DOES CALLOUT */
     if (rls->_context.version0.release) {
        rls->_context.version0.release(rls->_context.version0.info);
     }
+    memset((char *)cf + sizeof(CFRuntimeBase), 0, sizeof(struct __CFRunLoopSource) - sizeof(CFRuntimeBase));
 }
 
 static const CFRuntimeClass __CFRunLoopSourceClass = {
@@ -2528,13 +3136,13 @@ CFRunLoopSourceRef CFRunLoopSourceCreate(CFAllocatorRef allocator, CFIndex order
     case 1:
        size = sizeof(CFRunLoopSourceContext1);
        break;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     case 2:
        size = sizeof(CFRunLoopSourceContext2);
        break;
 #endif
     }
-    CF_WRITE_BARRIER_MEMMOVE(&memory->_context, context, size);
+    objc_memmove_collectable(&memory->_context, context, size);
     if (context->retain) {
        memory->_context.version0.info = (void *)context->retain(context->info);
     }
@@ -2547,16 +3155,20 @@ CFIndex CFRunLoopSourceGetOrder(CFRunLoopSourceRef rls) {
     return rls->_order;
 }
 
+static void __CFRunLoopSourceWakeUpLoop(const void *value, void *context) {
+    CFRunLoopWakeUp((CFRunLoopRef)value);
+}
+
 static void __CFRunLoopSourceRemoveFromRunLoop(const void *value, void *context) {
     CFRunLoopRef rl = (CFRunLoopRef)value;
-    CFTypeRef *params = context;
+    CFTypeRef *params = (CFTypeRef *)context;
     CFRunLoopSourceRef rls = (CFRunLoopSourceRef)params[0];
     CFArrayRef array;
     CFIndex idx;
     if (rl == params[1]) return;
     array = CFRunLoopCopyAllModes(rl);
     for (idx = CFArrayGetCount(array); idx--;) {
-       CFStringRef modeName = CFArrayGetValueAtIndex(array, idx);
+       CFStringRef modeName = (CFStringRef)CFArrayGetValueAtIndex(array, idx);
        CFRunLoopRemoveSource(rl, rls, modeName);
     }
     CFRunLoopRemoveSource(rl, rls, kCFRunLoopCommonModes);
@@ -2574,8 +3186,7 @@ void CFRunLoopSourceInvalidate(CFRunLoopSourceRef rls) {
         __CFRunLoopSourceUnsetSignaled(rls);
        if (NULL != rls->_runLoops) {
            CFTypeRef params[2] = {rls, NULL};
-           CFBagRef bag = CFBagCreateCopy(kCFAllocatorSystemDefault, rls->_runLoops);
-           CFRelease(rls->_runLoops);
+           CFBagRef bag = rls->_runLoops;
            rls->_runLoops = NULL;
            __CFRunLoopSourceUnlock(rls);
            CFBagApplyFunction(bag, (__CFRunLoopSourceRemoveFromRunLoop), params);
@@ -2608,7 +3219,7 @@ void CFRunLoopSourceGetContext(CFRunLoopSourceRef rls, CFRunLoopSourceContext *c
     case 1:
        size = sizeof(CFRunLoopSourceContext1);
        break;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     case 2:
        size = sizeof(CFRunLoopSourceContext2);
        break;
@@ -2634,6 +3245,14 @@ Boolean CFRunLoopSourceIsSignalled(CFRunLoopSourceRef rls) {
     return ret;
 }
 
+__private_extern__ void _CFRunLoopSourceWakeUpRunLoops(CFRunLoopSourceRef rls) {
+    __CFRunLoopSourceLock(rls);
+    if (__CFIsValid(rls) && NULL != rls->_runLoops) {
+       CFBagApplyFunction(rls->_runLoops, __CFRunLoopSourceWakeUpLoop, NULL);
+    }
+    __CFRunLoopSourceUnlock(rls);
+}
+
 /* CFRunLoopObserver */
 
 static CFStringRef __CFRunLoopObserverCopyDescription(CFTypeRef cf) {  /* DOES CALLOUT */
@@ -2644,13 +3263,15 @@ static CFStringRef __CFRunLoopObserverCopyDescription(CFTypeRef cf) {   /* DOES CA
        contextDesc = rlo->_context.copyDescription(rlo->_context.info);
     }
     if (!contextDesc) {
-       contextDesc = CFStringCreateWithFormat(CFGetAllocator(rlo), NULL, CFSTR("<CFRunLoopObserver context %p>"), rlo->_context.info);
+       contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopObserver context %p>"), rlo->_context.info);
     }
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+    result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopObserver %p [%p]>{locked = %s, valid = %s, activities = 0x%x, repeats = %s, order = %d, callout = %p, context = %@}"), cf, CFGetAllocator(rlo), "unknown", __CFIsValid(rlo) ? "Yes" : "No", rlo->_activities, __CFRunLoopObserverRepeats(rlo) ? "Yes" : "No", rlo->_order, rlo->_callout, contextDesc);    
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     void *addr = rlo->_callout;
     Dl_info info;
     const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
-    result = CFStringCreateWithFormat(CFGetAllocator(rlo), NULL, CFSTR("<CFRunLoopObserver %p [%p]>{locked = %s, valid = %s, activities = 0x%x, repeats = %s, order = %d, callout = %s (%p), context = %@}"), cf, CFGetAllocator(rlo), lockCount(rlo->_lock) ? "Yes" : "No", __CFIsValid(rlo) ? "Yes" : "No", rlo->_activities, __CFRunLoopObserverRepeats(rlo) ? "Yes" : "No", rlo->_order, name, addr, contextDesc);
+    result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopObserver %p [%p]>{locked = %s, valid = %s, activities = 0x%x, repeats = %s, order = %d, callout = %s (%p), context = %@}"), cf, CFGetAllocator(rlo), lockCount(rlo->_lock) ? "Yes" : "No", __CFIsValid(rlo) ? "Yes" : "No", rlo->_activities, __CFRunLoopObserverRepeats(rlo) ? "Yes" : "No", rlo->_order, name, addr, contextDesc);
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
@@ -2755,7 +3376,7 @@ void CFRunLoopObserverInvalidate(CFRunLoopObserverRef rlo) {      /* DOES CALLOUT */
            CFIndex idx;
            array = CFRunLoopCopyAllModes(rl);
            for (idx = CFArrayGetCount(array); idx--;) {
-               CFStringRef modeName = CFArrayGetValueAtIndex(array, idx);
+               CFStringRef modeName = (CFStringRef)CFArrayGetValueAtIndex(array, idx);
                CFRunLoopRemoveObserver(rl, rlo, modeName);
            }
            CFRunLoopRemoveObserver(rl, rlo, kCFRunLoopCommonModes);
@@ -2787,24 +3408,26 @@ void CFRunLoopObserverGetContext(CFRunLoopObserverRef rlo, CFRunLoopObserverCont
 static CFStringRef __CFRunLoopTimerCopyDescription(CFTypeRef cf) {     /* DOES CALLOUT */
     CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)cf;
     CFStringRef result;
-    CFStringRef contextDesc = NULL;
-    int64_t fireTime;
+    int64_t now2 = (int64_t)mach_absolute_time();
+    CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent();
     __CFRunLoopTimerFireTSRLock();
-    fireTime = rlt->_fireTSR;
+    int64_t fireTime = rlt->_fireTSR;
     __CFRunLoopTimerFireTSRUnlock();
+    CFAbsoluteTime fireDate = now1 + __CFTSRToTimeInterval(fireTime - now2);
+    CFStringRef contextDesc = NULL;
     if (NULL != rlt->_context.copyDescription) {
        contextDesc = rlt->_context.copyDescription(rlt->_context.info);
     }
     if (NULL == contextDesc) {
-       contextDesc = CFStringCreateWithFormat(CFGetAllocator(rlt), NULL, CFSTR("<CFRunLoopTimer context %p>"), rlt->_context.info);
+       contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopTimer context %p>"), rlt->_context.info);
     }
-    int64_t now2 = (int64_t)mach_absolute_time();
-    CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent();
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+    result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopTimer %p [%p]>{locked = %s, valid = %s, interval = %0.09g, next fire date = %0.09g, order = %d, callout = %p, context = %@}"), cf, CFGetAllocator(rlt), "unknown", __CFIsValid(rlt) ? "Yes" : "No", __CFTSRToTimeInterval(rlt->_intervalTSR), now1 + __CFTSRToTimeInterval(fireTime - now2), rlt->_order, rlt->_callout, contextDesc);
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     void *addr = rlt->_callout;
     Dl_info info;
     const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
-    result = CFStringCreateWithFormat(CFGetAllocator(rlt), NULL, CFSTR("<CFRunLoopTimer %p [%p]>{locked = %s, valid = %s, interval = %0.09g, next fire date = %0.09g, order = %d, callout = %s (%p), context = %@}"), cf, CFGetAllocator(rlt), lockCount(rlt->_lock) ? "Yes" : "No", __CFIsValid(rlt) ? "Yes" : "No", __CFTSRToTimeInterval(rlt->_intervalTSR), now1 + __CFTSRToTimeInterval(fireTime - now2), rlt->_order, name, addr, contextDesc);
+    result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopTimer %p [%p]>{locked = %s, valid = %s, interval = %0.09g, next fire date = %0.09g, order = %d, callout = %s (%p), context = %@}"), cf, CFGetAllocator(rlt), lockCount(rlt->_lock) ? "Yes" : "No", __CFIsValid(rlt) ? "Yes" : "No", rlt->_interval, fireDate, rlt->_order, name, addr, contextDesc);
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
@@ -2813,8 +3436,12 @@ static CFStringRef __CFRunLoopTimerCopyDescription(CFTypeRef cf) {       /* DOES CALLO
 }
 
 static void __CFRunLoopTimerDeallocate(CFTypeRef cf) { /* DOES CALLOUT */
+//CFLog(6, CFSTR("__CFRunLoopTimerDeallocate(%p)"), cf);
     CFRunLoopTimerRef rlt = (CFRunLoopTimerRef)cf;
+    __CFRunLoopTimerSetDeallocating(rlt);
     CFRunLoopTimerInvalidate(rlt);     /* DOES CALLOUT */
+    CFRelease(rlt->_rlModes);
+    rlt->_rlModes = NULL;
 }
 
 static const CFRuntimeClass __CFRunLoopTimerClass = {
@@ -2851,14 +3478,18 @@ CFRunLoopTimerRef CFRunLoopTimerCreate(CFAllocatorRef allocator, CFAbsoluteTime
     __CFRunLoopTimerUnsetDidFire(memory);
     CF_SPINLOCK_INIT_FOR_STRUCTS(memory->_lock);
     memory->_runLoop = NULL;
-    memory->_rlCount = 0;
-#if DEPLOYMENT_TARGET_MACOSX
+    memory->_rlModes = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     memory->_port = MACH_PORT_NULL;
 #endif
     memory->_order = order;
+    if (interval < 0.0) interval = 0.0;
+    memory->_interval = interval;
+    if (TIMER_DATE_LIMIT < fireDate) fireDate = TIMER_DATE_LIMIT;
+    if (TIMER_INTERVAL_LIMIT < interval) interval = TIMER_INTERVAL_LIMIT;
+    memory->_nextFireDate = fireDate;
     int64_t now2 = (int64_t)mach_absolute_time();
     CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent();
-    if (3.1556952e+9 < fireDate) fireDate = 3.1556952e+9;
     if (fireDate < now1) {
        memory->_fireTSR = now2;
     } else if (now1 + __CFTSRToTimeInterval(LLONG_MAX) < fireDate) {
@@ -2866,7 +3497,6 @@ CFRunLoopTimerRef CFRunLoopTimerCreate(CFAllocatorRef allocator, CFAbsoluteTime
     } else {
        memory->_fireTSR = now2 + __CFTimeIntervalToTSR(fireDate - now1);
     }
-    if (3.1556952e+9 < interval) interval = 3.1556952e+9;
     if (interval <= 0.0) {
        memory->_intervalTSR = 0;
     } else if (__CFTSRToTimeInterval(LLONG_MAX) < interval) {
@@ -2890,14 +3520,15 @@ CFRunLoopTimerRef CFRunLoopTimerCreate(CFAllocatorRef allocator, CFAbsoluteTime
        memory->_context.release = 0;
        memory->_context.copyDescription = 0;
     }
+//CFLog(4, CFSTR("CFRunLoopTimerCreate(%p, %f, %f, 0x%lx, %ld, %p, %p) => %p"), allocator, fireDate, interval, flags, order, callout, context, memory);
     return memory;
 }
 
 CFAbsoluteTime CFRunLoopTimerGetNextFireDate(CFRunLoopTimerRef rlt) {
     CHECK_FOR_FORK();
-    int64_t fireTime, result = 0;
     CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID, CFAbsoluteTime, rlt, "_cffireTime");
     __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID);
+    int64_t fireTime, result = 0;
     __CFRunLoopTimerFireTSRLock();
     fireTime = rlt->_fireTSR;
     __CFRunLoopTimerFireTSRUnlock();
@@ -2912,11 +3543,14 @@ CFAbsoluteTime CFRunLoopTimerGetNextFireDate(CFRunLoopTimerRef rlt) {
 }
 
 void CFRunLoopTimerSetNextFireDate(CFRunLoopTimerRef rlt, CFAbsoluteTime fireDate) {
+//CFLog(6, CFSTR("CFRunLoopTimerSetNextFireDate(rlt %p, fireDate %f)"), rlt, fireDate);
     CHECK_FOR_FORK();
-    __CFRunLoopTimerFireTSRLock();
+//CFLog(4, CFSTR("CFRunLoopTimerSetNextFireDate(%p, %f)  [limit: %f]"), rlt, fireDate, TIMER_DATE_LIMIT);
+    if (TIMER_DATE_LIMIT < fireDate) fireDate = TIMER_DATE_LIMIT;
+    rlt->_nextFireDate = fireDate;
     int64_t now2 = (int64_t)mach_absolute_time();
     CFAbsoluteTime now1 = CFAbsoluteTimeGetCurrent();
-    if (3.1556952e+9 < fireDate) fireDate = 3.1556952e+9;
+    __CFRunLoopTimerFireTSRLock();
     if (fireDate < now1) {
        rlt->_fireTSR = now2;
     } else if (now1 + __CFTSRToTimeInterval(LLONG_MAX) < fireDate) {
@@ -2925,7 +3559,7 @@ void CFRunLoopTimerSetNextFireDate(CFRunLoopTimerRef rlt, CFAbsoluteTime fireDat
        rlt->_fireTSR = now2 + __CFTimeIntervalToTSR(fireDate - now1);
     }
     if (rlt->_runLoop != NULL) {
-       __CFRunLoopTimerRescheduleWithAllModes(rlt, rlt->_runLoop);
+       __CFRunLoopTimerRescheduleWithAllModes(rlt);
     }
     __CFRunLoopTimerFireTSRUnlock();
 }
@@ -2934,13 +3568,13 @@ CFTimeInterval CFRunLoopTimerGetInterval(CFRunLoopTimerRef rlt) {
     CHECK_FOR_FORK();
     CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID, CFTimeInterval, rlt, "timeInterval");
     __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID);
-    return __CFTSRToTimeInterval(rlt->_intervalTSR);
+    return rlt->_interval;
 }
 
 Boolean CFRunLoopTimerDoesRepeat(CFRunLoopTimerRef rlt) {
     CHECK_FOR_FORK();
     __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID);
-    return (0 != rlt->_intervalTSR);
+    return (0.0 < rlt->_interval);
 }
 
 CFIndex CFRunLoopTimerGetOrder(CFRunLoopTimerRef rlt) {
@@ -2952,15 +3586,18 @@ CFIndex CFRunLoopTimerGetOrder(CFRunLoopTimerRef rlt) {
 
 void CFRunLoopTimerInvalidate(CFRunLoopTimerRef rlt) { /* DOES CALLOUT */
     CHECK_FOR_FORK();
+//CFLog(4, CFSTR("CFRunLoopTimerInvalidate(%p)"), rlt);
     CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID, void, rlt, "invalidate");
     __CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID);
-    CFRetain(rlt);
+    if (!__CFRunLoopTimerIsDeallocating(rlt)) {
+        CFRetain(rlt);
+    }
     __CFRunLoopTimerLock(rlt);
     if (__CFIsValid(rlt)) {
        CFRunLoopRef rl = rlt->_runLoop;
        void *info = rlt->_context.info;
        __CFUnsetValid(rlt);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        __CFRunLoopTimerPortMapLock();
        if (NULL != __CFRLTPortMap) {
            CFDictionaryRemoveValue(__CFRLTPortMap, (void *)(uintptr_t)rlt->_port);
@@ -2972,15 +3609,13 @@ void CFRunLoopTimerInvalidate(CFRunLoopTimerRef rlt) {  /* DOES CALLOUT */
        rlt->_context.info = NULL;
        __CFRunLoopTimerUnlock(rlt);
        if (NULL != rl) {
-           CFArrayRef array;
-           CFIndex idx;
-           array = CFRunLoopCopyAllModes(rl);
-           for (idx = CFArrayGetCount(array); idx--;) {
-               CFStringRef modeName = CFArrayGetValueAtIndex(array, idx);
-               CFRunLoopRemoveTimer(rl, rlt, modeName);
+           CFIndex cnt = CFSetGetCount(rlt->_rlModes);
+           STACK_BUFFER_DECL(CFStringRef, modes, cnt);
+           CFSetGetValues(rlt->_rlModes, (const void **)modes);
+           for (CFIndex idx = 0; idx < cnt; idx++) {
+               CFRunLoopRemoveTimer(rl, rlt, modes[idx]);
            }
            CFRunLoopRemoveTimer(rl, rlt, kCFRunLoopCommonModes);
-           CFRelease(array);
        }
        if (NULL != rlt->_context.release) {
            rlt->_context.release(info);        /* CALLOUT */
@@ -2988,7 +3623,9 @@ void CFRunLoopTimerInvalidate(CFRunLoopTimerRef rlt) {    /* DOES CALLOUT */
     } else {
        __CFRunLoopTimerUnlock(rlt);
     }
-    CFRelease(rlt);
+    if (!__CFRunLoopTimerIsDeallocating(rlt)) {
+        CFRelease(rlt);
+    }
 }
 
 Boolean CFRunLoopTimerIsValid(CFRunLoopTimerRef rlt) {
@@ -3005,5 +3642,164 @@ void CFRunLoopTimerGetContext(CFRunLoopTimerRef rlt, CFRunLoopTimerContext *cont
     *context = rlt->_context;
 }
 
-#endif
 
+#if DEPLOYMENT_TARGET_WINDOWS
+
+//#if MARRY_MESSAGE_QUEUE
+
+// Do we need to make sure it's not CFRunLoopRun processing the message queue? 
+CF_EXPORT LRESULT CALLBACK pumpRunLoopFromMessageQueue(int nCode, WPARAM wParam, LPARAM lParam) { 
+    //if nCode < 0, we're supposed to blindly call CallNexthookEx instead of processing the message ourselves
+    if (nCode >= 0) {
+        MSG *msgPtr = (MSG *)lParam;
+        CFRunLoopRef rl = CFRunLoopGetCurrent();
+        CFStringRef currMode;
+        
+        if (msgPtr->message == __kCFRunLoopV1SourceReadyMessage) {
+            CFRunLoopModeRef rlm;
+            CFRunLoopSourceRef rls;
+            __CFRunLoopLock(rl);
+            rlm = rl->_currentMode;
+            if (!rlm) {
+                rlm = __CFRunLoopFindMode(rl, kCFRunLoopDefaultMode, true); // returns the mode locked
+            } else {
+                __CFRunLoopModeLock(rlm);
+            }
+            rls = __CFRunLoopModeFindSourceForMachPort(rl, rlm, (__CFPort)msgPtr->lParam);
+            __CFRunLoopUnlock(rl);
+            if (rls) {
+                // Must still hold the mode lock when calling DoSource1
+                __CFRunLoopDoSource1(rl, rlm, rls);
+            }
+            __CFRunLoopModeUnlock(rlm);
+        }
+        if (msgPtr->message == __kCFRunLoopV1SourceReadyMessage || msgPtr->message == __kCFRunLoopWakeUpMessage) {
+            // Must always pump the RL regardless of whether we received the wakeup message because whomever processed the v1 source may be assuming that the RL is running and will see further callouts.
+            currMode = CFRunLoopCopyCurrentMode(rl);
+            if (!currMode) {
+                currMode = kCFRunLoopDefaultMode;
+                CFRetain(currMode);
+            }
+            while (CFRunLoopRunInMode(currMode, 0.0, true) == kCFRunLoopRunHandledSource) {
+                ;
+            }
+            CFRelease(currMode);
+        }
+    } 
+    return CallNextHookEx(__CFGetThreadSpecificData_inline()->_messageHook, nCode, wParam, lParam); 
+} 
+
+void __CFRunLoopMsgWaitThread(void *theRL) {
+    CFRunLoopRef rl = (CFRunLoopRef)theRL;
+    Boolean allDone = FALSE;
+    
+    while (!allDone) {
+        
+        CFRunLoopModeRef rlm;
+        __CFPortSet waitSet;
+        DWORD waitResult = WAIT_TIMEOUT;
+        DWORD qMask;
+        HANDLE handleBuf[MAXIMUM_WAIT_OBJECTS];
+        HANDLE *handles, *currHandle;
+        uint32_t handleCount, handleIndex;
+        Boolean freeHandles;
+        
+        __CFRunLoopLock(rl);
+        rlm = rl->_currentMode;
+        if (!rlm) {
+            rlm = __CFRunLoopFindMode(rl, kCFRunLoopDefaultMode, true); // Returns a locked mode
+        } else {
+            __CFRunLoopModeLock(rlm);
+        }
+        CFRetain(rlm);
+        waitSet = rlm->_portSet;
+        
+        // copy out the handles to be safe from other threads at work
+        handles = __CFPortSetGetPorts(waitSet, handleBuf, MAXIMUM_WAIT_OBJECTS, &handleCount);
+        freeHandles = (handles != handleBuf);
+        // Replace the wakeup port with our own update port
+        for (handleIndex = 0, currHandle = handles; handleIndex < handleCount; handleIndex ++, currHandle++) {
+            if (*currHandle == rl->_wakeUpPort) {
+                *currHandle = rl->_msgUpdatePort;
+                break;
+            }
+        }
+        
+        // Not sure what to do with this....
+        //        handles[handleCount] = rl->_msgShutdownPort;
+        //        handleCount ++;
+        
+        qMask = rlm->_msgQMask;
+        
+        while (1) {
+            Boolean shuttingDown = false;
+            __CFRunLoopModeUnlock(rlm);
+            __CFRunLoopUnlock(rl);
+            
+            // What do we do if there are more than MAXIMUM_WAIT_OBJECTS 
+            //waitResult = MsgWaitForMultipleObjects(__CFMin(handleCount, MAXIMUM_WAIT_OBJECTS), handles, false, INFINITE, qMask);
+            waitResult = WaitForMultipleObjects(__CFMin(handleCount, MAXIMUM_WAIT_OBJECTS), handles, false, INFINITE);
+            // Need to poll here to see if we've been told to die; if so, we must not touch rl.  I think.
+            __CFRunLoopLock(rl);
+            __CFRunLoopModeLock(rlm);
+            ResetEvent(rl->_msgUpdatePort);
+            
+            __CFPort livePort = CFPORT_NULL;
+            if (waitResult == WAIT_FAILED) {
+                DWORD error = GetLastError();
+                if (error == ERROR_INVALID_HANDLE) {
+                    // A handle got freed out from underneath us.  Force an update of our handle watch list.
+                    livePort = rl->_msgUpdatePort;
+                } else {
+                    CFAssert2(true, __kCFLogAssertion, "%s(): error %d from MsgWaitForMultipleObjects\n", __PRETTY_FUNCTION__,error);
+                }
+            }
+            if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0+handleCount) {
+                // a handle was signaled
+                livePort = handles[waitResult-WAIT_OBJECT_0];
+            } else if (waitResult >= WAIT_ABANDONED_0 && waitResult < WAIT_ABANDONED_0+handleCount) {
+                // an "abandoned mutex object"
+                livePort = handles[waitResult-WAIT_ABANDONED_0];
+            }
+            if (freeHandles){
+                CFAllocatorDeallocate(kCFAllocatorSystemDefault, handles);
+            }
+            
+            if (livePort == rl->_msgUpdatePort) {
+                break;
+                //            } else if (livePort == rl->_msgShutdownPort) {
+                //                allDone = true;
+                //                break;
+            } else {
+                //                OutputDebugStr(L"Posting v1 source ready msg\n");
+                ResetEvent(livePort);
+                PostThreadMessageW(rl->_threadID, __kCFRunLoopV1SourceReadyMessage, NULL, (LPARAM)livePort);
+            }
+        }
+        __CFRunLoopModeUnlock(rlm);
+        CFRelease(rlm);
+        __CFRunLoopUnlock(rl);
+    }
+}
+
+// #endif
+
+// Called while holding the run loop lock
+
+//#if MARRY_MESSAGE_QUEUE
+
+void __CFRunLoopUpdateMsgWaitMarryMsgQueue(CFRunLoopRef rl) {
+    if (rl->_msgUpdatePort == CFPORT_NULL) {
+        rl->_msgUpdatePort = __CFPortAllocate();
+        if (CFPORT_NULL == rl->_msgUpdatePort) HALT;
+        
+        // Kick off the MsgWaitThread
+        _beginthread(__CFRunLoopMsgWaitThread, 0, rl);
+    }
+    SetEvent(rl->_msgUpdatePort);
+}
+//#else
+CF_INLINE void __CFRunLoopUpdateMsgWait(CFRunLoopRef rl) {}
+//#endif
+    
+#endif
index 1a96c69ce25a22c6eff780ac557745139c846834..e47aa72ead06d42ff582ba1e74c2d30603595cf9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFRunLoop.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFRUNLOOP__)
@@ -31,8 +31,8 @@
 #include <CoreFoundation/CFArray.h>
 #include <CoreFoundation/CFDate.h>
 #include <CoreFoundation/CFString.h>
-#if defined(__MACH__)
-    #include <mach/port.h>
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+#include <mach/port.h>
 #endif
 
 CF_EXTERN_C_BEGIN
@@ -55,12 +55,12 @@ enum {
 
 /* Run Loop Observer Activities */
 enum {
-    kCFRunLoopEntry = (1 << 0),
-    kCFRunLoopBeforeTimers = (1 << 1),
-    kCFRunLoopBeforeSources = (1 << 2),
-    kCFRunLoopBeforeWaiting = (1 << 5),
-    kCFRunLoopAfterWaiting = (1 << 6),
-    kCFRunLoopExit = (1 << 7),
+    kCFRunLoopEntry = (1UL << 0),
+    kCFRunLoopBeforeTimers = (1UL << 1),
+    kCFRunLoopBeforeSources = (1UL << 2),
+    kCFRunLoopBeforeWaiting = (1UL << 5),
+    kCFRunLoopAfterWaiting = (1UL << 6),
+    kCFRunLoopExit = (1UL << 7),
     kCFRunLoopAllActivities = 0x0FFFFFFFU
 };
 typedef CFOptionFlags CFRunLoopActivity;
@@ -87,6 +87,10 @@ CF_EXPORT Boolean CFRunLoopIsWaiting(CFRunLoopRef rl);
 CF_EXPORT void CFRunLoopWakeUp(CFRunLoopRef rl);
 CF_EXPORT void CFRunLoopStop(CFRunLoopRef rl);
 
+#if __BLOCKS__ && MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED
+CF_EXPORT void CFRunLoopPerformBlock(CFRunLoopRef rl, CFTypeRef mode, void (^block)(void)) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER; 
+#endif
+
 CF_EXPORT Boolean CFRunLoopContainsSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef mode);
 CF_EXPORT void CFRunLoopAddSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef mode);
 CF_EXPORT void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef source, CFStringRef mode);
@@ -120,11 +124,11 @@ typedef struct {
     CFStringRef        (*copyDescription)(const void *info);
     Boolean    (*equal)(const void *info1, const void *info2);
     CFHashCode (*hash)(const void *info);
-#if defined(__MACH__)
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
     mach_port_t        (*getPort)(void *info);
     void *     (*perform)(void *msg, CFIndex size, CFAllocatorRef allocator, void *info);
 #else
-    HANDLE     (*getPort)(void *info);
+    void *     (*getPort)(void *info);
     void       (*perform)(void *info);
 #endif
 } CFRunLoopSourceContext1;
diff --git a/CFRunLoopPriv.h b/CFRunLoopPriv.h
deleted file mode 100644 (file)
index 9d516ee..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (c) 2008 Apple 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@
- */
-/*      CFRunLoopPriv.h
-        Copyright (c) 2006-2007, Apple Inc. All rights reserved.
-*/
-
-#if (DEPLOYMENT_TARGET_MACOSX || 0)
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-#import "CFObject.h"
-#include <CoreFoundation/CFRunLoop.h>
-#include <CoreFoundation/CFMachPort.h>
-#include <CoreFoundation/CFSocket.h>
-#include <CoreFoundation/CFArray.h>
-#include <CoreFoundation/CFBag.h>
-#include <mach/mach.h>
-#include <sys/event.h>
-#include <pthread.h>
-
-@class CFRunLoopSourceSet;
-typedef CFRunLoopSourceContext CFRunLoopSourceContext0;
-typedef CFMachPortContext CFRunLoopMachPortContext;
-typedef CFSocketContext CFRunLoopSocketContext;
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopSource : CFObject {
-    uint8_t _cfruntime_[8]; // large enough for 32-bit or 64-bit
-    int _kq;
-    mach_port_t _portset;
-    mach_port_t _port;
-    CFIndex _order;
-    uint8_t _invalid;
-    uint8_t _firing;
-    uint8_t _ownsPort;
-    uint8_t _async;
-}
-
-- (int)kqueue;
-- (mach_port_t)machPortSet;
-- (mach_port_t)machPort;
-
-- (void)setOrder:(CFIndex)o;
-- (CFIndex)order;
-
-- (void)setAsyncStrategy:(uint8_t)s;
-- (uint8_t)asyncStrategy;
-
-- (void)perform:(mach_msg_header_t *)msg;
-
-- (void)invalidate;
-- (Boolean)isValid;
-
-- (void)noteAddedToSourceSet:(CFRunLoopSourceSet *)ss;
-- (void)noteRemovedFromSourceSet:(CFRunLoopSourceSet *)ss;
-
-- (CFStringRef)copyPartialDebugDescription; // subclasses override
-- (CFStringRef)copyDebugDescription;
-
-@end
-
-@interface CFRunLoopVersion0SourceCFRef : CFRunLoopSource {
-    CFRunLoopSourceContext0 _context;
-}
-
-- (Boolean)setContext:(CFRunLoopSourceContext0)c;
-- (CFRunLoopSourceContext0)context;
-
-- (void)markReady;
-- (void)handle;
-
-- (void)scheduleInRunLoop:(CFRunLoopRef)rl mode:(CFStringRef)n;
-- (void)cancelFromRunLoop:(CFRunLoopRef)rl mode:(CFStringRef)n;
-
-@end
-
-@interface CFRunLoopVersion1SourceCFRef : CFRunLoopSource {
-    CFRunLoopSourceContext1 _context;
-}
-
-- (Boolean)setContext:(CFRunLoopSourceContext1)c;
-- (CFRunLoopSourceContext1)context;
-
-- (void)markReady;
-- (void)handle:(mach_msg_header_t *)msg;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopTimerSource : CFRunLoopSource {
-    CFAbsoluteTime _fireAT;
-    CFTimeInterval _interval;
-}
-
-- (void)setFireTime:(CFAbsoluteTime)at;
-- (CFAbsoluteTime)fireTime;
-
-- (void)setInterval:(CFTimeInterval)i;
-- (CFTimeInterval)interval;
-
-- (void)handle;
-
-@end
-
-@interface CFRunLoopTimerSourceCFRef : CFRunLoopTimerSource {
-    void *_function;
-    CFRunLoopTimerContext _context;
-}
-
-- (void)setFunction:(void *)f;
-- (void *)function;
-
-- (Boolean)setContext:(CFRunLoopTimerContext)c;
-- (CFRunLoopTimerContext)context;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopMachPortSource : CFRunLoopSource {
-    mach_port_t _notifyPort;
-    mach_port_t _oldNotifyPort;
-}
-
-+ (id)newWithPort:(mach_port_t)p;
-
-- (void)handle:(mach_msg_header_t *)msg;
-
-@end
-
-@interface CFRunLoopMachPortSourceCFRef : CFRunLoopMachPortSource {
-    void *_function;
-    CFRunLoopMachPortContext _context;
-    void *_invalidation;
-}
-
-- (void)setFunction:(void *)f;
-- (void *)function;
-
-- (Boolean)setContext:(CFRunLoopMachPortContext)c;
-- (CFRunLoopMachPortContext)context;
-
-- (void)setInvalidationFunction:(void *)f;
-- (void *)invalidationFunction;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopKEventSource : CFRunLoopSource {
-    struct kevent _filter;
-}
-
-- (Boolean)setFilter:(struct kevent)kev;
-- (struct kevent)filter;
-
-- (void)handle:(struct kevent *)kev;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopSignalSource : CFRunLoopSource {
-    int _signal;
-}
-
-- (Boolean)setSignal:(int)sig;
-- (int)signal;
-
-- (long)poll;
-
-- (void)handle:(long)n;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopProcessDeathSource : CFRunLoopSource {
-    int _pid;
-}
-
-- (Boolean)setProcessID:(int)pid;
-- (int)processID;
-
-- (void)handle;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopSocketSource : CFRunLoopSource {
-    int _socket;
-    uint8_t _ownsSocket;
-    uint8_t _enabledR;
-    uint8_t _enabledW;
-}
-
-+ (id)newWithSocket:(int)s;
-
-- (int)socket;
-- (CFDataRef)copyLocalAddress;
-- (CFDataRef)copyRemoteAddress;
-
-- (void)setReadEventsEnabled:(Boolean)b;
-- (Boolean)readEventsEnabled;
-
-- (void)setWriteEventsEnabled:(Boolean)b;
-- (Boolean)writeEventsEnabled;
-
-- (void)handleReadability:(CFIndex)amt endOfFile:(Boolean)b;
-- (void)performRead:(struct kevent *)kev;
-
-- (void)handleWritability:(CFIndex)amt endOfFile:(Boolean)b;
-- (void)performWrite:(struct kevent *)kev;
-
-@end
-
-@interface CFRunLoopSocketSourceCFRef : CFRunLoopSocketSource {
-    void *_function;
-    CFRunLoopSocketContext _context;
-    uint8_t _callbacks;
-    uint8_t _flags;
-    uint8_t _disabled;
-}
-
-- (void)setFunction:(void *)f;
-- (void *)function;
-
-- (Boolean)setContext:(CFRunLoopSocketContext)c;
-- (CFRunLoopSocketContext)context;
-
-- (void)setCallBackTypes:(uint8_t)f;
-- (uint8_t)callBackTypes;
-
-- (void)setFlags:(uint8_t)f;
-- (uint8_t)flags;
-
-- (void)setDisabledFlags:(uint8_t)f;
-- (uint8_t)disabledFlags;
-
-- (Boolean)handleAcceptError:(int)err;
-- (Boolean)handleReadError:(int)err;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopObserver : CFRunLoopSource {
-}
-
-- (void)observeEntry:(CFRunLoopSourceSet *)ss;
-- (void)observeBeforeWaiting:(CFRunLoopSourceSet *)ss;
-- (void)observeAfterWaiting:(CFRunLoopSourceSet *)ss;
-- (void)observeExit:(CFRunLoopSourceSet *)ss;
-
-@end
-
-@interface CFRunLoopObserverCFRef : CFRunLoopObserver {
-    void *_function;
-    CFRunLoopObserverContext _context;
-    CFOptionFlags _activities;
-    uint8_t _oneshot;
-}
-
-- (void)setFunction:(void *)f;
-- (void *)function;
-
-- (Boolean)setContext:(CFRunLoopObserverContext)c;
-- (CFRunLoopObserverContext)context;
-
-- (void)setActivities:(CFOptionFlags)a;
-- (CFOptionFlags)activities;
-
-- (void)setOneshot:(Boolean)b;
-- (Boolean)oneshot;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopSourceSet : CFRunLoopObserver {
-    CFMutableBagRef _sources;
-    CFStringRef _name;
-    pthread_t _thread;
-    CFMutableArrayRef _observers[4];
-    CFRunLoopTimerSource *_timeoutTimer;
-    CFRunLoopMachPortSource *_wakeupPort;
-    uint8_t _stopped;
-    uint8_t _waiting;
-}
-
-+ (void)removeSourceFromAllSets:(CFRunLoopSource *)src;
-
-- (void)setName:(CFStringRef)n;
-- (CFStringRef)name;
-
-- (void)setAffineThread:(pthread_t)t;
-- (pthread_t)affineThread;
-
-- (Boolean)containsObserver:(CFRunLoopObserver *)o;
-- (void)addObserver:(CFRunLoopObserver *)o activities:(CFRunLoopActivity)a;
-- (void)removeObserver:(CFRunLoopObserver *)o activities:(CFRunLoopActivity)a;
-
-- (Boolean)containsSource:(CFRunLoopSource *)src;
-- (void)addSource:(CFRunLoopSource *)src;
-- (void)removeSource:(CFRunLoopSource *)src;
-
-- (void)forEachSource:(Boolean (*)(CFRunLoopSource *, void *))f context:(void *)c;
-
-- (void)stop;
-- (void)wakeup;
-- (Boolean)isWaiting;
-- (Boolean)isEmpty;
-- (Boolean)hasInputAvailable;
-
-- (int32_t)serviceUntil:(CFAbsoluteTime)at handleOne:(Boolean)handleOne;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-@interface CFRunLoopCFRef : CFObject {
-    uint8_t _cfruntime_[8]; // large enough for 32-bit or 64-bit
-    pthread_t _thread;
-    void *_counterpart;
-    CFMutableArrayRef _sourceSets;
-    CFRunLoopSourceSet *_currentSet;
-    uint8_t _invalid;
-}
-
-- (void)setAffineThread:(pthread_t)t;
-- (pthread_t)affineThread;
-
-- (void)setCounterpart:(void *)c;
-- (void *)counterpart;
-
-- (void)invalidate;
-- (Boolean)isValid;
-
-- (CFArrayRef)copySourceSets;
-
-- (void)setCurrentSourceSet:(CFRunLoopSourceSet *)ss;
-- (CFRunLoopSourceSet *)currentSourceSet;
-
-- (CFRunLoopSourceSet *)lookupSourceSetWithName:(CFStringRef)n;
-- (CFRunLoopSourceSet *)lookupOrCreateSourceSetWithName:(CFStringRef)n;
-
-- (CFStringRef)copyDebugDescription;
-
-@end
-
-/* -------- -------- -------- -------- -------- -------- -------- -------- */
-
-#endif
-
index be667e179e159f849507644d0328431185bfac22..f2544ef48f4a3fc4ae5b3ef6025bc70966853a3e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFRuntime.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #define ENABLE_ZOMBIES 1
 
-#include "CFRuntime.h"
+#include <CoreFoundation/CFRuntime.h>
 #include "CFInternal.h"
+#include "CFBasicHash.h"
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <dlfcn.h>
 #include <mach-o/dyld.h>
-#include <monitor.h>
+#include <mach/mach.h>
 #include <crt_externs.h>
 #include <unistd.h>
-#include "auto_stubs.h"
+#include <objc/runtime.h>
+#include <sys/stat.h>
+#include <CoreFoundation/CFStringDefaultEncoding.h>
+#define objc_isAuto (0)
+#else
+#include <objc/runtime.h>
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#define _objc_getFreedObjectClass()       0
+#else
+extern Class _objc_getFreedObjectClass(void);
+#endif
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+extern void __CFRecordAllocationEvent(int eventnum, void *ptr, int64_t size, uint64_t data, const char *classname);
+#else
 #define __CFRecordAllocationEvent(a, b, c, d, e) ((void)0)
+#endif
+
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+extern void instrumentObjcMessageSends(BOOL flag);
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#include <Shellapi.h>
+#endif
 
 enum {
 // retain/release recording constants -- must match values
@@ -48,7 +75,44 @@ __kCFRetainEvent = 28,
 __kCFReleaseEvent = 29
 };
 
+#if DEPLOYMENT_TARGET_WINDOWS
+#include <malloc.h>
+#else
 #include <malloc/malloc.h>
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+
+bool __CFOASafe = false;
+
+void (*__CFObjectAllocRecordAllocationFunction)(int, void *, int64_t , uint64_t, const char *) = NULL;
+void (*__CFObjectAllocSetLastAllocEventNameFunction)(void *, const char *) = NULL;
+
+void __CFOAInitialize(void) {
+    static void (*dyfunc)(void) = (void *)~0;
+    if (NULL == __CFgetenv("OAKeepAllocationStatistics")) return;
+    if ((void *)~0 == dyfunc) {
+       dyfunc = dlsym(RTLD_DEFAULT, "_OAInitialize");
+    }
+    if (NULL != dyfunc) {
+       dyfunc();
+       __CFObjectAllocRecordAllocationFunction = dlsym(RTLD_DEFAULT, "_OARecordAllocationEvent");
+       __CFObjectAllocSetLastAllocEventNameFunction = dlsym(RTLD_DEFAULT, "_OASetLastAllocationEventName");
+       __CFOASafe = true;
+    }
+}
+
+void __CFRecordAllocationEvent(int eventnum, void *ptr, int64_t size, uint64_t data, const char *classname) {
+    if (!__CFOASafe || !__CFObjectAllocRecordAllocationFunction) return;
+    __CFObjectAllocRecordAllocationFunction(eventnum, ptr, size, data, classname);
+}
+
+void __CFSetLastAllocationEventName(void *ptr, const char *classname) {
+    if (!__CFOASafe || !__CFObjectAllocSetLastAllocEventNameFunction) return;
+    __CFObjectAllocSetLastAllocEventNameFunction(ptr, classname);
+}
+
+#endif
 
 extern void __HALT(void);
 
@@ -115,43 +179,40 @@ static const CFRuntimeClass __CFTypeClass = {
 };
 #endif //__cplusplus
 
+// the lock does not protect most reading of these; we just leak the old table to allow read-only accesses to continue to work
+static CFSpinLock_t __CFBigRuntimeFunnel = CFSpinLockInit;
 static CFRuntimeClass ** __CFRuntimeClassTable = NULL;
 int32_t __CFRuntimeClassTableSize = 0;
 static int32_t __CFRuntimeClassTableCount = 0;
 
-__private_extern__ void * (*__CFSendObjCMsg)(const void *, SEL, ...) = NULL;
+uintptr_t *__CFRuntimeObjCClassTable = NULL;
 
-__private_extern__ malloc_zone_t *__CFCollectableZone = NULL;
+__private_extern__ void * (*__CFSendObjCMsg)(const void *, SEL, ...) = NULL;
 
 bool (*__CFObjCIsCollectable)(void *) = NULL;
 
-static const void* objc_AssignIvar_none(const void *value, const void *base, const void **slot) { return (*slot = value); }
-const void* (*__CFObjCAssignIvar)(const void *value, const void *base, const void **slot) = objc_AssignIvar_none;
-
-static const void* objc_StrongAssign_none(const void *value, const void **slot) { return (*slot = value); }
-const void* (*__CFObjCStrongAssign)(const void *value, const void **slot) = objc_StrongAssign_none;
-
-void* (*__CFObjCMemmoveCollectable)(void *dst, const void *, size_t) = memmove;
-
-// GC: to be moved to objc if necessary.
-static void objc_WriteBarrierRange_none(void *ptr, size_t size) {}
-static void objc_WriteBarrierRange_auto(void *ptr, size_t size) { auto_zone_write_barrier_range(__CFCollectableZone, ptr, size); }
-void (*__CFObjCWriteBarrierRange)(void *, size_t) = objc_WriteBarrierRange_none;
-
-// Compiler uses this symbol name; must match compiler built-in decl
+// Compiler uses this symbol name; must match compiler built-in decl, so we use 'int'
 #if __LP64__
 int __CFConstantStringClassReference[24] = {0};
 #else
 int __CFConstantStringClassReference[12] = {0};
 #endif
 
-// #warning the whole business of reallocating the ClassTables is not thread-safe, because access to those values is not protected
+
+Boolean _CFIsObjC(CFTypeID typeID, void *obj) {
+    __CFSpinLock(&__CFBigRuntimeFunnel);
+    Boolean b = ((typeID >= (CFTypeID)__CFRuntimeClassTableSize) || (((CFRuntimeBase *)obj)->_cfisa != (uintptr_t)__CFRuntimeObjCClassTable[typeID] && ((CFRuntimeBase *)obj)->_cfisa > (uintptr_t)0xFFF));
+    __CFSpinUnlock(&__CFBigRuntimeFunnel);
+    return b;
+}
 
 CFTypeID _CFRuntimeRegisterClass(const CFRuntimeClass * const cls) {
 // version field must be 0
 // className must be pure ASCII string, non-null
+    __CFSpinLock(&__CFBigRuntimeFunnel);
     if (__CFMaxRuntimeTypes <= __CFRuntimeClassTableCount) {
        CFLog(kCFLogLevelWarning, CFSTR("*** CoreFoundation class table full; registration failing for class '%s'.  Program will crash soon."), cls->className);
+        __CFSpinUnlock(&__CFBigRuntimeFunnel);
        return _kCFRuntimeNotATypeID;
     }
     if (__CFRuntimeClassTableSize <= __CFRuntimeClassTableCount) {
@@ -161,6 +222,14 @@ CFTypeID _CFRuntimeRegisterClass(const CFRuntimeClass * const cls) {
        void *new_table1 = calloc(new_size, sizeof(CFRuntimeClass *));
        memmove(new_table1, __CFRuntimeClassTable, old_size * sizeof(CFRuntimeClass *));
        __CFRuntimeClassTable = (CFRuntimeClass**)new_table1;
+
+       void *new_table2 = calloc(new_size, sizeof(uintptr_t));
+       memmove(new_table2, __CFRuntimeObjCClassTable, old_size * sizeof(uintptr_t));
+        for (CFIndex idx = old_size; idx < new_size; idx++) {
+            ((uintptr_t *)new_table2)[idx] = __CFRuntimeObjCClassTable[0];
+        }
+       __CFRuntimeObjCClassTable = (uintptr_t *)new_table2;
+
        __CFRuntimeClassTableSize = new_size;
        // The old value of __CFRuntimeClassTable is intentionally leaked
        // for thread-safety reasons:
@@ -175,19 +244,25 @@ CFTypeID _CFRuntimeRegisterClass(const CFRuntimeClass * const cls) {
        // this thread gets done reallocating here, so freeing is unsafe.
     }
     __CFRuntimeClassTable[__CFRuntimeClassTableCount++] = (CFRuntimeClass *)cls;
-    return __CFRuntimeClassTableCount - 1;
+    CFTypeID typeID = __CFRuntimeClassTableCount - 1;
+    __CFSpinUnlock(&__CFBigRuntimeFunnel);
+    return typeID;
 }
 
 void _CFRuntimeBridgeClasses(CFTypeID cf_typeID, const char *objc_classname) {
-    return;
+    __CFSpinLock(&__CFBigRuntimeFunnel);
+    __CFRuntimeObjCClassTable[cf_typeID] = (uintptr_t)objc_getFutureClass(objc_classname);
+    __CFSpinUnlock(&__CFBigRuntimeFunnel);
 }
 
 const CFRuntimeClass * _CFRuntimeGetClassWithTypeID(CFTypeID typeID) {
-    return __CFRuntimeClassTable[typeID];
+    return __CFRuntimeClassTable[typeID]; // hopelessly unthreadsafe
 }
 
 void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID) {
+    __CFSpinLock(&__CFBigRuntimeFunnel);
     __CFRuntimeClassTable[typeID] = NULL;
+    __CFSpinUnlock(&__CFBigRuntimeFunnel);
 }
 
 
@@ -201,41 +276,57 @@ void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID) {
  */
 
 static uint32_t __CFZombieLevel = 0x0;
-static uint8_t __CFZombieEnabled = 0;
-static uint8_t __CFDeallocateZombies = 0;
+__private_extern__ uint8_t __CFZombieEnabled = 0;
+__private_extern__ uint8_t __CFDeallocateZombies = 0;
+#if !__OBJC2__
 static void *_original_objc_dealloc = 0;
+#endif
 
 #endif /* DEBUG */
 
 // XXX_PCB:  use the class version field as a bitmask, to allow classes to opt-in for GC scanning.
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+CF_INLINE CFOptionFlags CF_GET_COLLECTABLE_MEMORY_TYPE(const CFRuntimeClass *cls)
+{
+    return ((cls->version & _kCFRuntimeScannedObject) ? __kCFAllocatorGCScannedMemory : 0) | __kCFAllocatorGCObjectMemory;
+}
+#else
 #define CF_GET_COLLECTABLE_MEMORY_TYPE(x) (0)
+#endif
 
 CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CFIndex extraBytes, unsigned char *category) {
-    CFRuntimeBase *memory;
-    Boolean usesSystemDefaultAllocator;
-    CFIndex size;
-
     CFAssert1(typeID != _kCFRuntimeNotATypeID, __kCFLogAssertion, "%s(): Uninitialized type id", __PRETTY_FUNCTION__);
-
-    if (NULL == __CFRuntimeClassTable[typeID]) {
+    CFRuntimeClass *cls = __CFRuntimeClassTable[typeID];
+    if (NULL == cls) {
        return NULL;
     }
     allocator = (NULL == allocator) ? __CFGetDefaultAllocator() : allocator;
-    usesSystemDefaultAllocator = (allocator == kCFAllocatorSystemDefault);
-    size = sizeof(CFRuntimeBase) + extraBytes + (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef));
+    if (kCFAllocatorNull == allocator) {
+       return NULL;
+    }
+    Boolean usesSystemDefaultAllocator = (allocator == kCFAllocatorSystemDefault);
+    CFIndex size = sizeof(CFRuntimeBase) + extraBytes + (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef));
     size = (size + 0xF) & ~0xF;        // CF objects are multiples of 16 in size
     // CFType version 0 objects are unscanned by default since they don't have write-barriers and hard retain their innards
     // CFType version 1 objects are scanned and use hand coded write-barriers to store collectable storage within
-    memory = (CFRuntimeBase *)CFAllocatorAllocate(allocator, size, CF_GET_COLLECTABLE_MEMORY_TYPE(__CFRuntimeClassTable[typeID]));
+    CFRuntimeBase *memory = (CFRuntimeBase *)CFAllocatorAllocate(allocator, size, CF_GET_COLLECTABLE_MEMORY_TYPE(cls));
     if (NULL == memory) {
+        CFStringRef msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for %s failed"), size, category ? (char *)category : (char *)cls->className);
+       {
+            CFLog(kCFLogLevelCritical, CFSTR("%@"), msg);
+            HALT;
+        }
+        CFRelease(msg);
        return NULL;
     }
-    memset(memory, 0, malloc_size(memory));
+    if (!kCFUseCollectableAllocator || !CF_IS_COLLECTABLE_ALLOCATOR(allocator) || !(CF_GET_COLLECTABLE_MEMORY_TYPE(cls) & __kCFAllocatorGCScannedMemory)) {
+       memset(memory, 0, size);
+    }
     if (__CFOASafe && category) {
        __CFSetLastAllocationEventName(memory, (char *)category);
     } else if (__CFOASafe) {
-       __CFSetLastAllocationEventName(memory, (char *)__CFRuntimeClassTable[typeID]->className);
+       __CFSetLastAllocationEventName(memory, (char *)cls->className);
     }
     if (!usesSystemDefaultAllocator) {
         // add space to hold allocator ref for non-standard allocators.
@@ -250,18 +341,18 @@ CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CF
 #else
     *(uint32_t *)(memory->_cfinfo) = (uint32_t)((1 << 24) + ((typeID & 0xFFFF) << 8) + (usesSystemDefaultAllocator ? 0x80 : 0x00));
 #endif
-    if (NULL != __CFRuntimeClassTable[typeID]->init) {
-       (__CFRuntimeClassTable[typeID]->init)(memory);
+    if (NULL != cls->init) {
+       (cls->init)(memory);
     }
     return memory;
 }
 
 void _CFRuntimeInitStaticInstance(void *ptr, CFTypeID typeID) {
-    CFRuntimeBase *memory = (CFRuntimeBase *)ptr;
     CFAssert1(typeID != _kCFRuntimeNotATypeID, __kCFLogAssertion, "%s(): Uninitialized type id", __PRETTY_FUNCTION__);
     if (NULL == __CFRuntimeClassTable[typeID]) {
        return;
     }
+    CFRuntimeBase *memory = (CFRuntimeBase *)ptr;
     memory->_cfisa = __CFISAForTypeID(typeID);
     *(uint32_t *)(memory->_cfinfo) = (uint32_t)((0 << 24) + ((typeID & 0xFFFF) << 8) + 0x80);
 #if __LP64__
@@ -284,12 +375,75 @@ __private_extern__ Boolean __CFRuntimeIsFreedObject(id anObject) {
    if (cls == freedClass) return true;
    // in 64-bit, a future class has nil isa, and calling class_getName() on
    // such will crash so we do this test; zombie classes are not future classes
-   if (objc_getClass((id)cls) == nil) return false;
+   if (object_getClass((id)cls) == nil) return false;
    const char *cname = class_getName(cls);
    if (cname && 0 == strncmp(cname, "_NSZombie_", 10)) return true;
    return false;
 }
 
+
+enum {
+    __kCFObjectRetainedEvent = 12,
+    __kCFObjectReleasedEvent = 13
+};
+
+#if DEPLOYMENT_TARGET_MACOSX
+#define NUM_EXTERN_TABLES 8
+#define EXTERN_TABLE_IDX(O) (((uintptr_t)(O) >> 8) & 0x7)
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#define NUM_EXTERN_TABLES 1
+#define EXTERN_TABLE_IDX(O) 0
+#else
+#error
+#endif
+
+// we disguise pointers so that programs like 'leaks' forget about these references
+#define DISGUISE(O) (~(uintptr_t)(O))
+
+static struct {
+    CFSpinLock_t lock;
+    CFBasicHashRef table;
+    uint8_t padding[64 - sizeof(CFBasicHashRef) - sizeof(CFSpinLock_t)];
+} __NSRetainCounters[NUM_EXTERN_TABLES];
+
+CF_EXPORT uintptr_t __CFDoExternRefOperation(uintptr_t op, id obj) {
+    if (nil == obj) HALT;
+    uintptr_t idx = EXTERN_TABLE_IDX(obj);
+    uintptr_t disguised = DISGUISE(obj);
+#if DEPLOYMENT_TARGET_WINDOWS
+    // assume threaded on windows for now
+    int thr = 1;
+#else
+    int thr = pthread_is_threaded_np();
+#endif
+    CFSpinLock_t *lock = &__NSRetainCounters[idx].lock;
+    CFBasicHashRef table = __NSRetainCounters[idx].table;
+    uintptr_t count;
+    switch (op) {
+    case 300:   // increment
+    case 350:   // increment, no event
+        if (thr) __CFSpinLock(lock);
+       CFBasicHashAddValue(table, disguised, disguised);
+        if (thr) __CFSpinUnlock(lock);
+        if (__CFOASafe && op != 350) __CFRecordAllocationEvent(__kCFObjectRetainedEvent, obj, 0, 0, NULL);
+        return (uintptr_t)obj;
+    case 400:   // decrement
+        if (__CFOASafe) __CFRecordAllocationEvent(__kCFObjectReleasedEvent, obj, 0, 0, NULL);
+    case 450:   // decrement, no event
+        if (thr) __CFSpinLock(lock);
+        count = (uintptr_t)CFBasicHashRemoveValue(table, disguised);
+        if (thr) __CFSpinUnlock(lock);
+        return 0 == count;
+    case 500:
+        if (thr) __CFSpinLock(lock);
+        count = (uintptr_t)CFBasicHashGetCountOfKey(table, disguised);
+        if (thr) __CFSpinUnlock(lock);
+        return count;
+    }
+    return 0;
+}
+
+
 CFTypeID __CFGenericTypeID(const void *cf) {
     return (*(uint32_t *)(((CFRuntimeBase *)cf)->_cfinfo) >> 8) & 0xFFFF;
 }
@@ -311,10 +465,12 @@ __private_extern__ void __CFGenericValidateType_(CFTypeRef cf, CFTypeID type, co
 #define __CFGenericAssertIsCF(cf) \
     CFAssert2(cf != NULL && (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]) && (__kCFNotATypeTypeID != __CFGenericTypeID_inline(cf)) && (__kCFTypeTypeID != __CFGenericTypeID_inline(cf)), __kCFLogAssertion, "%s(): pointer %p is not a CF object", __PRETTY_FUNCTION__, cf);
 
+
 #define CFTYPE_IS_OBJC(obj) (false)
 #define CFTYPE_OBJC_FUNCDISPATCH0(rettype, obj, sel) do {} while (0)
 #define CFTYPE_OBJC_FUNCDISPATCH1(rettype, obj, sel, a1) do {} while (0)
 
+
 CFTypeID CFGetTypeID(CFTypeRef cf) {
 #if defined(DEBUG)
     if (NULL == cf) HALT;
@@ -329,20 +485,22 @@ CFStringRef CFCopyTypeIDDescription(CFTypeID type) {
     return CFStringCreateWithCString(kCFAllocatorSystemDefault, __CFRuntimeClassTable[type]->className, kCFStringEncodingASCII);
 }
 
-#define DISGUISE(object)       ((void *)(((uintptr_t)object) + 1))
-#define UNDISGUISE(disguised)  ((id)(((uintptr_t)disguised) - 1))
-
 // Bit 31 (highest bit) in second word of cf instance indicates external ref count
 
 CF_EXPORT void _CFRelease(CFTypeRef cf);
 CF_EXPORT CFTypeRef _CFRetain(CFTypeRef cf);
-CF_EXPORT CFHashCode _CFHash(CFTypeRef cf);
 
 CFTypeRef CFRetain(CFTypeRef cf) {
+    if (NULL == cf) HALT;
     if (CF_IS_COLLECTABLE(cf)) {
-        // always honor CFRetain's with a GC-visible retain.
-        auto_zone_retain(__CFCollectableZone, (void*)cf);
-        return cf;
+       if (CFTYPE_IS_OBJC(cf)) {
+           // always honor CFRetain's with a GC-visible retain.
+           auto_zone_retain(auto_zone(), (void*)cf);
+           return cf;
+       } else {
+           // special case CF objects for performance.
+           return _CFRetain(cf);
+       }
     }
     CFTYPE_OBJC_FUNCDISPATCH0(CFTypeRef, cf, "retain");
     if (cf) __CFGenericAssertIsCF(cf);
@@ -352,25 +510,38 @@ CFTypeRef CFRetain(CFTypeRef cf) {
 __private_extern__ void __CFAllocatorDeallocate(CFTypeRef cf);
 
 void CFRelease(CFTypeRef cf) {
-#if !defined(__WIN32__)
+    if (NULL == cf) HALT;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     if (CF_IS_COLLECTABLE(cf)) {
-        // release the GC-visible reference.
-        if (auto_zone_release(__CFCollectableZone, (void*)cf) == 0 && !CFTYPE_IS_OBJC(cf)) {
-            CFRuntimeClass *cfClass = __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)];
-            if (cfClass->version & _kCFRuntimeResourcefulObject) {
-                if (cfClass->reclaim) cfClass->reclaim(cf);
-            }
+        if (CFTYPE_IS_OBJC(cf)) {
+            // release the GC-visible reference.
+            auto_zone_release(auto_zone(), (void*)cf);
+        } else {
+            // special-case CF objects for better performance.
+            _CFRelease(cf);
         }
         return;
     }
+#endif
+#if 0
+    void **addrs[2] = {&&start, &&end};
+    start:;
+    if (addrs[0] <= __builtin_return_address(0) && __builtin_return_address(0) <= addrs[1]) {
+       CFLog(3, CFSTR("*** WARNING: Recursion in CFRelease(%p) : %p '%s' : 0x%08lx 0x%08lx 0x%08lx 0x%08lx 0x%08lx 0x%08lx"), cf, object_getClass(cf), object_getClassName(cf), ((uintptr_t *)cf)[0], ((uintptr_t *)cf)[1], ((uintptr_t *)cf)[2], ((uintptr_t *)cf)[3], ((uintptr_t *)cf)[4], ((uintptr_t *)cf)[5]);
+       HALT;
+    }
 #endif
     CFTYPE_OBJC_FUNCDISPATCH0(void, cf, "release");
     if (cf) __CFGenericAssertIsCF(cf);
     _CFRelease(cf);
+#if 0
+    end:;
+#endif
 }
 
 
 __private_extern__ const void *__CFStringCollectionCopy(CFAllocatorRef allocator, const void *ptr) {
+    if (NULL == ptr) HALT;
     CFStringRef theString = (CFStringRef)ptr;
     CFStringRef result = CFStringCreateCopy(allocator, theString);
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
@@ -382,17 +553,18 @@ __private_extern__ const void *__CFStringCollectionCopy(CFAllocatorRef allocator
 extern void CFCollection_non_gc_storage_error(void);
 
 __private_extern__ const void *__CFTypeCollectionRetain(CFAllocatorRef allocator, const void *ptr) {
+    if (NULL == ptr) HALT;
     CFTypeRef cf = (CFTypeRef)ptr;
     // only collections allocated in the GC zone can opt-out of reference counting.
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
         if (CFTYPE_IS_OBJC(cf)) return cf;  // do nothing for OBJC objects.
-        if (auto_zone_is_valid_pointer(__CFCollectableZone, ptr)) {
+        if (auto_zone_is_valid_pointer(auto_zone(), ptr)) {
             CFRuntimeClass *cfClass = __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)];
             if (cfClass->version & _kCFRuntimeResourcefulObject) {
                 // GC: If this a CF object in the GC heap that is marked resourceful, then
                 // it must be retained keep it alive in a CF collection.
-                // We're basically inlining CFRetain() here, to avoid an extra heap membership test.
-                auto_zone_retain(__CFCollectableZone, (void*)cf);
+                // We're basically inlining CFRetain() here, to avoid extra heap membership tests.
+                _CFRetain(cf);
             }
             else
                 ;   // don't retain normal CF objects
@@ -417,22 +589,24 @@ __private_extern__ const void *__CFTypeCollectionRetain(CFAllocatorRef allocator
 
 
 __private_extern__ void __CFTypeCollectionRelease(CFAllocatorRef allocator, const void *ptr) {
+    if (NULL == ptr) HALT;
     CFTypeRef cf = (CFTypeRef)ptr;
     // only collections allocated in the GC zone can opt-out of reference counting.
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
         if (CFTYPE_IS_OBJC(cf)) return; // do nothing for OBJC objects.
-        if (auto_zone_is_valid_pointer(__CFCollectableZone, cf)) {
-#if !defined(__WIN32__)
+        if (auto_zone_is_valid_pointer(auto_zone(), cf)) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
             // GC: If this a CF object in the GC heap that is marked uncollectable, then
             // must balance the retain done in __CFTypeCollectionRetain().
-            // We're basically inlining CFRelease() here, to avoid an extra heap membership test.
+            // We're basically inlining CFRelease() here, to avoid extra heap membership tests.
             CFRuntimeClass *cfClass = __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)];
-            if (cfClass->version & _kCFRuntimeResourcefulObject && auto_zone_release(__CFCollectableZone, (void*)cf) == 0) {
-                // ResourceFull objects trigger 'reclaim' on transition to zero
-                if (cfClass->reclaim) cfClass->reclaim(cf);
+            if (cfClass->version & _kCFRuntimeResourcefulObject) {
+                // reclaim is called by _CFRelease(), which must be called to keep the
+                // CF and GC retain counts in sync.
+                _CFRelease(cf);
+            } else {
+                // avoid releasing normal CF objects.  Like other collections, for example
             }
-            else // avoid releasing normal CF objects.  Like other collections, for example
-                ;
             return;
 #endif
         } else {
@@ -454,6 +628,7 @@ static CFMutableBagRef __CFRuntimeExternRefCountTable = NULL;
 #endif
 
 static uint64_t __CFGetFullRetainCount(CFTypeRef cf) {
+    if (NULL == cf) HALT;
 #if __LP64__
     uint32_t lowBits = ((CFRuntimeBase *)cf)->_rc;
     if (0 == lowBits) {
@@ -467,9 +642,7 @@ static uint64_t __CFGetFullRetainCount(CFTypeRef cf) {
     }
     uint64_t highBits = 0;
     if ((lowBits & 0x80) != 0) {
-       __CFSpinLock(&__CFRuntimeExternRefCountTableLock);
-       highBits = (uint64_t)CFBagGetCountOfValue(__CFRuntimeExternRefCountTable, DISGUISE(cf));
-       __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock);
+        highBits = __CFDoExternRefOperation(500, (id)cf);
     }
     uint64_t compositeRC = (lowBits & 0x7f) + (highBits << 6);
     return compositeRC;
@@ -478,31 +651,32 @@ static uint64_t __CFGetFullRetainCount(CFTypeRef cf) {
 
 CFTypeRef _CFRetainGC(CFTypeRef cf) {
 #if defined(DEBUG)
-    if (CF_USING_COLLECTABLE_MEMORY && !CF_IS_COLLECTABLE(cf)) {
+    if (kCFUseCollectableAllocator && !CF_IS_COLLECTABLE(cf)) {
         fprintf(stderr, "non-auto object %p passed to _CFRetainGC.\n", cf);
         HALT;
     }
 #endif
-    return CF_USING_COLLECTABLE_MEMORY ? cf : CFRetain(cf);
+    return kCFUseCollectableAllocator ? cf : CFRetain(cf);
 }
 
 void _CFReleaseGC(CFTypeRef cf) {
 #if defined(DEBUG)
-    if (CF_USING_COLLECTABLE_MEMORY && !CF_IS_COLLECTABLE(cf)) {
+    if (kCFUseCollectableAllocator && !CF_IS_COLLECTABLE(cf)) {
         fprintf(stderr, "non-auto object %p passed to _CFReleaseGC.\n", cf);
         HALT;
     }
 #endif
-    if (!CF_USING_COLLECTABLE_MEMORY) CFRelease(cf);
+    if (!kCFUseCollectableAllocator) CFRelease(cf);
 }
 
 CFIndex CFGetRetainCount(CFTypeRef cf) {
-    if (NULL == cf) return 0;
+    if (NULL == cf) HALT;
     if (CF_IS_COLLECTABLE(cf)) {
-        return auto_zone_retain_count(__CFCollectableZone, cf);
+        if (CFTYPE_IS_OBJC(cf)) return auto_zone_retain_count(auto_zone(), cf);
+    } else {
+       CFTYPE_OBJC_FUNCDISPATCH0(CFIndex, cf, "retainCount");
+       __CFGenericAssertIsCF(cf);
     }
-    CFTYPE_OBJC_FUNCDISPATCH0(CFIndex, cf, "retainCount");
-    __CFGenericAssertIsCF(cf);
     uint64_t rc = __CFGetFullRetainCount(cf);
     return (rc < (uint64_t)LONG_MAX) ? (CFIndex)rc : (CFIndex)LONG_MAX;
 }
@@ -510,6 +684,7 @@ CFIndex CFGetRetainCount(CFTypeRef cf) {
 CFTypeRef CFMakeCollectable(CFTypeRef cf) {
     if (NULL == cf) return NULL;
     if (CF_IS_COLLECTABLE(cf)) {
+        objc_assertRegisteredThreadWithCollector();
 #if defined(DEBUG)
         CFAllocatorRef allocator = CFGetAllocator(cf);
         if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
@@ -525,20 +700,26 @@ CFTypeRef CFMakeCollectable(CFTypeRef cf) {
                 HALT;
             }
         }
-        if (auto_zone_retain_count(__CFCollectableZone, cf) == 0) {
+        if (CFGetRetainCount(cf) == 0) {
             CFLog(kCFLogLevelWarning, CFSTR("object %p with 0 retain-count passed to CFMakeCollectable."), cf);
             return cf;
         }
-        auto_zone_release(__CFCollectableZone, (void *)cf);
+        CFRelease(cf);
+    }
+    return cf;
+}
+
+CFTypeRef CFMakeUncollectable(CFTypeRef cf) {
+    if (NULL == cf) return NULL;
+    if (CF_IS_COLLECTABLE(cf)) {
+        CFRetain(cf);
     }
     return cf;
 }
 
 Boolean CFEqual(CFTypeRef cf1, CFTypeRef cf2) {
-#if defined(DEBUG)
     if (NULL == cf1) HALT;
     if (NULL == cf2) HALT;
-#endif
     if (cf1 == cf2) return true;
     CFTYPE_OBJC_FUNCDISPATCH1(Boolean, cf1, "isEqual:", cf2);
     CFTYPE_OBJC_FUNCDISPATCH1(Boolean, cf2, "isEqual:", cf1);
@@ -552,16 +733,26 @@ Boolean CFEqual(CFTypeRef cf1, CFTypeRef cf2) {
 }
 
 CFHashCode CFHash(CFTypeRef cf) {
+    if (NULL == cf) HALT;
     CFTYPE_OBJC_FUNCDISPATCH0(CFHashCode, cf, "hash");
     __CFGenericAssertIsCF(cf);
-    return _CFHash(cf);
+    if (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->hash) {
+       return __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->hash(cf);
+    }
+    return (CFHashCode)cf;
 }
 
 // definition: produces a normally non-NULL debugging description of the object
 CFStringRef CFCopyDescription(CFTypeRef cf) {
-#if defined(DEBUG)
     if (NULL == cf) HALT;
-#endif
+    if (CFTYPE_IS_OBJC(cf)) {
+        static SEL s = NULL;
+        CFStringRef (*func)(void *, SEL) = (CFStringRef (*)(void *, SEL))objc_msgSend;
+        if (!s) s = sel_registerName("_copyDescription");
+        CFStringRef result = func((void *)cf, s);
+        return result;
+    }
+    // CFTYPE_OBJC_FUNCDISPATCH0(CFStringRef, cf, "_copyDescription");  // XXX returns 0 refcounted item under GC
     __CFGenericAssertIsCF(cf);
     if (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->copyDebugDesc) {
        CFStringRef result;
@@ -573,9 +764,16 @@ CFStringRef CFCopyDescription(CFTypeRef cf) {
 
 // Definition: if type produces a formatting description, return that string, otherwise NULL
 __private_extern__ CFStringRef __CFCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
-#if defined(DEBUG)
     if (NULL == cf) HALT;
-#endif
+    if (CFTYPE_IS_OBJC(cf)) {
+       static SEL s = NULL, r = NULL;
+       CFStringRef (*func)(void *, SEL, CFDictionaryRef) = (CFStringRef (*)(void *, SEL, CFDictionaryRef))objc_msgSend;
+       BOOL (*rfunc)(void *, SEL, SEL) = (BOOL (*)(void *, SEL, SEL))objc_msgSend;
+       if (!s) s = sel_registerName("_copyFormattingDescription:");
+       if (!r) r = sel_registerName("respondsToSelector:");
+       if (s && rfunc((void *)cf, r, s)) return func((void *)cf, s, formatOptions);
+       return NULL;
+    }
     __CFGenericAssertIsCF(cf);
     if (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->copyFormattingDesc) {
        return __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->copyFormattingDesc(cf, formatOptions);
@@ -587,6 +785,9 @@ extern CFAllocatorRef __CFAllocatorGetAllocator(CFTypeRef);
 
 CFAllocatorRef CFGetAllocator(CFTypeRef cf) {
     if (NULL == cf) return kCFAllocatorSystemDefault;
+// CF: need to get allocator from objc objects in better way...how?
+// -> bridging of CFAllocators and malloc_zone_t will help this
+    if (CFTYPE_IS_OBJC(cf)) return __CFGetDefaultAllocator();
     if (__kCFAllocatorTypeID_CONST == __CFGenericTypeID_inline(cf)) {
        return __CFAllocatorGetAllocator(cf);
     }
@@ -598,78 +799,189 @@ extern void __CFNullInitialize(void);
 extern void __CFAllocatorInitialize(void);
 extern void __CFStringInitialize(void);
 extern void __CFArrayInitialize(void);
-extern void __CFBagInitialize(void);
 extern void __CFBooleanInitialize(void);
 extern void __CFCharacterSetInitialize(void);
 extern void __CFDataInitialize(void);
-extern void __CFDateInitialize(void);
-extern void __CFDictionaryInitialize(void);
 extern void __CFNumberInitialize(void);
-extern void __CFSetInitialize(void);
 extern void __CFStorageInitialize(void);
 extern void __CFErrorInitialize(void);
-extern void __CFTimeZoneInitialize(void);
 extern void __CFTreeInitialize(void);
 extern void __CFURLInitialize(void);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 extern void __CFMachPortInitialize(void);
 #endif
-#if DEPLOYMENT_TARGET_MACOSX
 extern void __CFMessagePortInitialize(void);
-#endif
-#if DEPLOYMENT_TARGET_MACOSX || defined(__WIN32__)
 extern void __CFRunLoopInitialize(void);
 extern void __CFRunLoopObserverInitialize(void);
 extern void __CFRunLoopSourceInitialize(void);
 extern void __CFRunLoopTimerInitialize(void);
-extern void __CFSocketInitialize(void);
-#endif
 extern void __CFBundleInitialize(void);
 extern void __CFPlugInInitialize(void);
 extern void __CFPlugInInstanceInitialize(void);
 extern void __CFUUIDInitialize(void);
 extern void __CFBinaryHeapInitialize(void);
 extern void __CFBitVectorInitialize(void);
+#if DEPLOYMENT_TARGET_WINDOWS
+extern void __CFBaseCleanup(void);
+#endif
 extern void __CFStreamInitialize(void);
 
-static void __exceptionInit(void) {}
-static void __collatorInit(void) {}
-static void __forwarding_prep_0___(void) {}
-static void __forwarding_prep_1___(void) {}
-static void __NSFastEnumerationMutationHandler(id obj) {}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+__private_extern__ uint8_t __CF120290 = false;
+__private_extern__ uint8_t __CF120291 = false;
+__private_extern__ uint8_t __CF120293 = false;
+__private_extern__ char * __crashreporter_info__ = NULL;
+asm(".desc ___crashreporter_info__, 0x10");
+
+static void __01121__(void) {
+    __CF120291 = pthread_is_threaded_np() ? true : false;
+}
+
+static void __01123__(void) {
+    // Ideally, child-side atfork handlers should be async-cancel-safe, as fork()
+    // is async-cancel-safe and can be called from signal handlers.  See also
+    // http://standards.ieee.org/reading/ieee/interp/1003-1c-95_int/pasc-1003.1c-37.html
+    // This is not a problem for CF.
+    if (__CF120290) {
+       __CF120293 = true;
+       if (__CF120291) {
+           __crashreporter_info__ = "*** multi-threaded process forked ***";
+       } else {
+           __crashreporter_info__ = "*** single-threaded process forked ***";
+       }
+    }
+}
+
+#define EXEC_WARNING_STRING_1 "The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().\n"
+#define EXEC_WARNING_STRING_2 "Break on __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__() to debug.\n"
+
+__private_extern__ void __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__(void) {
+    write(2, EXEC_WARNING_STRING_1, sizeof(EXEC_WARNING_STRING_1) - 1);
+    write(2, EXEC_WARNING_STRING_2, sizeof(EXEC_WARNING_STRING_2) - 1);
+//    HALT;
+}
+#endif
+
+
+CF_EXPORT const void *__CFArgStuff;
 const void *__CFArgStuff = NULL;
 __private_extern__ void *__CFAppleLanguages = NULL;
 
-bool kCFUseCollectableAllocator = false;
+static struct {
+    const char *name;
+    const char *value;
+} __CFEnv[] = {
+    {"PATH", NULL},
+    {"HOME", NULL},
+    {"USER", NULL},
+    {"HOMEPATH", NULL},
+    {"HOMEDRIVE", NULL},
+    {"USERNAME", NULL},
+    {"TZFILE", NULL},
+    {"TZ", NULL},
+    {"NEXT_ROOT", NULL},
+    {"DYLD_IMAGE_SUFFIX", NULL},
+    {"CFProcessPath", NULL},
+    {"CFFIXED_USER_HOME", NULL},
+    {"CFNETWORK_LIBRARY_PATH", NULL},
+    {"CFUUIDVersionNumber", NULL},
+    {"CFDebugNamedDataSharing", NULL},
+    {"CFPropertyListAllowImmutableCollections", NULL},
+    {"CFBundleUseDYLD", NULL},
+    {"CFBundleDisableStringsSharing", NULL},
+    {"CFCharacterSetCheckForExpandedSet", NULL},
+    {"__CF_DEBUG_EXPANDED_SET", NULL},
+    {"CFStringDisableROM", NULL},
+    {"CF_CHARSET_PATH", NULL},
+    {"__CF_USER_TEXT_ENCODING", NULL},
+    {NULL, NULL}, // the last one is for optional "COMMAND_MODE" "legacy", do not use this slot, insert before
+};
+
+__private_extern__ const char *__CFgetenv(const char *n) {
+    for (CFIndex idx = 0; idx < sizeof(__CFEnv) / sizeof(__CFEnv[0]); idx++) {
+       if (__CFEnv[idx].name && 0 == strcmp(n, __CFEnv[idx].name)) return __CFEnv[idx].value;
+    }
+    return getenv(n);
+}
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#define kNilPthreadT  { nil, nil }
+#else
+#define kNilPthreadT  (pthread_t)0
+#endif
+
+
+CF_EXPORT pthread_t _CFMainPThread;
+pthread_t _CFMainPThread = kNilPthreadT;
 
+CF_EXPORT bool kCFUseCollectableAllocator = false;
+
+__private_extern__ Boolean __CFProphylacticAutofsAccess = false;
 
 #if DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 static void __CFInitialize(void) __attribute__ ((constructor));
 static
 #endif
+#if DEPLOYMENT_TARGET_WINDOWS
+CF_EXPORT
+#endif
 void __CFInitialize(void) {
     static int __done = 0;
 
     if (!__done) {
         __done = 1;
 
+       if (!pthread_main_np()) HALT;   // CoreFoundation must be initialized on the main thread
+
+       _CFMainPThread = pthread_self();
+
+        __CFProphylacticAutofsAccess = true;
+
+       for (CFIndex idx = 0; idx < sizeof(__CFEnv) / sizeof(__CFEnv[0]); idx++) {
+           __CFEnv[idx].value = __CFEnv[idx].name ? getenv(__CFEnv[idx].name) : NULL;
+       }
+
+        kCFUseCollectableAllocator = objc_collectingEnabled();
+        if (kCFUseCollectableAllocator) {
+            __CFObjCIsCollectable = (bool (*)(void *))objc_isAuto;
+        }
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+       UInt32 s, r;
+       __CFStringGetUserDefaultEncoding(&s, &r); // force the potential setenv to occur early
+       pthread_atfork(__01121__, NULL, __01123__);
+        const char *value2 = __CFgetenv("NSObjCMessageLoggingEnabled");
+        if (value2 && (*value2 == 'Y' || *value2 == 'y')) instrumentObjcMessageSends(1);
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#endif
+
 #if defined(DEBUG) || defined(ENABLE_ZOMBIES)
-       const char *value = getenv("NSZombieEnabled");
+       const char *value = __CFgetenv("NSZombieEnabled");
        if (value && (*value == 'Y' || *value == 'y')) __CFZombieEnabled = 0xff;
-       value = getenv("NSDeallocateZombies");
+       value = __CFgetenv("NSDeallocateZombies");
        if (value && (*value == 'Y' || *value == 'y')) __CFDeallocateZombies = 0xff;
+#if !__OBJC2__
+       _original_objc_dealloc = (void *)_dealloc;
+#endif
 
-       value = getenv("CFZombieLevel");
+       value = __CFgetenv("CFZombieLevel");
        if (NULL != value) {
            __CFZombieLevel = (uint32_t)strtoul_l(value, NULL, 0, NULL);
        }
        if (0x0 == __CFZombieLevel) __CFZombieLevel = 0x0000FC00; // default
+
 #endif
 
         __CFRuntimeClassTableSize = 1024;
         __CFRuntimeClassTable = (CFRuntimeClass **)calloc(__CFRuntimeClassTableSize, sizeof(CFRuntimeClass *));
+       __CFRuntimeObjCClassTable = (uintptr_t *)calloc(__CFRuntimeClassTableSize, sizeof(uintptr_t));
         __CFBaseInitialize();
 
+        _CFRuntimeBridgeClasses(0, "__NSCFType");
+        for (CFIndex idx = 1; idx < __CFRuntimeClassTableSize; idx++) {
+            __CFRuntimeObjCClassTable[idx] = __CFRuntimeObjCClassTable[0];
+        }
+
         /* Here so that two runtime classes get indices 0, 1. */
         __kCFNotATypeTypeID = _CFRuntimeRegisterClass(&__CFNotATypeClass);
         __kCFTypeTypeID = _CFRuntimeRegisterClass(&__CFTypeClass);
@@ -677,7 +989,7 @@ void __CFInitialize(void) {
         /* Here so that __kCFAllocatorTypeID gets index 2. */
         __CFAllocatorInitialize();
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
         {
             CFIndex idx, cnt;
             char **args = *_NSGetArgv();
@@ -695,32 +1007,32 @@ void __CFInitialize(void) {
 #endif
 
 
-        /* CFBag needs to be up before CFString. */
-        __CFBagInitialize();
-
+        CFBasicHashGetTypeID();
+        CFBagGetTypeID();
 #if !__LP64__
         // Creating this lazily in CFRetain causes recursive call to CFRetain
         __CFRuntimeExternRefCountTable = CFBagCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
 #endif
 
+       for (CFIndex idx = 0; idx < NUM_EXTERN_TABLES; idx++) {
+           __NSRetainCounters[idx].table = CFBasicHashCreate(kCFAllocatorSystemDefault, kCFBasicHashHasCounts | kCFBasicHashLinearHashing | kCFBasicHashAggressiveGrowth, &CFBasicHashNullCallbacks);
+           CFBasicHashSetCapacity(__NSRetainCounters[idx].table, 40);
+           __NSRetainCounters[idx].lock = CFSpinLockInit;
+       }
+
         /*** _CFRuntimeCreateInstance() can finally be called generally after this line. ***/
 
        __CFRuntimeClassTableCount = 7;
        __CFStringInitialize();         // CFString's TypeID must be 0x7, now and forever
        __CFRuntimeClassTableCount = 16;
-        __CFDictionaryInitialize();
-        __CFArrayInitialize();
-        __CFDataInitialize();
-        __CFSetInitialize();
+        CFSetGetTypeID();              // See above for hard-coding of this position
+        CFDictionaryGetTypeID();       // See above for hard-coding of this position
+        __CFArrayInitialize();         // See above for hard-coding of this position
+        __CFDataInitialize();          // See above for hard-coding of this position
         __CFNullInitialize();          // See above for hard-coding of this position
         __CFBooleanInitialize();       // See above for hard-coding of this position
         __CFNumberInitialize();                // See above for hard-coding of this position
 
-
-        __CFDateInitialize();  // just initializes the time goo
-//     _CFRuntimeBridgeClasses(CFDateGetTypeID(), objc_lookUpClass("NSCFDate") ? "NSCFDate" : "__NSCFDate");
-        __CFTimeZoneInitialize();
-//     _CFRuntimeBridgeClasses(CFTimeZoneGetTypeID(), "NSCFTimeZone");
         __CFBinaryHeapInitialize();
         __CFBitVectorInitialize();
         __CFCharacterSetInitialize();
@@ -729,37 +1041,44 @@ void __CFInitialize(void) {
         __CFTreeInitialize();
         __CFURLInitialize();
         __CFBundleInitialize();
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
         __CFPlugInInitialize();
         __CFPlugInInstanceInitialize();
-#endif //__MACH__
-        __CFUUIDInitialize();
-#if DEPLOYMENT_TARGET_MACOSX
-    __CFMessagePortInitialize();
 #endif
-#if DEPLOYMENT_TARGET_MACOSX
+        __CFUUIDInitialize();
+       __CFMessagePortInitialize();
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
         __CFMachPortInitialize();
 #endif
         __CFStreamInitialize();
-        __CFPreferencesDomainInitialize();
-#if DEPLOYMENT_TARGET_MACOSX || defined(__WIN32__)
         __CFRunLoopInitialize();
         __CFRunLoopObserverInitialize();
         __CFRunLoopSourceInitialize();
         __CFRunLoopTimerInitialize();
-        __CFSocketInitialize();
-#endif
 
 
-#if DEPLOYMENT_TARGET_MACOSX
         {
             CFIndex idx, cnt;
-            char **args;
+        char **args;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
             args = *_NSGetArgv();
             cnt = *_NSGetArgc();
+#elif DEPLOYMENT_TARGET_WINDOWS
+            wchar_t *commandLine = GetCommandLineW();
+            wchar_t **wideArgs = CommandLineToArgvW(commandLine, (int *)&cnt);
+            args = (char **)malloc(sizeof(char *) * cnt);
+            for (int y=0; y < cnt; y++) {
+                int bufSize = lstrlenW(wideArgs[y]) + 20;
+                char *arg = (char *)malloc(sizeof(char) * bufSize);
+                int res = WideCharToMultiByte(CP_ACP, 1024 /*WC_NO_BEST_FIT_CHARS*/, wideArgs[y], -1, arg, bufSize, NULL, NULL);
+                if (!res)
+                    printf("CF - Error converting command line arg string to ascii: %x\n", (unsigned int)wideArgs[y]);
+                args[y] = arg;
+            }
+#endif
             CFIndex count;
             CFStringRef *list, buffer[256];
-            list = (cnt <= 256) ? buffer : malloc(cnt * sizeof(CFStringRef));
+            list = (cnt <= 256) ? buffer : (CFStringRef *)malloc(cnt * sizeof(CFStringRef));
             for (idx = 0, count = 0; idx < cnt; idx++) {
                 if (NULL == args[idx]) continue;
                 list[count] = CFStringCreateWithCString(kCFAllocatorSystemDefault, args[idx], kCFStringEncodingUTF8);
@@ -776,59 +1095,104 @@ void __CFInitialize(void) {
             }
             __CFArgStuff = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)list, count, &kCFTypeArrayCallBacks);
         }
-#endif
+
         _CFProcessPath();      // cache this early
 
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+        __CFOAInitialize();
+#endif
+
         if (__CFRuntimeClassTableCount < 256) __CFRuntimeClassTableCount = 256;
+       __CFSendObjCMsg = (void *(*)(const void *, SEL, ...))objc_msgSend;
+
+#if DEPLOYMENT_TARGET_MACOSX
+#elif DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_EMBEDDED
+#else
+#error
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+       if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) {
+           setenv("COMMAND_MODE", "legacy", 1);
+           __CFEnv[sizeof(__CFEnv) / sizeof(__CFEnv[0]) - 1].name = "COMMAND_MODE";
+           __CFEnv[sizeof(__CFEnv) / sizeof(__CFEnv[0]) - 1].value = "legacy";
+       }
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error
+#endif
 
-#if defined(DEBUG) && !defined(__WIN32__)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
         CFLog(kCFLogLevelWarning, CFSTR("Assertions enabled"));
 #endif
+
+        __CFProphylacticAutofsAccess = false;
     }
 }
 
-//#if defined(__WIN32__)
 
-#ifdef _BUILD_NET_FOUNDATION_
-#ifdef __cplusplus
-extern "C"{
-#endif //C++
-extern void _CFFTPCleanup(void);
-extern void _CFHTTPMessageCleanup(void);
-extern void _CFHTTPStreamCleanup(void);
-#ifdef __cplusplus
-}
-#endif //C++
+#if DEPLOYMENT_TARGET_WINDOWS
+
+static CFBundleRef RegisterCoreFoundationBundle(void) {
+#ifdef _DEBUG
+    // might be nice to get this from the project file at some point
+    wchar_t *DLLFileName = (wchar_t *)L"CoreFoundation_debug.dll";
+#else
+    wchar_t *DLLFileName = (wchar_t *)L"CoreFoundation.dll";
+#endif
+    wchar_t path[MAX_PATH+1];
+    path[0] = path[1] = 0;
+    DWORD wResult;
+    CFIndex idx;
+    HMODULE ourModule = GetModuleHandleW(DLLFileName);
+
+    CFAssert(ourModule, __kCFLogAssertion, "GetModuleHandle failed");
+
+    wResult = GetModuleFileNameW(ourModule, path, MAX_PATH+1);
+    CFAssert1(wResult > 0, __kCFLogAssertion, "GetModuleFileName failed: %d", GetLastError());
+    CFAssert1(wResult < MAX_PATH+1, __kCFLogAssertion, "GetModuleFileName result truncated: %s", path);
+
+    // strip off last component, the DLL name
+    for (idx = wResult - 1; idx; idx--) {
+        if ('\\' == path[idx]) {
+            path[idx] = '\0';
+            break;
+        }
+    }
 
-#endif //_BUILD_NET_FOUNDATION_
+    CFStringRef fsPath = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar*)path, idx);
+    CFURLRef dllURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, fsPath, kCFURLWindowsPathStyle, TRUE);
+    CFURLRef bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, dllURL, CFSTR("CoreFoundation.resources"), TRUE);
+    CFRelease(fsPath);
+    CFRelease(dllURL);
 
-#if 0
+    // this registers us so subsequent calls to CFBundleGetBundleWithIdentifier will succeed
+    CFBundleRef bundle = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
+    CFRelease(bundleURL);
 
-/* We have to call __CFInitialize when library is attached to the process.
- * (Sergey Zubarev)
- */
-#if defined(_BUILD_NET_FOUNDATION_)
-extern "C" {
-BOOL WINAPI CoreFoundationDllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved );
+    return bundle;
 }
 
-BOOL WINAPI CoreFoundationDllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved ) {
-#else
-BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved ) {
-#endif
+
+#define DLL_PROCESS_ATTACH   1
+#define DLL_THREAD_ATTACH    2
+#define DLL_THREAD_DETACH    3
+#define DLL_PROCESS_DETACH   0
+
+int DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved ) {
     static CFBundleRef cfBundle = NULL;
     if (dwReason == DLL_PROCESS_ATTACH) {
        __CFInitialize();
         cfBundle = RegisterCoreFoundationBundle();
     } else if (dwReason == DLL_PROCESS_DETACH) {
-        if (cfBundle) CFRelease(cfBundle);
-#if !0
-        __CFStringCleanup();
+        __CFStreamCleanup();
         __CFSocketCleanup();
-#endif
         __CFUniCharCleanup();
-        __CFStreamCleanup();
         __CFBaseCleanup();
+       // do these last
+       if (cfBundle) CFRelease(cfBundle);
+        __CFStringCleanup();
     } else if (dwReason == DLL_THREAD_DETACH) {
         __CFFinalizeThreadData(NULL);
     }
@@ -837,62 +1201,26 @@ BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved ) {
 
 #endif
 
-// Functions that avoid ObC dispatch and CF type validation, for use by NSNotifyingCFArray, etc.
-// Hopefully all of this will just go away.  3321464.  M.P. To Do - 7/9/03
-
-Boolean _CFEqual(CFTypeRef cf1, CFTypeRef cf2) {
-    if (cf1 == cf2) return true;
-    if (NULL == cf1) return false;
-    if (NULL == cf2) return false;
-    __CFGenericAssertIsCF(cf1);
-    __CFGenericAssertIsCF(cf2);
-    if (__CFGenericTypeID_inline(cf1) != __CFGenericTypeID_inline(cf2)) return false;
-    if (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf1)]->equal) {
-       return __CFRuntimeClassTable[__CFGenericTypeID_inline(cf1)]->equal(cf1, cf2);
-    }
-    return false;
-}
-
-CFIndex _CFGetRetainCount(CFTypeRef cf) {
-    if (NULL == cf) return 0;
-    if (CF_IS_COLLECTABLE(cf)) {
-        return auto_zone_retain_count(__CFCollectableZone, cf);
-    }
-    uint64_t rc = __CFGetFullRetainCount(cf);
-    return (rc < (uint64_t)LONG_MAX) ? (CFIndex)rc : (CFIndex)LONG_MAX;
-}
-
-CFHashCode _CFHash(CFTypeRef cf) {
-    if (NULL == cf) return 0;
-    if (NULL != __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->hash) {
-       return __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->hash(cf);
-    }
-    return (CFHashCode)cf;
-}
-
-#if 0 || 0
-static inline bool myOSAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatile int32_t *theValue) {
-    int32_t actualOldValue = InterlockedCompareExchange((volatile LONG *)theValue, newValue, oldValue);
-    return actualOldValue == oldValue ? true : false;
-}
-#else
-static bool (*myOSAtomicCompareAndSwap32Barrier)(int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue) = OSAtomicCompareAndSwap32Barrier;
-#endif
-
 CF_EXPORT CFTypeRef _CFRetain(CFTypeRef cf) {
     if (NULL == cf) return NULL;
+    Boolean didAuto = false;
 #if __LP64__
+    if (0 == ((CFRuntimeBase *)cf)->_rc && !CF_IS_COLLECTABLE(cf)) return cf;  // Constant CFTypeRef 
     uint32_t lowBits;
     do {
        lowBits = ((CFRuntimeBase *)cf)->_rc;
-       if (0 == lowBits) return cf;    // Constant CFTypeRef
-    } while (!myOSAtomicCompareAndSwap32Barrier(lowBits, lowBits + 1, (int32_t *)&((CFRuntimeBase *)cf)->_rc));
+    } while (!OSAtomicCompareAndSwap32Barrier(lowBits, lowBits + 1, (int32_t *)&((CFRuntimeBase *)cf)->_rc));
+    // GC:  0 --> 1 transition? then add a GC retain count, to root the object. we'll remove it on the 1 --> 0 transition.
+    if (lowBits == 0 && CF_IS_COLLECTABLE(cf)) {
+       auto_zone_retain(auto_zone(), (void*)cf);
+       didAuto = true;
+    }
 #else
 #define RC_START 24
 #define RC_END 31
     volatile UInt32 *infoLocation = (UInt32 *)&(((CFRuntimeBase *)cf)->_cfinfo);
     CFIndex rcLowBits = __CFBitfieldGetValue(*infoLocation, RC_END, RC_START);
-    if (__builtin_expect(0 == rcLowBits, 0)) return cf;        // Constant CFTypeRef
+    if (__builtin_expect(0 == rcLowBits, 0) && !CF_IS_COLLECTABLE(cf)) return cf;      // Constant CFTypeRef
     bool success = 0;
     do {
         UInt32 initialCheckInfo = *infoLocation;
@@ -911,24 +1239,30 @@ CF_EXPORT CFTypeRef _CFRetain(CFTypeRef cf) {
             prospectiveNewInfo = initialCheckInfo;
             __CFBitfieldSetValue(prospectiveNewInfo, RC_END, RC_START, ((1 << 7) | (1 << 6)));
             __CFSpinLock(&__CFRuntimeExternRefCountTableLock);
-            success = myOSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
+            success = OSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
             if (__builtin_expect(success, 1)) {
-                CFBagAddValue(__CFRuntimeExternRefCountTable, DISGUISE(cf));
+                __CFDoExternRefOperation(350, (id)cf);
             }
             __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock);
         } else {
-            success = myOSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
+            success = OSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
+            // XXX_PCB:  0 --> 1 transition? then add a GC retain count, to root the object. we'll remove it on the 1 --> 0 transition.
+            if (success && __CFBitfieldGetValue(initialCheckInfo, RC_END, RC_START) == 0 && CF_IS_COLLECTABLE(cf)) {
+               auto_zone_retain(auto_zone(), (void*)cf);
+               didAuto = true;
+           }
         }
     } while (__builtin_expect(!success, 0));
 #endif
-    if (__builtin_expect(__CFOASafe, 0)) {
-       __CFRecordAllocationEvent(__kCFRetainEvent, (void *)cf, 0, _CFGetRetainCount(cf), NULL);
+    if (!didAuto && __builtin_expect(__CFOASafe, 0)) {
+       __CFRecordAllocationEvent(__kCFRetainEvent, (void *)cf, 0, CFGetRetainCount(cf), NULL);
     }
     return cf;
 }
 
 CF_EXPORT void _CFRelease(CFTypeRef cf) {
     Boolean isAllocator = false;
+    Boolean didAuto = false;
 #if __LP64__
     uint32_t lowBits;
     do {
@@ -942,21 +1276,28 @@ CF_EXPORT void _CFRelease(CFTypeRef cf) {
             if (cfClass->version & _kCFRuntimeResourcefulObject && cfClass->reclaim != NULL) {
                 cfClass->reclaim(cf);
             }
-            void (*func)(CFTypeRef) = __CFRuntimeClassTable[typeID]->finalize;
-           if (NULL != func) {
-               func(cf);
-           }
-           // We recheck lowBits to see if the object has been retained again during
-           // the finalization process.  This allows for the finalizer to resurrect,
-           // but the main point is to allow finalizers to be able to manage the
-           // removal of objects from uniquing caches, which may race with other threads
-           // which are allocating (looking up and finding) objects from those caches,
-           // which (that thread) would be the thing doing the extra retain in that case.
-           if (isAllocator || myOSAtomicCompareAndSwap32Barrier(1, 0, (int32_t *)&((CFRuntimeBase *)cf)->_rc)) {
-               goto really_free;
+           if (!CF_IS_COLLECTABLE(cf)) {
+                void (*func)(CFTypeRef) = __CFRuntimeClassTable[typeID]->finalize;
+               if (NULL != func) {
+                   func(cf);
+               }
+               // We recheck lowBits to see if the object has been retained again during
+               // the finalization process.  This allows for the finalizer to resurrect,
+               // but the main point is to allow finalizers to be able to manage the
+               // removal of objects from uniquing caches, which may race with other threads
+               // which are allocating (looking up and finding) objects from those caches,
+               // which (that thread) would be the thing doing the extra retain in that case.
+               if (isAllocator || OSAtomicCompareAndSwap32Barrier(1, 0, (int32_t *)&((CFRuntimeBase *)cf)->_rc)) {
+                   goto really_free;
+               }
            }
        }
-    } while (!myOSAtomicCompareAndSwap32Barrier(lowBits, lowBits - 1, (int32_t *)&((CFRuntimeBase *)cf)->_rc));
+    } while (!OSAtomicCompareAndSwap32Barrier(lowBits, lowBits - 1, (int32_t *)&((CFRuntimeBase *)cf)->_rc));
+    if (lowBits == 1 && CF_IS_COLLECTABLE(cf)) {
+        // GC:  release the collector's hold over the object, which will call the finalize function later on.
+       auto_zone_release(auto_zone(), (void*)cf);
+        didAuto = true;
+    }
 #else
     volatile UInt32 *infoLocation = (UInt32 *)&(((CFRuntimeBase *)cf)->_cfinfo);
     CFIndex rcLowBits = __CFBitfieldGetValue(*infoLocation, RC_END, RC_START);
@@ -967,31 +1308,43 @@ CF_EXPORT void _CFRelease(CFTypeRef cf) {
         rcLowBits = __CFBitfieldGetValue(initialCheckInfo, RC_END, RC_START);
         if (__builtin_expect(1 == rcLowBits, 0)) {
             // we think cf should be deallocated
-            if (__builtin_expect(__kCFAllocatorTypeID_CONST == __CFGenericTypeID_inline(cf), 0)) {
-                if (__builtin_expect(__CFOASafe, 0)) __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, 0, NULL);
-               __CFAllocatorDeallocate((void *)cf);
-                success = 1;
-            } else {
-                // CANNOT WRITE ANY NEW VALUE INTO [CF_RC_BITS] UNTIL AFTER FINALIZATION
-                CFTypeID typeID = __CFGenericTypeID_inline(cf);
-                CFRuntimeClass *cfClass = __CFRuntimeClassTable[typeID];
-                if (cfClass->version & _kCFRuntimeResourcefulObject && cfClass->reclaim != NULL) {
-                    cfClass->reclaim(cf);
-                }
-                if (NULL != __CFRuntimeClassTable[typeID]->finalize) {
-                    __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->finalize(cf);
-                }
-                // We recheck rcLowBits to see if the object has been retained again during
-                // the finalization process.  This allows for the finalizer to resurrect,
-                // but the main point is to allow finalizers to be able to manage the
-                // removal of objects from uniquing caches, which may race with other threads
-                // which are allocating (looking up and finding) objects from those caches,
-                // which (that thread) would be the thing doing the extra retain in that case.
-                rcLowBits = __CFBitfieldGetValue(*infoLocation, RC_END, RC_START);
-                success = (1 == rcLowBits);
-                if (__builtin_expect(success, 1)) {
-                    goto really_free;
-                }
+           // CANNOT WRITE ANY NEW VALUE INTO [CF_RC_BITS] UNTIL AFTER FINALIZATION
+           CFTypeID typeID = __CFGenericTypeID_inline(cf);
+           CFRuntimeClass *cfClass = __CFRuntimeClassTable[typeID];
+           if (cfClass->version & _kCFRuntimeResourcefulObject && cfClass->reclaim != NULL) {
+               cfClass->reclaim(cf);
+           }
+           if (CF_IS_COLLECTABLE(cf)) {
+                UInt32 prospectiveNewInfo = initialCheckInfo - (1 << RC_START);
+                success = OSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
+                // GC:  release the collector's hold over the object, which will call the finalize function later on.
+                if (success) {
+                   auto_zone_release(auto_zone(), (void*)cf);
+                   didAuto = true;
+               }
+             } else {
+               if (__builtin_expect(__kCFAllocatorTypeID_CONST == typeID, 0)) {
+                   if (!didAuto && __builtin_expect(__CFOASafe, 0)) {
+                       __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, 0, NULL);
+                   }
+                   __CFAllocatorDeallocate((void *)cf);
+                   success = 1;
+               } else {
+                   if (NULL != __CFRuntimeClassTable[typeID]->finalize) {
+                       __CFRuntimeClassTable[typeID]->finalize(cf);
+                   }
+                   // We recheck rcLowBits to see if the object has been retained again during
+                   // the finalization process.  This allows for the finalizer to resurrect,
+                   // but the main point is to allow finalizers to be able to manage the
+                   // removal of objects from uniquing caches, which may race with other threads
+                   // which are allocating (looking up and finding) objects from those caches,
+                   // which (that thread) would be the thing doing the extra retain in that case.
+                   rcLowBits = __CFBitfieldGetValue(*infoLocation, RC_END, RC_START);
+                   success = (1 == rcLowBits);
+                   if (__builtin_expect(success, 1)) {
+                       goto really_free;
+                   }
+               }
             }
         } else {
             // not yet junk
@@ -999,33 +1352,33 @@ CF_EXPORT void _CFRelease(CFTypeRef cf) {
             if (__builtin_expect((1 << 7) == rcLowBits, 0)) {
                 // Time to remove a bit from the external ref count
                 __CFSpinLock(&__CFRuntimeExternRefCountTableLock);
-                CFIndex rcHighBitsCnt = CFBagGetCountOfValue(__CFRuntimeExternRefCountTable, DISGUISE(cf));
+                CFIndex rcHighBitsCnt = __CFDoExternRefOperation(500, (id)cf);
                 if (1 == rcHighBitsCnt) {
                     __CFBitfieldSetValue(prospectiveNewInfo, RC_END, RC_START, (1 << 6) - 1);
                 } else {
                     __CFBitfieldSetValue(prospectiveNewInfo, RC_END, RC_START, ((1 << 6) | (1 << 7)) - 1);
                 }
-                success = myOSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
+                success = OSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
                 if (__builtin_expect(success, 1)) {
-                    CFBagRemoveValue(__CFRuntimeExternRefCountTable, DISGUISE(cf));
+                   __CFDoExternRefOperation(450, (id)cf);
                 }
                 __CFSpinUnlock(&__CFRuntimeExternRefCountTableLock);
             } else {
                 prospectiveNewInfo -= (1 << RC_START);
-                success = myOSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
+                success = OSAtomicCompareAndSwap32Barrier(*(int32_t *)&initialCheckInfo, *(int32_t *)&prospectiveNewInfo, (int32_t *)infoLocation);
             }
         }
     } while (__builtin_expect(!success, 0));
 
 #endif
-    if (__builtin_expect(__CFOASafe, 0)) {
-       __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, _CFGetRetainCount(cf), NULL);
+    if (!didAuto && __builtin_expect(__CFOASafe, 0)) {
+       __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, CFGetRetainCount(cf), NULL);
     }
     return;
 
     really_free:;
-    if (__builtin_expect(__CFOASafe, 0)) {
-       // do not use _CFGetRetainCount() because cf has been freed if it was an allocator
+    if (!didAuto && __builtin_expect(__CFOASafe, 0)) {
+       // do not use CFGetRetainCount() because cf has been freed if it was an allocator
        __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, 0, NULL);
     }
     // cannot zombify allocators, which get deallocated by __CFAllocatorDeallocate (finalize)
@@ -1040,23 +1393,89 @@ CF_EXPORT void _CFRelease(CFTypeRef cf) {
        }
        usesSystemDefaultAllocator = (allocator == kCFAllocatorSystemDefault);
 
-       if (__CFZombieLevel & (1 << 0)) {
-           uint8_t *ptr = (uint8_t *)cf - (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef));
-           size_t size = malloc_size(ptr);
-           uint8_t byte = 0xFC;
-           if (__CFZombieLevel & (1 << 1)) {
-               ptr = (uint8_t *)cf + sizeof(CFRuntimeBase);
-               size = size - sizeof(CFRuntimeBase) - (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef));
+       if (__CFZombieEnabled && !kCFUseCollectableAllocator) {
+           Class cls = object_getClass((id)cf);
+           const char *name = NULL;
+            __CFSpinLock(&__CFBigRuntimeFunnel);
+           for (CFIndex idx = 0; !name && idx < __CFRuntimeClassTableCount; idx++) {
+               if ((uintptr_t)cls == __CFRuntimeObjCClassTable[idx]) {
+                   CFRuntimeClass *c = __CFRuntimeClassTable[idx];
+                   if (c) name = c->className;
+               }
            }
-           if (__CFZombieLevel & (1 << 7)) {
-               byte = (__CFZombieLevel >> 8) & 0xFF;
+            __CFSpinUnlock(&__CFBigRuntimeFunnel);
+           // in 64-bit, a future class has nil isa, and calling class_getName()
+           // on such will crash so we do this test
+           if (!name && object_getClass((id)cls)) {
+               name = class_getName(cls);
+           }
+           if (!name) name = "$class-unknown$";
+           char *cname = NULL;
+           asprintf(&cname, "_NSZombie_%s", name);
+           Class zclass = (Class)objc_lookUpClass(cname);
+           if (!zclass) {
+              zclass = objc_duplicateClass((Class)objc_lookUpClass("_NSZombie_"), cname, 0);
+           }
+           free(cname);
+
+#if DEPLOYMENT_TARGET_MACOSX
+           if (object_getClass((id)cls)) {
+               objc_destructInstance((id)cf);
+           }
+#endif
+           if (__CFDeallocateZombies) {
+#if __OBJC2__
+               object_setClass((id)cf, zclass);
+#else
+               //  Set 'isa' pointer only if using standard deallocator
+               // However, _internal_object_dispose is not exported from libobjc
+               if (_dealloc == _original_objc_dealloc) {
+                   object_setClass((id)cf, zclass);
+               }
+#endif
+               CFAllocatorDeallocate(allocator, (uint8_t *)cf - (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef)));
+           } else {
+               object_setClass((id)cf, zclass);
+           }
+
+#if 0
+           extern uintptr_t __CFFindPointer(uintptr_t ptr, uintptr_t start);
+           uintptr_t res = __CFFindPointer((uintptr_t)cf, 0);
+           while (0 != res) {
+               if (res < (uintptr_t)&cf - 4 * 4096 || (uintptr_t)&cf + 4096 < res) {
+                   printf("*** NSZombie warning: object %p deallocated, but reference still found at %p (%p %p)\n", cf, res);
+               }
+               res = __CFFindPointer((uintptr_t)cf, res + 1);
+           }
+#endif
+
+       } else {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+           if (kCFUseCollectableAllocator || !(__CFZombieLevel & (1 << 4))) {
+               Class cls = object_getClass((id)cf);
+               if (object_getClass((id)cls)) {
+                   objc_removeAssociatedObjects((id)cf);
+               }
+           }
+#endif
+           if ((__CFZombieLevel & (1 << 0)) && !kCFUseCollectableAllocator) {
+               uint8_t *ptr = (uint8_t *)cf - (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef));
+               size_t size = malloc_size(ptr);
+               uint8_t byte = 0xFC;
+               if (__CFZombieLevel & (1 << 1)) {
+                   ptr = (uint8_t *)cf + sizeof(CFRuntimeBase);
+                   size = size - sizeof(CFRuntimeBase) - (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef));
+               }
+               if (__CFZombieLevel & (1 << 7)) {
+                   byte = (__CFZombieLevel >> 8) & 0xFF;
+               }
+               memset(ptr, byte, size);
+           }
+           if (kCFUseCollectableAllocator || !(__CFZombieLevel & (1 << 4))) {
+               CFAllocatorDeallocate(allocator, (uint8_t *)cf - (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef)));
            }
-           memset(ptr, byte, size);
-       }
-       if (!(__CFZombieLevel & (1 << 4))) {
-           CFAllocatorDeallocate(allocator, (uint8_t *)cf - (usesSystemDefaultAllocator ? 0 : sizeof(CFAllocatorRef)));
        }
-       
+
        if (kCFAllocatorSystemDefault != allocator) {
            CFRelease(allocator);
        }
index 6c81c5ce809ff93a45db75f2767abfe09241e9e4..c38563723bbbbea8b437c4f39e402e464bd2f1de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFRuntime.h
-       Copyright (c) 1999-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFRUNTIME__)
 CF_EXTERN_C_BEGIN
 
 // GC: until we link against ObjC must use indirect functions.  Overridden in CFSetupFoundationBridging
-extern bool kCFUseCollectableAllocator;
-extern bool (*__CFObjCIsCollectable)(void *);
-extern const void* (*__CFObjCAssignIvar)(const void *value, const void *base, const void **slot);
-extern const void* (*__CFObjCStrongAssign)(const void *value, const void **slot);
-extern void* (*__CFObjCMemmoveCollectable)(void *dest, const void *src, size_t);
-extern void (*__CFObjCWriteBarrierRange)(void *, size_t);
+CF_EXPORT bool kCFUseCollectableAllocator;
+CF_EXPORT bool (*__CFObjCIsCollectable)(void *);
 
 // GC: primitives.
 // is GC on?
 #define CF_USING_COLLECTABLE_MEMORY (kCFUseCollectableAllocator)
 // is GC on and is this the GC allocator?
-#define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (CF_USING_COLLECTABLE_MEMORY && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator)))
+#define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (kCFUseCollectableAllocator && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator)))
 // is this allocated by the collector?
 #define CF_IS_COLLECTABLE(obj) (__CFObjCIsCollectable ? __CFObjCIsCollectable((void*)obj) : false)
 
-// XXX_PCB for generational GC support.
-
-CF_INLINE const void* __CFAssignIvar(CFAllocatorRef allocator, const void *rvalue, const void *base, const void **lvalue) {
-    if (rvalue && CF_IS_COLLECTABLE_ALLOCATOR(allocator))
-        return __CFObjCAssignIvar(rvalue, base, lvalue);
-    else
-        return (*lvalue = rvalue);
-}
-
-CF_INLINE const void* __CFStrongAssign(CFAllocatorRef allocator, const void *rvalue, const void **lvalue) {
-    if (rvalue && CF_IS_COLLECTABLE_ALLOCATOR(allocator))
-        return __CFObjCStrongAssign(rvalue, lvalue);
-    else
-        return (*lvalue = rvalue);
-}
-
-// Use this form when the base pointer to the object is known.
-#define CF_WRITE_BARRIER_BASE_ASSIGN(allocator, base, lvalue, rvalue) __CFAssignIvar(allocator, (const void*)rvalue, (const void*)base, (const void**)&(lvalue))
-
-// Use this form when the base pointer to the object isn't known.
-#define CF_WRITE_BARRIER_ASSIGN(allocator, lvalue, rvalue) __CFStrongAssign(allocator, (const void*)rvalue, (const void**)&(lvalue))
-
-// Write-barrier memory move.
-#define CF_WRITE_BARRIER_MEMMOVE(dst, src, size) __CFObjCMemmoveCollectable(dst, src, size)
-
-// Used by frameworks to assert they "KNOW WHAT THEY'RE DOING under GC."
-CF_EXPORT CFAllocatorRef _CFAllocatorCreateGC(CFAllocatorRef allocator, CFAllocatorContext *context);
-
-// Zero-retain count CFAllocator functions, i.e. memory that will be collected, no dealloc necessary
-CF_EXPORT void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint);
-CF_EXPORT void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint);
-CF_EXPORT void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr);
 
 enum {
     _kCFRuntimeNotATypeID =                0,
-    _kCFRuntimeScannedObject =       (1 << 0),
-    /* _kCFRuntimeUncollectableObject = (1 << 1),  No longer used; obsolete. */
-    _kCFRuntimeResourcefulObject =   (1 << 2)
+    _kCFRuntimeScannedObject =       (1UL << 0),
+    /* _kCFRuntimeUncollectableObject = (1UL << 1),  No longer used; obsolete. */
+    _kCFRuntimeResourcefulObject =   (1UL << 2)
 };
 
 typedef struct __CFRuntimeClass {      // Version 0 struct
diff --git a/CFSet.c b/CFSet.c
index 4c0e1f07560458765ff731d966b85bc30d41c95f..6c84711ea3522accbb726fa65d3ed2d3d664c715 100644 (file)
--- a/CFSet.c
+++ b/CFSet.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFSet.c
-       Copyright 1998-2006, Apple, Inc. All rights reserved.
+       Copyright 1998-2008, Apple, Inc. All rights reserved.
        Responsibility: Christopher Kane
-        Machine generated from Notes/HashingCode.template
+       Machine generated from Notes/HashingCode.template
 */
 
 
 
 
+
 #include <CoreFoundation/CFSet.h>
 #include "CFInternal.h"
-#include <mach-o/dyld.h>
+#include "CFBasicHash.h"
+#include <CoreFoundation/CFString.h>
 
 #define CFDictionary 0
 #define CFSet 0
@@ -48,7 +50,8 @@ static const CFSetValueCallBacks __kCFNullSetValueCallBacks = {0, NULL, NULL, NU
 
 #define CFHashRef CFDictionaryRef
 #define CFMutableHashRef CFMutableDictionaryRef
-#define __kCFHashTypeID __kCFDictionaryTypeID
+#define CFHashKeyCallBacks CFSetKeyCallBacks
+#define CFHashValueCallBacks CFSetValueCallBacks
 #endif
 
 #if CFSet
@@ -65,7 +68,8 @@ static const CFSetCallBacks __kCFNullSetCallBacks = {0, NULL, NULL, NULL, NULL,
 
 #define CFHashRef CFSetRef
 #define CFMutableHashRef CFMutableSetRef
-#define __kCFHashTypeID __kCFSetTypeID
+#define CFHashKeyCallBacks CFSetCallBacks
+#define CFHashValueCallBacks CFSetCallBacks
 #endif
 
 #if CFBag
@@ -82,566 +86,29 @@ static const CFSetCallBacks __kCFNullSetCallBacks = {0, NULL, NULL, NULL, NULL,
 
 #define CFHashRef CFBagRef
 #define CFMutableHashRef CFMutableBagRef
-#define __kCFHashTypeID __kCFBagTypeID
-#endif
-
-#define GETNEWKEY(newKey, oldKey) \
-        any_t (*kretain)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))__CFSetGetKeyCallBacks(hc)->retain \
-            : (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        any_t newKey = kretain ? (any_t)INVOKE_CALLBACK3(kretain, allocator, (any_t)key, hc->_context) : (any_t)oldKey
-
-#define RELEASEKEY(oldKey) \
-        void (*krelease)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (void (*)(CFAllocatorRef,any_t,any_pointer_t))__CFSetGetKeyCallBacks(hc)->release \
-            : (void (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        if (krelease) INVOKE_CALLBACK3(krelease, allocator, oldKey, hc->_context)
-        
-#if CFDictionary
-#define GETNEWVALUE(newValue) \
-        any_t (*vretain)(CFAllocatorRef, any_t, any_pointer_t) = \
-          !hasBeenFinalized(hc) \
-            ? (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))__CFSetGetValueCallBacks(hc)->retain \
-            : (any_t (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-        any_t newValue = vretain ? (any_t)INVOKE_CALLBACK3(vretain, allocator, (any_t)value, hc->_context) : (any_t)value
-
-#define RELEASEVALUE(oldValue) \
-    void (*vrelease)(CFAllocatorRef, any_t, any_pointer_t) = \
-      !hasBeenFinalized(hc) \
-        ? (void (*)(CFAllocatorRef,any_t,any_pointer_t))__CFSetGetValueCallBacks(hc)->release \
-        : (void (*)(CFAllocatorRef,any_t,any_pointer_t))0; \
-    if (vrelease) INVOKE_CALLBACK3(vrelease, allocator, oldValue, hc->_context)
-
+#define CFHashKeyCallBacks CFSetCallBacks
+#define CFHashValueCallBacks CFSetCallBacks
 #endif
 
-static void __CFSetHandleOutOfMemory(CFTypeRef obj, CFIndex numBytes) {
-    CFStringRef msg = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("Attempt to allocate %ld bytes for NS/CFSet failed"), numBytes);
-    CFBadErrorCallBack cb = _CFGetOutOfMemoryErrorCallBack();
-    if (NULL == cb || !cb(obj, CFSTR("NS/CFSet"), msg)) {
-        CFLog(kCFLogLevelCritical, CFSTR("%@"), msg);
-       HALT;
-    }
-    CFRelease(msg);
-}
-
-
-// Max load is 3/4 number of buckets
-CF_INLINE CFIndex __CFHashRoundUpCapacity(CFIndex capacity) {
-    return 3 * ((CFIndex)1 << (flsl((capacity - 1) / 3)));
-}
-
-// Returns next power of two higher than the capacity
-// threshold for the given input capacity.
-CF_INLINE CFIndex __CFHashNumBucketsForCapacity(CFIndex capacity) {
-    return 4 * ((CFIndex)1 << (flsl((capacity - 1) / 3)));
-}
-
-enum {                /* Bits 1-0 */
-    __kCFHashImmutable = 0,        /* unchangable and fixed capacity */
-    __kCFHashMutable = 1,                /* changeable and variable capacity */
-};
-
-enum {                /* Bits 5-4 (value), 3-2 (key) */
-    __kCFHashHasNullCallBacks = 0,
-    __kCFHashHasCFTypeCallBacks = 1,
-    __kCFHashHasCustomCallBacks = 3        /* callbacks are at end of header */
-};
-
-// Under GC, we fudge the key/value memory in two ways
-// First, if we had null callbacks or null for both retain/release, we use unscanned memory and get
-// standard 'dangling' references.
-// This means that if people were doing addValue:[xxx new] and never removing, well, that doesn't work
-//
-// Second, if we notice standard retain/release implementations we use scanned memory, and fudge the
-// standard callbacks to generally do nothing if the collection was allocated in GC memory. On special
-// CF objects, however, like those used for precious resources like video-card buffers, we do indeed
-// do CFRetain on input and CFRelease on output.  The tricky case is GC finalization; we need to remember
-// that we did the CFReleases so that subsequent collection operations, like removal, don't double CFRelease.
-// (In fact we don't really use CFRetain/CFRelease but go directly to the collector)
-//
-
-enum {
-    __kCFHashFinalized =         (1 << 7),
-    __kCFHashWeakKeys =          (1 << 8),
-    __kCFHashWeakValues =        (1 << 9)
-};
 
 typedef uintptr_t any_t;
 typedef const void * const_any_pointer_t;
 typedef void * any_pointer_t;
 
-struct __CFSet {
-    CFRuntimeBase _base;
-    CFIndex _count;             /* number of values */
-    CFIndex _bucketsNum;        /* number of buckets */
-    CFIndex _bucketsUsed;       /* number of used buckets */
-    CFIndex _bucketsCap;        /* maximum number of used buckets */
-    CFIndex _mutations;
-    CFIndex _deletes;
-    any_pointer_t _context;     /* private */
-    CFOptionFlags _xflags;
-    any_t _marker;
-    any_t *_keys;     /* can be NULL if not allocated yet */
-    any_t *_values;   /* can be NULL if not allocated yet */
-};
-
-/* Bits 1-0 of the _xflags are used for mutability variety */
-/* Bits 3-2 of the _xflags are used for key callback indicator bits */
-/* Bits 5-4 of the _xflags are used for value callback indicator bits */
-/* Bit 6 of the _xflags is special KVO actions bit */
-/* Bits 7,8,9 are GC use */
-
-CF_INLINE bool hasBeenFinalized(CFTypeRef collection) {
-    return __CFBitfieldGetValue(((const struct __CFSet *)collection)->_xflags, 7, 7) != 0;
-}
-
-CF_INLINE void markFinalized(CFTypeRef collection) {
-    __CFBitfieldSetValue(((struct __CFSet *)collection)->_xflags, 7, 7, 1);
-}
-
-
-CF_INLINE CFIndex __CFHashGetType(CFHashRef hc) {
-    return __CFBitfieldGetValue(hc->_xflags, 1, 0);
-}
-
-CF_INLINE CFIndex __CFSetGetSizeOfType(CFIndex t) {
-    CFIndex size = sizeof(struct __CFSet);
-    if (__CFBitfieldGetValue(t, 3, 2) == __kCFHashHasCustomCallBacks) {
-        size += sizeof(CFSetKeyCallBacks);
-    }
-    if (__CFBitfieldGetValue(t, 5, 4) == __kCFHashHasCustomCallBacks) {
-        size += sizeof(CFSetValueCallBacks);
-    }
-    return size;
-}
-
-CF_INLINE const CFSetKeyCallBacks *__CFSetGetKeyCallBacks(CFHashRef hc) {
-    CFSetKeyCallBacks *result = NULL;
-    switch (__CFBitfieldGetValue(hc->_xflags, 3, 2)) {
-    case __kCFHashHasNullCallBacks:
-        return &__kCFNullSetKeyCallBacks;
-    case __kCFHashHasCFTypeCallBacks:
-        return &kCFTypeSetKeyCallBacks;
-    case __kCFHashHasCustomCallBacks:
-        break;
-    }
-    result = (CFSetKeyCallBacks *)((uint8_t *)hc + sizeof(struct __CFSet));
-    return result;
-}
-
-CF_INLINE Boolean __CFSetKeyCallBacksMatchNull(const CFSetKeyCallBacks *c) {
-    return (NULL == c ||
-        (c->retain == __kCFNullSetKeyCallBacks.retain &&
-         c->release == __kCFNullSetKeyCallBacks.release &&
-         c->copyDescription == __kCFNullSetKeyCallBacks.copyDescription &&
-         c->equal == __kCFNullSetKeyCallBacks.equal &&
-         c->hash == __kCFNullSetKeyCallBacks.hash));
-}
-
-CF_INLINE Boolean __CFSetKeyCallBacksMatchCFType(const CFSetKeyCallBacks *c) {
-    return (&kCFTypeSetKeyCallBacks == c ||
-        (c->retain == kCFTypeSetKeyCallBacks.retain &&
-         c->release == kCFTypeSetKeyCallBacks.release &&
-         c->copyDescription == kCFTypeSetKeyCallBacks.copyDescription &&
-         c->equal == kCFTypeSetKeyCallBacks.equal &&
-         c->hash == kCFTypeSetKeyCallBacks.hash));
-}
-
-CF_INLINE const CFSetValueCallBacks *__CFSetGetValueCallBacks(CFHashRef hc) {
-    CFSetValueCallBacks *result = NULL;
-    switch (__CFBitfieldGetValue(hc->_xflags, 5, 4)) {
-    case __kCFHashHasNullCallBacks:
-        return &__kCFNullSetValueCallBacks;
-    case __kCFHashHasCFTypeCallBacks:
-        return &kCFTypeSetValueCallBacks;
-    case __kCFHashHasCustomCallBacks:
-        break;
-    }
-    if (__CFBitfieldGetValue(hc->_xflags, 3, 2) == __kCFHashHasCustomCallBacks) {
-        result = (CFSetValueCallBacks *)((uint8_t *)hc + sizeof(struct __CFSet) + sizeof(CFSetKeyCallBacks));
-    } else {
-        result = (CFSetValueCallBacks *)((uint8_t *)hc + sizeof(struct __CFSet));
-    }
-    return result;
-}
-
-CF_INLINE Boolean __CFSetValueCallBacksMatchNull(const CFSetValueCallBacks *c) {
-    return (NULL == c ||
-        (c->retain == __kCFNullSetValueCallBacks.retain &&
-         c->release == __kCFNullSetValueCallBacks.release &&
-         c->copyDescription == __kCFNullSetValueCallBacks.copyDescription &&
-         c->equal == __kCFNullSetValueCallBacks.equal));
-}
-
-CF_INLINE Boolean __CFSetValueCallBacksMatchCFType(const CFSetValueCallBacks *c) {
-    return (&kCFTypeSetValueCallBacks == c ||
-        (c->retain == kCFTypeSetValueCallBacks.retain &&
-         c->release == kCFTypeSetValueCallBacks.release &&
-         c->copyDescription == kCFTypeSetValueCallBacks.copyDescription &&
-         c->equal == kCFTypeSetValueCallBacks.equal));
-}
-
-CFIndex _CFSetGetKVOBit(CFHashRef hc) {
-    return __CFBitfieldGetValue(hc->_xflags, 6, 6);
-}
-
-void _CFSetSetKVOBit(CFHashRef hc, CFIndex bit) {
-    __CFBitfieldSetValue(((CFMutableHashRef)hc)->_xflags, 6, 6, ((uintptr_t)bit & 0x1));
-}
-
-CF_INLINE Boolean __CFSetShouldShrink(CFHashRef hc) {
-    return (__kCFHashMutable == __CFHashGetType(hc)) &&
-                !(CF_USING_COLLECTABLE_MEMORY && auto_zone_is_finalized(__CFCollectableZone, hc)) && /* GC:  don't shrink finalizing hcs! */
-                (hc->_bucketsNum < 4 * hc->_deletes || (256 <= hc->_bucketsCap && hc-> _bucketsUsed < 3 * hc->_bucketsCap / 16));
-}
-
-CF_INLINE CFIndex __CFHashGetOccurrenceCount(CFHashRef hc, CFIndex idx) {
-#if CFBag
-    return hc->_values[idx];
-#endif
-    return 1;
-}
-
-CF_INLINE Boolean __CFHashKeyIsValue(CFHashRef hc, any_t key) {
-    return (hc->_marker != key && ~hc->_marker != key) ? true : false;
-}
-
-CF_INLINE Boolean __CFHashKeyIsMagic(CFHashRef hc, any_t key) {
-    return (hc->_marker == key || ~hc->_marker == key) ? true : false;
-}
-
-
-#if !defined(CF_OBJC_KVO_WILLCHANGE)
-#define CF_OBJC_KVO_WILLCHANGE(obj, key)
-#define CF_OBJC_KVO_DIDCHANGE(obj, key)
-#endif
-
-CF_INLINE uintptr_t __CFSetScrambleHash(uintptr_t k) {
-#if 0
-    return k;
-#else
-#if __LP64__
-    uintptr_t a = 0x4368726973746F70ULL;
-    uintptr_t b = 0x686572204B616E65ULL;
-#else
-    uintptr_t a = 0x4B616E65UL;
-    uintptr_t b = 0x4B616E65UL;
-#endif
-    uintptr_t c = 1;
-    a += k;
-#if __LP64__
-    a -= b; a -= c; a ^= (c >> 43);
-    b -= c; b -= a; b ^= (a << 9);
-    c -= a; c -= b; c ^= (b >> 8);
-    a -= b; a -= c; a ^= (c >> 38);
-    b -= c; b -= a; b ^= (a << 23);
-    c -= a; c -= b; c ^= (b >> 5);
-    a -= b; a -= c; a ^= (c >> 35);
-    b -= c; b -= a; b ^= (a << 49);
-    c -= a; c -= b; c ^= (b >> 11);
-    a -= b; a -= c; a ^= (c >> 12);
-    b -= c; b -= a; b ^= (a << 18);
-    c -= a; c -= b; c ^= (b >> 22);
-#else
-    a -= b; a -= c; a ^= (c >> 13);
-    b -= c; b -= a; b ^= (a << 8);
-    c -= a; c -= b; c ^= (b >> 13);
-    a -= b; a -= c; a ^= (c >> 12);
-    b -= c; b -= a; b ^= (a << 16);
-    c -= a; c -= b; c ^= (b >> 5);
-    a -= b; a -= c; a ^= (c >> 3);
-    b -= c; b -= a; b ^= (a << 10);
-    c -= a; c -= b; c ^= (b >> 15);
-#endif
-    return c;
-#endif
-}
-
-static CFIndex __CFSetFindBuckets1a(CFHashRef hc, any_t key) {
-    CFHashCode keyHash = (CFHashCode)key;
-    keyHash = __CFSetScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            return kCFNotFound;
-        } else if (~marker == currKey) {        /* deleted */
-            /* do nothing */
-        } else if (currKey == key) {
-            return probe;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return kCFNotFound;
-        }
-    }
-}
-
-static CFIndex __CFSetFindBuckets1b(CFHashRef hc, any_t key) {
-    const CFSetKeyCallBacks *cb = __CFSetGetKeyCallBacks(hc);
-    CFHashCode keyHash = cb->hash ? (CFHashCode)INVOKE_CALLBACK2(((CFHashCode (*)(any_t, any_pointer_t))cb->hash), key, hc->_context) : (CFHashCode)key;
-    keyHash = __CFSetScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            return kCFNotFound;
-        } else if (~marker == currKey) {        /* deleted */
-            /* do nothing */
-        } else if (currKey == key || (cb->equal && INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))cb->equal, currKey, key, hc->_context))) {
-            return probe;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return kCFNotFound;
-        }
-    }
-}
-
-CF_INLINE CFIndex __CFSetFindBuckets1(CFHashRef hc, any_t key) {
-    if (__kCFHashHasNullCallBacks == __CFBitfieldGetValue(hc->_xflags, 3, 2)) {
-        return __CFSetFindBuckets1a(hc, key);
-    }
-    return __CFSetFindBuckets1b(hc, key);
-}
-
-static void __CFSetFindBuckets2(CFHashRef hc, any_t key, CFIndex *match, CFIndex *nomatch) {
-    const CFSetKeyCallBacks *cb = __CFSetGetKeyCallBacks(hc);
-    CFHashCode keyHash = cb->hash ? (CFHashCode)INVOKE_CALLBACK2(((CFHashCode (*)(any_t, any_pointer_t))cb->hash), key, hc->_context) : (CFHashCode)key;
-    keyHash = __CFSetScrambleHash(keyHash);
-    any_t *keys = hc->_keys;
-    any_t marker = hc->_marker;
-    CFIndex probe = keyHash & (hc->_bucketsNum - 1);
-    CFIndex probeskip = 1;        // See RemoveValue() for notes before changing this value
-    CFIndex start = probe;
-    *match = kCFNotFound;
-    *nomatch = kCFNotFound;
-    for (;;) {
-        any_t currKey = keys[probe];
-        if (marker == currKey) {                /* empty */
-            if (nomatch) *nomatch = probe;
-            return;
-        } else if (~marker == currKey) {        /* deleted */
-            if (nomatch) {
-                *nomatch = probe;
-                nomatch = NULL;
-            }
-        } else if (currKey == key || (cb->equal && INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))cb->equal, currKey, key, hc->_context))) {
-            *match = probe;
-            return;
-        }
-        probe = probe + probeskip;
-        // This alternative to probe % buckets assumes that
-        // probeskip is always positive and less than the
-        // number of buckets.
-        if (hc->_bucketsNum <= probe) {
-            probe -= hc->_bucketsNum;
-        }
-        if (start == probe) {
-            return;
-        }
-    }
-}
-
-static void __CFSetFindNewMarker(CFHashRef hc) {
-    any_t *keys = hc->_keys;
-    any_t newMarker;
-    CFIndex idx, nbuckets;
-    Boolean hit;
-
-    nbuckets = hc->_bucketsNum;
-    newMarker = hc->_marker;
-    do {
-        newMarker--;
-        hit = false;
-        for (idx = 0; idx < nbuckets; idx++) {
-            if (newMarker == keys[idx] || ~newMarker == keys[idx]) {
-                hit = true;
-                break;
-            }
-        }
-    } while (hit);
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (hc->_marker == keys[idx]) {
-            keys[idx] = newMarker;
-        } else if (~hc->_marker == keys[idx]) {
-            keys[idx] = ~newMarker;
-        }
-    }
-    ((struct __CFSet *)hc)->_marker = newMarker;
-}
-
 static Boolean __CFSetEqual(CFTypeRef cf1, CFTypeRef cf2) {
-    CFHashRef hc1 = (CFHashRef)cf1;
-    CFHashRef hc2 = (CFHashRef)cf2;
-    const CFSetKeyCallBacks *cb1, *cb2;
-    const CFSetValueCallBacks *vcb1, *vcb2;
-    any_t *keys;
-    CFIndex idx, nbuckets;
-    if (hc1 == hc2) return true;
-    if (hc1->_count != hc2->_count) return false;
-    cb1 = __CFSetGetKeyCallBacks(hc1);
-    cb2 = __CFSetGetKeyCallBacks(hc2);
-    if (cb1->equal != cb2->equal) return false;
-    vcb1 = __CFSetGetValueCallBacks(hc1);
-    vcb2 = __CFSetGetValueCallBacks(hc2);
-    if (vcb1->equal != vcb2->equal) return false;
-    if (0 == hc1->_bucketsUsed) return true; /* after function comparison! */
-    keys = hc1->_keys;
-    nbuckets = hc1->_bucketsNum;
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (hc1->_marker != keys[idx] && ~hc1->_marker != keys[idx]) {
-#if CFDictionary
-            const_any_pointer_t value;
-            if (!CFSetGetValueIfPresent(hc2, (any_pointer_t)keys[idx], &value)) return false;
-           if (hc1->_values[idx] != (any_t)value) {
-               if (NULL == vcb1->equal) return false;
-               if (!INVOKE_CALLBACK3((Boolean (*)(any_t, any_t, any_pointer_t))vcb1->equal, hc1->_values[idx], (any_t)value, hc1->_context)) return false;
-            }
-#endif
-#if  CFSet
-            const_any_pointer_t value;
-            if (!CFSetGetValueIfPresent(hc2, (any_pointer_t)keys[idx], &value)) return false;
-#endif
-#if CFBag
-            if (hc1->_values[idx] != CFSetGetCountOfValue(hc2, (any_pointer_t)keys[idx])) return false;
-#endif
-        }
-    }
-    return true;
+    return __CFBasicHashEqual((CFBasicHashRef)cf1, (CFBasicHashRef)cf2);
 }
 
 static CFHashCode __CFSetHash(CFTypeRef cf) {
-    CFHashRef hc = (CFHashRef)cf;
-    return hc->_count;
+    return __CFBasicHashHash((CFBasicHashRef)cf);
 }
 
 static CFStringRef __CFSetCopyDescription(CFTypeRef cf) {
-    CFHashRef hc = (CFHashRef)cf;
-    CFAllocatorRef allocator;
-    const CFSetKeyCallBacks *cb;
-    const CFSetValueCallBacks *vcb;
-    any_t *keys;
-    CFIndex idx, nbuckets;
-    CFMutableStringRef result;
-    cb = __CFSetGetKeyCallBacks(hc);
-    vcb = __CFSetGetValueCallBacks(hc);
-    keys = hc->_keys;
-    nbuckets = hc->_bucketsNum;
-    allocator = CFGetAllocator(hc);
-    result = CFStringCreateMutable(allocator, 0);
-    const char *type = "?";
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashImmutable: type = "immutable"; break;
-    case __kCFHashMutable: type = "mutable"; break;
-    }
-    CFStringAppendFormat(result, NULL, CFSTR("<CFSet %p [%p]>{type = %s, count = %u, capacity = %u, pairs = (\n"), cf, allocator, type, hc->_count, hc->_bucketsCap);
-    for (idx = 0; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            CFStringRef kDesc = NULL, vDesc = NULL;
-            if (NULL != cb->copyDescription) {
-                kDesc = (CFStringRef)INVOKE_CALLBACK2(((CFStringRef (*)(any_t, any_pointer_t))cb->copyDescription), keys[idx], hc->_context);
-            }
-            if (NULL != vcb->copyDescription) {
-                vDesc = (CFStringRef)INVOKE_CALLBACK2(((CFStringRef (*)(any_t, any_pointer_t))vcb->copyDescription), hc->_values[idx], hc->_context);
-            }
-#if CFDictionary
-            if (NULL != kDesc && NULL != vDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ = %@\n"), idx, kDesc, vDesc);
-                CFRelease(kDesc);
-                CFRelease(vDesc);
-            } else if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ = <%p>\n"), idx, kDesc, hc->_values[idx]);
-                CFRelease(kDesc);
-            } else if (NULL != vDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> = %@\n"), idx, keys[idx], vDesc);
-                CFRelease(vDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> = <%p>\n"), idx, keys[idx], hc->_values[idx]);
-            }
-#endif
-#if CFSet
-            if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@\n"), idx, kDesc);
-                CFRelease(kDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, keys[idx]);
-            }
-#endif
-#if CFBag
-            if (NULL != kDesc) {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : %@ (%ld)\n"), idx, kDesc, hc->_values[idx]);
-                CFRelease(kDesc);
-            } else {
-                CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p> (%ld)\n"), idx, keys[idx], hc->_values[idx]);
-            }
-#endif
-        }
-    }
-    CFStringAppend(result, CFSTR(")}"));
-    return result;
+    return __CFBasicHashCopyDescription((CFBasicHashRef)cf);
 }
 
 static void __CFSetDeallocate(CFTypeRef cf) {
-    CFMutableHashRef hc = (CFMutableHashRef)cf;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    const CFSetKeyCallBacks *cb = __CFSetGetKeyCallBacks(hc);
-    const CFSetValueCallBacks *vcb = __CFSetGetValueCallBacks(hc);
-
-    // mark now in case any callout somehow tries to add an entry back in
-    markFinalized(cf);
-    if (vcb->release || cb->release) {
-        any_t *keys = hc->_keys;
-        CFIndex idx, nbuckets = hc->_bucketsNum;
-        for (idx = 0; idx < nbuckets; idx++) {
-            any_t oldkey = keys[idx];
-            if (hc->_marker != oldkey && ~hc->_marker != oldkey) {
-                if (vcb->release) {
-                    INVOKE_CALLBACK3(((void (*)(CFAllocatorRef, any_t, any_pointer_t))vcb->release), allocator, hc->_values[idx], hc->_context);
-                }
-                if (cb->release) {
-                    INVOKE_CALLBACK3(((void (*)(CFAllocatorRef, any_t, any_pointer_t))cb->release), allocator, oldkey, hc->_context);
-                }
-            }
-        }
-    }
-
-    if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-        // return early so that contents are preserved after finalization
-        return;
-    }
-    
-    _CFAllocatorDeallocateGC(allocator, hc->_keys);
-#if CFDictionary || CFBag
-    _CFAllocatorDeallocateGC(allocator, hc->_values);
-#endif
-    hc->_keys = NULL;
-    hc->_values = NULL;
-    hc->_count = 0;  // GC: also zero count, so the hc will appear empty.
-    hc->_bucketsUsed = 0;
-    hc->_bucketsNum = 0;
+    __CFBasicHashDeallocate((CFBasicHashRef)cf);
 }
 
 static CFTypeID __kCFSetTypeID = _kCFRuntimeNotATypeID;
@@ -658,123 +125,183 @@ static const CFRuntimeClass __CFSetClass = {
     __CFSetCopyDescription
 };
 
-__private_extern__ void __CFSetInitialize(void) {
-    __kCFHashTypeID = _CFRuntimeRegisterClass(&__CFSetClass);
-}
-
 CFTypeID CFSetGetTypeID(void) {
-    return __kCFHashTypeID;
+    if (_kCFRuntimeNotATypeID == __kCFSetTypeID) __kCFSetTypeID = _CFRuntimeRegisterClass(&__CFSetClass);
+    return __kCFSetTypeID;
 }
 
-static CFMutableHashRef __CFSetInit(CFAllocatorRef allocator, CFOptionFlags flags, CFIndex capacity, const CFSetKeyCallBacks *keyCallBacks
-#if CFDictionary
-, const CFSetValueCallBacks *valueCallBacks
-#endif
-) {
-    struct __CFSet *hc;
-    CFIndex size;
-    __CFBitfieldSetValue(flags, 31, 2, 0);
-    CFOptionFlags xflags = 0;
+static uintptr_t __CFSetCallback(CFBasicHashRef ht, uint8_t op, uintptr_t a1, uintptr_t a2, CFBasicHashCallbacks *cb) {
+    switch (op) {
+    case kCFBasicHashCallbackOpCopyCallbacks: {
+        CFBasicHashCallbacks *newcb = NULL;
+        if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
+            newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
+        } else {
+            newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate((CFAllocatorRef)a1, 10 * sizeof(void *), 0);
+        }
+        if (!newcb) HALT;
+        memmove(newcb, (void *)cb, 10 * sizeof(void *));
+        return (uintptr_t)newcb;
+    }
+    case kCFBasicHashCallbackOpFreeCallbacks: {
+        if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
+           auto_zone_release(auto_zone(), cb);
+       } else {
+            CFAllocatorDeallocate((CFAllocatorRef)a1, cb);
+        }
+        return 0;
+    }
+    case kCFBasicHashCallbackOpRetainValue: {
+        const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0];
+        if (NULL == value_retain) return a1;
+        return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpRetainKey: {
+        const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1];
+        if (NULL == key_retain) return a1;
+        return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpReleaseValue: {
+        void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2];
+        if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
+        return 0;
+    }
+    case kCFBasicHashCallbackOpReleaseKey: {
+        void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3];
+        if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
+        return 0;
+    }
+    case kCFBasicHashCallbackOpValueEqual: {
+        Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4];
+        if (NULL == value_equal) return (a1 == a2);
+        return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
+    }
+    case kCFBasicHashCallbackOpKeyEqual: {
+        Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5];
+        if (NULL == key_equal) return (a1 == a2);
+        return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
+    }
+    case kCFBasicHashCallbackOpHashKey: {
+        CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6];
+        if (NULL == hash) return a1;
+        return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpDescribeValue: {
+        CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[7];
+        if (NULL == value_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
+        return (uintptr_t)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t)a1);
+    }
+    case kCFBasicHashCallbackOpDescribeKey: {
+        CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8];
+        if (NULL == key_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
+        return (uintptr_t)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t)a1);
+    }
+    }
+    return 0;
+}
+
+static CFBasicHashRef __CFSetCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
+
+    CFBasicHashCallbacks *cb = NULL;
+    CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
+    flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
+
+    const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
+    Boolean std_cb = false;
+    if ((NULL == keyCallBacks || (keyCallBacks && 0 == memcmp(&__kCFNullSetKeyCallBacks, keyCallBacks, sizeof(__kCFNullSetKeyCallBacks))))
+                && (!useValueCB || (NULL == valueCallBacks || (valueCallBacks && 0 == memcmp(&__kCFNullSetValueCallBacks, valueCallBacks, sizeof(__kCFNullSetValueCallBacks)))))) {
+        cb = (CFBasicHashCallbacks *)& CFBasicHashNullCallbacks;
+    } else if ((&kCFTypeSetKeyCallBacks == keyCallBacks || (keyCallBacks && 0 == memcmp(&kCFTypeSetKeyCallBacks, keyCallBacks, sizeof(kCFTypeSetKeyCallBacks))))
+                && (!useValueCB || (&kCFTypeSetValueCallBacks == valueCallBacks || (valueCallBacks && 0 == memcmp(&kCFTypeSetValueCallBacks, valueCallBacks, sizeof(kCFTypeSetValueCallBacks)))))) {
+        std_cb = true;
+        cb = (CFBasicHashCallbacks *)& CFBasicHashStandardCallbacks;
+    } else {
+        Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
+        Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
+        CFStringRef (*key_describe)(const_any_pointer_t) = NULL;
+        CFStringRef (*value_describe)(const_any_pointer_t) = NULL;
+        CFHashCode (*hash_key)(const_any_pointer_t) = NULL;
+        key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
+        key_release = keyCallBacks ? keyCallBacks->release : NULL;
+        key_equal = keyCallBacks ? keyCallBacks->equal : NULL;
+        key_describe = keyCallBacks ? keyCallBacks->copyDescription : NULL;
+        if (useValueCB) {
+            value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
+            value_release = valueCallBacks ? valueCallBacks->release : NULL;
+            value_equal = valueCallBacks ? valueCallBacks->equal : NULL;
+            value_describe = valueCallBacks ? valueCallBacks->copyDescription : NULL;
+        } else {
+            value_retain = key_retain;
+            value_release = key_release;
+            value_equal = key_equal;
+            value_describe = key_describe;
+        }
+        hash_key = keyCallBacks ? keyCallBacks->hash : NULL;
+        FAULT_CALLBACK((void **)&key_retain);
+        FAULT_CALLBACK((void **)&key_release);
+        FAULT_CALLBACK((void **)&value_retain);
+        FAULT_CALLBACK((void **)&value_release);
+        FAULT_CALLBACK((void **)&key_equal);
+        FAULT_CALLBACK((void **)&value_equal);
+        FAULT_CALLBACK((void **)&key_describe);
+        FAULT_CALLBACK((void **)&value_describe);
+        FAULT_CALLBACK((void **)&hash_key);
+
+        CFBasicHashCallbacks *newcb = NULL;
+        if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+            newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
+        } else {
+            newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, 10 * sizeof(void *), 0);
+        }
+        if (!newcb) HALT;
+        newcb->func = (CFBasicHashCallbackType)__CFSetCallback;
+        newcb->context[0] = (uintptr_t)value_retain;
+        newcb->context[1] = (uintptr_t)key_retain;
+        newcb->context[2] = (uintptr_t)value_release;
+        newcb->context[3] = (uintptr_t)key_release;
+        newcb->context[4] = (uintptr_t)value_equal;
+        newcb->context[5] = (uintptr_t)key_equal;
+        newcb->context[6] = (uintptr_t)hash_key;
+        newcb->context[7] = (uintptr_t)value_describe;
+        newcb->context[8] = (uintptr_t)key_describe;
+        cb = newcb;
+    }
+
     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
-        // preserve NULL for key or value CB, otherwise fix up.
-        if (!keyCallBacks || (keyCallBacks->retain == NULL && keyCallBacks->release == NULL)) {
-            xflags = __kCFHashWeakKeys;
+        if (std_cb || value_retain != NULL || value_release != NULL) {
+            flags |= kCFBasicHashStrongValues;
         }
-#if CFDictionary
-        if (!valueCallBacks || (valueCallBacks->retain == NULL && valueCallBacks->release == NULL)) {
-            xflags |= __kCFHashWeakValues;
+        if (std_cb || key_retain != NULL || key_release != NULL) {
+            flags |= kCFBasicHashStrongKeys;
         }
-#endif
-#if CFBag
-        xflags |= __kCFHashWeakValues;
-#endif
-    }
-    if (__CFSetKeyCallBacksMatchNull(keyCallBacks)) {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasNullCallBacks);
-    } else if (__CFSetKeyCallBacksMatchCFType(keyCallBacks)) {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasCFTypeCallBacks);
-    } else {
-        __CFBitfieldSetValue(flags, 3, 2, __kCFHashHasCustomCallBacks);
-    }
-#if CFDictionary
-    if (__CFSetValueCallBacksMatchNull(valueCallBacks)) {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasNullCallBacks);
-    } else if (__CFSetValueCallBacksMatchCFType(valueCallBacks)) {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasCFTypeCallBacks);
-    } else {
-        __CFBitfieldSetValue(flags, 5, 4, __kCFHashHasCustomCallBacks);
-    }
-#endif
-    size = __CFSetGetSizeOfType(flags) - sizeof(CFRuntimeBase);
-    hc = (struct __CFSet *)_CFRuntimeCreateInstance(allocator, __kCFHashTypeID, size, NULL);
-    if (NULL == hc) {
-        return NULL;
     }
-    hc->_count = 0;
-    hc->_bucketsUsed = 0;
-    hc->_marker = (any_t)0xa1b1c1d3;
-    hc->_context = NULL;
-    hc->_deletes = 0;
-    hc->_mutations = 1;
-    hc->_xflags = xflags | flags;
-    switch (__CFBitfieldGetValue(flags, 1, 0)) {
-    case __kCFHashImmutable:
-        if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFSet (immutable)");
-        break;
-    case __kCFHashMutable:
-        if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFSet (mutable-variable)");
-        break;
-    }
-    hc->_bucketsCap = __CFHashRoundUpCapacity(1);
-    hc->_bucketsNum = 0;
-    hc->_keys = NULL;
-    hc->_values = NULL;
-    if (__kCFHashHasCustomCallBacks == __CFBitfieldGetValue(flags, 3, 2)) {
-        CFSetKeyCallBacks *cb = (CFSetKeyCallBacks *)__CFSetGetKeyCallBacks((CFHashRef)hc);
-        *cb = *keyCallBacks;
-        FAULT_CALLBACK((void **)&(cb->retain));
-        FAULT_CALLBACK((void **)&(cb->release));
-        FAULT_CALLBACK((void **)&(cb->copyDescription));
-        FAULT_CALLBACK((void **)&(cb->equal));
-        FAULT_CALLBACK((void **)&(cb->hash));
-    }
-#if CFDictionary
-    if (__kCFHashHasCustomCallBacks == __CFBitfieldGetValue(flags, 5, 4)) {
-        CFSetValueCallBacks *vcb = (CFSetValueCallBacks *)__CFSetGetValueCallBacks((CFHashRef)hc);
-        *vcb = *valueCallBacks;
-        FAULT_CALLBACK((void **)&(vcb->retain));
-        FAULT_CALLBACK((void **)&(vcb->release));
-        FAULT_CALLBACK((void **)&(vcb->copyDescription));
-        FAULT_CALLBACK((void **)&(vcb->equal));
-    }
-#endif
-    return hc;
+
+    return CFBasicHashCreate(allocator, flags, cb);
 }
 
 #if CFDictionary
-CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *keys, const_any_pointer_t *values, CFIndex numValues, const CFSetKeyCallBacks *keyCallBacks, const CFSetValueCallBacks *valueCallBacks) {
+CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues, const CFSetKeyCallBacks *keyCallBacks, const CFSetValueCallBacks *valueCallBacks) {
 #endif
 #if CFSet || CFBag
-CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *keys, CFIndex numValues, const CFSetKeyCallBacks *keyCallBacks) {
+CFHashRef CFSetCreate(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues, const CFSetKeyCallBacks *keyCallBacks) {
+    const_any_pointer_t *vlist = klist;
+    const CFSetValueCallBacks *valueCallBacks = 0;
 #endif
+    CFTypeID typeID = CFSetGetTypeID();
     CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
-#if CFDictionary
-    CFMutableHashRef hc = __CFSetInit(allocator, __kCFHashImmutable, numValues, keyCallBacks, valueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFSetInit(allocator, __kCFHashImmutable, numValues, keyCallBacks);
-#endif
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashMutable);
+    CFBasicHashRef ht = __CFSetCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+    if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
     for (CFIndex idx = 0; idx < numValues; idx++) {
-#if CFDictionary
-        CFSetAddValue(hc, keys[idx], values[idx]);
-#endif
-#if CFSet || CFBag
-        CFSetAddValue(hc, keys[idx]);
-#endif
+        CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
     }
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    return (CFHashRef)hc;
+    CFBasicHashMakeImmutable(ht);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)");
+    return (CFHashRef)ht;
 }
 
 #if CFDictionary
@@ -782,158 +309,90 @@ CFMutableHashRef CFSetCreateMutable(CFAllocatorRef allocator, CFIndex capacity,
 #endif
 #if CFSet || CFBag
 CFMutableHashRef CFSetCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFSetKeyCallBacks *keyCallBacks) {
+    const CFSetValueCallBacks *valueCallBacks = 0;
 #endif
+    CFTypeID typeID = CFSetGetTypeID();
     CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
-#if CFDictionary
-    CFMutableHashRef hc = __CFSetInit(allocator, __kCFHashMutable, capacity, keyCallBacks, valueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFSetInit(allocator, __kCFHashMutable, capacity, keyCallBacks);
-#endif
-    return hc;
+    CFBasicHashRef ht = __CFSetCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)");
+    return (CFMutableHashRef)ht;
 }
 
-#if CFDictionary || CFSet
-// does not have Add semantics for Bag; it has Set semantics ... is that best?
-static void __CFSetGrow(CFMutableHashRef hc, CFIndex numNewValues);
-
-// This creates a hc which is for CFTypes or NSObjects, with a CFRetain style ownership transfer;
-// the hc does not take a retain (since it claims 1), and the caller does not need to release the inserted objects (since we do it).
-// The incoming objects must also be collectable if allocated out of a collectable allocator - and are neither released nor retained.
-#if CFDictionary
-CFHashRef _CFSetCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const_any_pointer_t *keys, const_any_pointer_t *values, CFIndex numValues) {
-#endif
-#if CFSet || CFBag
-CFHashRef _CFSetCreate_ex(CFAllocatorRef allocator, Boolean isMutable, const_any_pointer_t *keys, CFIndex numValues) {
-#endif
-    CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
-#if CFDictionary
-    CFMutableHashRef hc = __CFSetInit(allocator, __kCFHashMutable, numValues, &kCFTypeSetKeyCallBacks, &kCFTypeSetValueCallBacks);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFSetInit(allocator, __kCFHashMutable, numValues, &kCFTypeSetKeyCallBacks);
-#endif
-    __CFSetGrow(hc, numValues);
-    for (CFIndex idx = 0; idx < numValues; idx++) {
-        CFIndex match, nomatch;
-        __CFSetFindBuckets2(hc, (any_t)keys[idx], &match, &nomatch);
-        if (kCFNotFound == match) {
-            CFAllocatorRef allocator = __CFGetAllocator(hc);
-            any_t newKey = (any_t)keys[idx];
-            if (__CFHashKeyIsMagic(hc, newKey)) {
-                __CFSetFindNewMarker(hc);
-            }
-            if (hc->_keys[nomatch] == ~hc->_marker) {
-                hc->_deletes--;
-            }
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-            any_t newValue = (any_t)values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-            hc->_values[nomatch] = 1;
-#endif
-            hc->_bucketsUsed++;
-            hc->_count++;
-        } else {
-            CFAllocatorRef allocator = __CFGetAllocator(hc);
+CFHashRef CFSetCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
+    CFTypeID typeID = CFSetGetTypeID();
+    CFAssert1(other, __kCFLogAssertion, "%s(): other CFSet cannot be NULL", __PRETTY_FUNCTION__);
+    __CFGenericValidateType(other, typeID);
+    CFBasicHashRef ht = NULL;
+    if (CF_IS_OBJC(typeID, other)) {
+        CFIndex numValues = CFSetGetCount(other);
+        const_any_pointer_t vbuffer[256], kbuffer[256];
+        const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
 #if CFSet || CFBag
-            any_t oldKey = hc->_keys[match];
-            any_t newKey = (any_t)keys[idx];
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-            if (__CFHashKeyIsMagic(hc, newKey)) {
-                __CFSetFindNewMarker(hc);
-            }
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-            RELEASEKEY(oldKey);
+        const_any_pointer_t *klist = vlist;
+        CFSetGetValues(other, vlist);
 #endif
 #if CFDictionary
-            any_t oldValue = hc->_values[match];
-            any_t newValue = (any_t)values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-            RELEASEVALUE(oldValue);
+        const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
+        CFDictionaryGetKeysAndValues(other, klist, vlist);
 #endif
+        ht = __CFSetCreateGeneric(allocator, & kCFTypeSetKeyCallBacks, CFDictionary ? & kCFTypeSetValueCallBacks : NULL, CFDictionary);
+        if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+        for (CFIndex idx = 0; idx < numValues; idx++) {
+            CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
         }
+        if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
+        if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
+    } else {
+        ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
     }
-    if (!isMutable) __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    return (CFHashRef)hc;
-}
-#endif
-
-CFHashRef CFSetCreateCopy(CFAllocatorRef allocator, CFHashRef other) {
-    CFMutableHashRef hc = CFSetCreateMutableCopy(allocator, CFSetGetCount(other), other);
-    __CFBitfieldSetValue(hc->_xflags, 1, 0, __kCFHashImmutable);
-    if (__CFOASafe) __CFSetLastAllocationEventName(hc, "CFSet (immutable)");
-    return hc;
+    CFBasicHashMakeImmutable(ht);
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (immutable)");
+    return (CFHashRef)ht;
 }
 
 CFMutableHashRef CFSetCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFHashRef other) {
-    CFIndex numValues = CFSetGetCount(other);
-    const_any_pointer_t *list, buffer[256];
-    list = (numValues <= 256) ? buffer : (const_any_pointer_t *)CFAllocatorAllocate(allocator, numValues * sizeof(const_any_pointer_t), 0);
-    if (list != buffer && __CFOASafe) __CFSetLastAllocationEventName(list, "CFSet (temp)");
-#if CFDictionary
-    const_any_pointer_t *vlist, vbuffer[256];
-    vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(allocator, numValues * sizeof(const_any_pointer_t), 0);
-    if (vlist != vbuffer && __CFOASafe) __CFSetLastAllocationEventName(vlist, "CFSet (temp)");
-#endif
+    CFTypeID typeID = CFSetGetTypeID();
+    CFAssert1(other, __kCFLogAssertion, "%s(): other CFSet cannot be NULL", __PRETTY_FUNCTION__);
+    __CFGenericValidateType(other, typeID);
+    CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%ld) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
+    CFBasicHashRef ht = NULL;
+    if (CF_IS_OBJC(typeID, other)) {
+        CFIndex numValues = CFSetGetCount(other);
+        const_any_pointer_t vbuffer[256], kbuffer[256];
+        const_any_pointer_t *vlist = (numValues <= 256) ? vbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
 #if CFSet || CFBag
-    CFSetGetValues(other, list);
+        const_any_pointer_t *klist = vlist;
+        CFSetGetValues(other, vlist);
 #endif
 #if CFDictionary
-    CFSetGetKeysAndValues(other, list, vlist);
+        const_any_pointer_t *klist = (numValues <= 256) ? kbuffer : (const_any_pointer_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, numValues * sizeof(const_any_pointer_t), 0);
+        CFDictionaryGetKeysAndValues(other, klist, vlist);
 #endif
-    const CFSetKeyCallBacks *kcb;
-    const CFSetValueCallBacks *vcb;
-    if (CF_IS_OBJC(__kCFHashTypeID, other)) {
-        kcb = &kCFTypeSetKeyCallBacks;
-        vcb = &kCFTypeSetValueCallBacks;
+        ht = __CFSetCreateGeneric(allocator, & kCFTypeSetKeyCallBacks, CFDictionary ? & kCFTypeSetValueCallBacks : NULL, CFDictionary);
+        if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+        for (CFIndex idx = 0; idx < numValues; idx++) {
+            CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
+        }
+        if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
+        if (vlist != vbuffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, vlist);
     } else {
-        kcb = __CFSetGetKeyCallBacks(other);
-        vcb = __CFSetGetValueCallBacks(other);
-    }
-#if CFDictionary
-    CFMutableHashRef hc = __CFSetInit(allocator, __kCFHashMutable, capacity, kcb, vcb);
-#endif
-#if CFSet || CFBag
-    CFMutableHashRef hc = __CFSetInit(allocator, __kCFHashMutable, capacity, kcb);
-#endif
-    if (0 == capacity) _CFSetSetCapacity(hc, numValues);
-    for (CFIndex idx = 0; idx < numValues; idx++) {
-#if CFDictionary
-        CFSetAddValue(hc, list[idx], vlist[idx]);
-#endif
-#if CFSet || CFBag
-        CFSetAddValue(hc, list[idx]);
-#endif
+        ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
     }
-    if (list != buffer) CFAllocatorDeallocate(allocator, list);
-#if CFDictionary
-    if (vlist != vbuffer) CFAllocatorDeallocate(allocator, vlist);
-#endif
-    return hc;
-}
-
-// Used by NSHashTables/NSMapTables and KVO
-void _CFSetSetContext(CFHashRef hc, any_pointer_t context) {
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    CF_WRITE_BARRIER_BASE_ASSIGN(__CFGetAllocator(hc), hc, hc->_context, context);
-}
-
-any_pointer_t _CFSetGetContext(CFHashRef hc) {
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    return hc->_context;
+    *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+    _CFRuntimeSetInstanceTypeID(ht, typeID);
+    if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)");
+    return (CFMutableHashRef)ht;
 }
 
 CFIndex CFSetGetCount(CFHashRef hc) {
-    if (CFDictionary || CFSet) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, CFIndex, hc, "count");
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    return hc->_count;
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFSetTypeID, CFIndex, hc, "count");
+    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFSetTypeID, CFIndex, hc, "count");
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    return CFBasicHashGetCount((CFBasicHashRef)hc);
 }
 
 #if CFDictionary
@@ -942,12 +401,10 @@ CFIndex CFSetGetCountOfKey(CFHashRef hc, const_any_pointer_t key) {
 #if CFSet || CFBag
 CFIndex CFSetGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    CFIndex match = __CFSetFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? __CFHashGetOccurrenceCount(hc, match) : 0);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, CFIndex, hc, "countForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, CFIndex, hc, "countForObject:", key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
 }
 
 #if CFDictionary
@@ -956,74 +413,66 @@ Boolean CFSetContainsKey(CFHashRef hc, const_any_pointer_t key) {
 #if CFSet || CFBag
 Boolean CFSetContainsValue(CFHashRef hc, const_any_pointer_t key) {
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFSetFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? true : false);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, char, hc, "containsKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, char, hc, "containsObject:", key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
 }
 
-#if CFDictionary
-CFIndex CFSetGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
-    CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, CFIndex, hc, "countForObject:", value);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    any_t *keys = hc->_keys;
-    Boolean (*equal)(any_t, any_t, any_pointer_t) = (Boolean (*)(any_t, any_t, any_pointer_t))__CFSetGetValueCallBacks(hc)->equal;
-    CFIndex cnt = 0;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            if ((hc->_values[idx] == (any_t)value) || (equal && INVOKE_CALLBACK3(equal, hc->_values[idx], (any_t)value, hc->_context))) {
-                cnt++;
-            }
-        }
-    }
-    return cnt;
+const_any_pointer_t CFSetGetValue(CFHashRef hc, const_any_pointer_t key) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, const_any_pointer_t, hc, "objectForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, const_any_pointer_t, hc, "member:", key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
 }
 
-Boolean CFSetContainsValue(CFHashRef hc, const_any_pointer_t value) {
-    CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, char, hc, "containsObject:", value);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    any_t *keys = hc->_keys;
-    Boolean (*equal)(any_t, any_t, any_pointer_t) = (Boolean (*)(any_t, any_t, any_pointer_t))__CFSetGetValueCallBacks(hc)->equal;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            if ((hc->_values[idx] == (any_t)value) || (equal && INVOKE_CALLBACK3(equal, hc->_values[idx], (any_t)value, hc->_context))) {
-                return true;
+Boolean CFSetGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, Boolean, hc, "_getValue:forKey:", (any_t *)value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, Boolean, hc, "_getValue:forObj:", (any_t *)value, key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    if (0 < bkt.count) {
+        if (value) {
+            if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongValues)) {
+                __CFAssignWithWriteBarrier((void **)value, (void *)bkt.weak_value);
+            } else {
+                *value = (const_any_pointer_t)bkt.weak_value;
             }
         }
+        return true;
     }
     return false;
 }
-#endif
 
-const_any_pointer_t CFSetGetValue(CFHashRef hc, const_any_pointer_t key) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, const_any_pointer_t, hc, "objectForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, const_any_pointer_t, hc, "member:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return 0;
-    CFIndex match = __CFSetFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? (const_any_pointer_t)(CFDictionary ? hc->_values[match] : hc->_keys[match]) : 0);
+#if CFDictionary
+CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
+    CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, CFIndex, hc, "countForObject:", value);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
 }
 
-Boolean CFSetGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "_getValue:forKey:", (any_t *)value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "_getValue:forObj:", (any_t *)value, key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFSetFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? ((value ? __CFObjCStrongAssign((const_any_pointer_t)(CFDictionary ? hc->_values[match] : hc->_keys[match]), value) : 0), true) : false);
+Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
+    CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, char, hc, "containsObject:", value);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
 }
 
-#if CFDictionary
-Boolean CFSetGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
-    CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (0 == hc->_bucketsUsed) return false;
-    CFIndex match = __CFSetFindBuckets1(hc, (any_t)key);
-    return (kCFNotFound != match ? ((actualkey ? __CFObjCStrongAssign((const_any_pointer_t)hc->_keys[match], actualkey) : NULL), true) : false);
+CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
+    CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
+    if (0 < bkt.count) {
+        if (actualkey) {
+            if (kCFUseCollectableAllocator && (CFBasicHashGetFlags((CFBasicHashRef)hc) & kCFBasicHashStrongKeys)) {
+                __CFAssignWithWriteBarrier((void **)actualkey, (void *)bkt.weak_key);
+            } else {
+                *actualkey = (const_any_pointer_t)bkt.weak_key;
+            }
+        }
+        return true;
+    }
+    return false;
 }
 #endif
 
@@ -1034,183 +483,113 @@ void CFSetGetKeysAndValues(CFHashRef hc, const_any_pointer_t *keybuf, const_any_
 void CFSetGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
     const_any_pointer_t *valuebuf = 0;
 #endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "getObjects:", (any_t *)keybuf);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    if (CF_USING_COLLECTABLE_MEMORY) {
-        // GC: speculatively issue a write-barrier on the copied to buffers
-        __CFObjCWriteBarrierRange(keybuf, hc->_count * sizeof(any_t));
-        __CFObjCWriteBarrierRange(valuebuf, hc->_count * sizeof(any_t));
-    }
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            for (CFIndex cnt = __CFHashGetOccurrenceCount(hc, idx); cnt--;) {
-                if (keybuf) *keybuf++ = (const_any_pointer_t)keys[idx];
-                if (valuebuf) *valuebuf++ = (const_any_pointer_t)hc->_values[idx];
-            }
-        }
-    }
-}
-
-#if CFDictionary || CFSet
-unsigned long _CFSetFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
-    /* copy as many as count items over */
-    if (0 == state->state) {        /* first time */
-        state->mutationsPtr = (unsigned long *)&hc->_mutations;
-    }
-    state->itemsPtr = (unsigned long *)stackbuffer;
-    CFIndex cnt = 0;
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = (CFIndex)state->state, nbuckets = hc->_bucketsNum; idx < nbuckets && cnt < (CFIndex)count; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            state->itemsPtr[cnt++] = (unsigned long)keys[idx];
-        }
-        state->state++;
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "getObjects:", (any_t *)keybuf);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    if (kCFUseCollectableAllocator) {
+        CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
+        __block const_any_pointer_t *keys = keybuf, *values = valuebuf;
+        CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
+                for (CFIndex cnt = bkt.count; cnt--;) {
+                    if (keybuf && (flags & kCFBasicHashStrongKeys)) { __CFAssignWithWriteBarrier((void **)keys, (void *)bkt.weak_key); keys++; }
+                    if (keybuf && !(flags & kCFBasicHashStrongKeys)) { *keys++ = (const_any_pointer_t)bkt.weak_key; }
+                    if (valuebuf && (flags & kCFBasicHashStrongValues)) { __CFAssignWithWriteBarrier((void **)values, (void *)bkt.weak_value); values++; }
+                    if (valuebuf && !(flags & kCFBasicHashStrongValues)) { *values++ = (const_any_pointer_t)bkt.weak_value; }
+                }
+                return (Boolean)true;
+            });
+    } else {
+        CFBasicHashGetElements((CFBasicHashRef)hc, CFSetGetCount(hc), (uintptr_t *)valuebuf, NULL, (uintptr_t *)keybuf, NULL);
     }
-    return cnt;
 }
-#endif
 
 void CFSetApplyFunction(CFHashRef hc, CFSetApplierFunction applier, any_pointer_t context) {
     FAULT_CALLBACK((void **)&(applier));
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_apply:context:", applier, context);
-    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_applyValues:context:", applier, context);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            for (CFIndex cnt = __CFHashGetOccurrenceCount(hc, idx); cnt--;) {
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "_apply:context:", applier, context);
+    if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "_applyValues:context:", applier, context);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
 #if CFDictionary
-                INVOKE_CALLBACK3(applier, (const_any_pointer_t)keys[idx], (const_any_pointer_t)hc->_values[idx], context);
+            INVOKE_CALLBACK3(applier, (const_any_pointer_t)bkt.weak_key, (const_any_pointer_t)bkt.weak_value, context);
 #endif
-#if CFSet || CFBag
-                INVOKE_CALLBACK2(applier, (const_any_pointer_t)keys[idx], context);
+#if CFSet
+            INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
 #endif
+#if CFBag
+            for (CFIndex cnt = bkt.count; cnt--;) {
+                INVOKE_CALLBACK2(applier, (const_any_pointer_t)bkt.weak_value, context);
             }
-        }
-    }
+#endif
+            return (Boolean)true;
+        });
 }
 
-static void __CFSetGrow(CFMutableHashRef hc, CFIndex numNewValues) {
-    any_t *oldkeys = hc->_keys;
-    any_t *oldvalues = hc->_values;
-    CFIndex nbuckets = hc->_bucketsNum;
-    hc->_bucketsCap = __CFHashRoundUpCapacity(hc->_bucketsUsed + numNewValues);
-    hc->_bucketsNum = __CFHashNumBucketsForCapacity(hc->_bucketsCap);
-    hc->_deletes = 0;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    CFOptionFlags weakOrStrong = (hc->_xflags & __kCFHashWeakKeys) ? 0 : __kCFAllocatorGCScannedMemory;
-    any_t *mem = (any_t *)_CFAllocatorAllocateGC(allocator, hc->_bucketsNum * sizeof(any_t), weakOrStrong);
-    if (NULL == mem) __CFSetHandleOutOfMemory(hc, hc->_bucketsNum * sizeof(any_t));
-    if (__CFOASafe) __CFSetLastAllocationEventName(mem, "CFSet (key-store)");
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, hc, hc->_keys, mem);
-    CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;  // GC: avoids write-barrier in weak case.
-    any_t *keysBase = mem;
-#if CFDictionary || CFBag
-    weakOrStrong = (hc->_xflags & __kCFHashWeakValues) ? 0 : __kCFAllocatorGCScannedMemory;
-    mem = (any_t *)_CFAllocatorAllocateGC(allocator, hc->_bucketsNum * sizeof(any_t), weakOrStrong);
-    if (NULL == mem) __CFSetHandleOutOfMemory(hc, hc->_bucketsNum * sizeof(any_t));
-    if (__CFOASafe) __CFSetLastAllocationEventName(mem, "CFSet (value-store)");
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, hc, hc->_values, mem);
-#endif
-#if CFDictionary
-    CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator; // GC: avoids write-barrier in weak case.
-    any_t *valuesBase = mem;
-#endif
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        hc->_keys[idx] = hc->_marker;
-#if CFDictionary || CFBag
-        hc->_values[idx] = 0;
-#endif
-    }
-    if (NULL == oldkeys) return;
-    for (CFIndex idx = 0; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, oldkeys[idx])) {
-            CFIndex match, nomatch;
-            __CFSetFindBuckets2(hc, oldkeys[idx], &match, &nomatch);
-            CFAssert3(kCFNotFound == match, __kCFLogAssertion, "%s(): two values (%p, %p) now hash to the same slot; mutable value changed while in table or hash value is not immutable", __PRETTY_FUNCTION__, oldkeys[idx], hc->_keys[match]);
-            if (kCFNotFound != nomatch) {
-                CF_WRITE_BARRIER_BASE_ASSIGN(keysAllocator, keysBase, hc->_keys[nomatch], oldkeys[idx]);
-#if CFDictionary
-                CF_WRITE_BARRIER_BASE_ASSIGN(valuesAllocator, valuesBase, hc->_values[nomatch], oldvalues[idx]);
-#endif
-#if CFBag
-                hc->_values[nomatch] = oldvalues[idx];
-#endif
-            }
-        }
-    }
-    _CFAllocatorDeallocateGC(allocator, oldkeys);
-    _CFAllocatorDeallocateGC(allocator, oldvalues);
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT unsigned long _CFSetFastEnumeration(CFHashRef hc, struct __objcFastEnumerationStateEquivalent *state, void *stackbuffer, unsigned long count) {
+    if (CF_IS_OBJC(__kCFSetTypeID, hc)) return 0;
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    return __CFBasicHashFastEnumeration((CFBasicHashRef)hc, (struct __objcFastEnumerationStateEquivalent2 *)state, stackbuffer, count);
 }
 
 // This function is for Foundation's benefit; no one else should use it.
-void _CFSetSetCapacity(CFMutableHashRef hc, CFIndex cap) {
-    if (CF_IS_OBJC(__kCFHashTypeID, hc)) return;
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    CFAssert1(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): collection is immutable", __PRETTY_FUNCTION__);
-    CFAssert3(hc->_bucketsUsed <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than bucket count (%ld)", __PRETTY_FUNCTION__, cap, hc->_bucketsUsed);
-    __CFSetGrow(hc, cap - hc->_bucketsUsed);
+CF_EXPORT Boolean _CFSetIsMutable(CFHashRef hc) {
+    if (CF_IS_OBJC(__kCFSetTypeID, hc)) return false;
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    return CFBasicHashIsMutable((CFBasicHashRef)hc);
 }
 
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT void _CFSetSetCapacity(CFMutableHashRef hc, CFIndex cap) {
+    if (CF_IS_OBJC(__kCFSetTypeID, hc)) return;
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    CFAssert3(CFSetGetCount(hc) <= cap, __kCFLogAssertion, "%s(): desired capacity (%ld) is less than count (%ld)", __PRETTY_FUNCTION__, cap, CFSetGetCount(hc));
+    CFBasicHashSetCapacity((CFBasicHashRef)hc, cap);
+}
+
+CF_INLINE CFIndex __CFSetGetKVOBit(CFHashRef hc) {
+    return __CFBitfieldGetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0);
+}
+
+CF_INLINE void __CFSetSetKVOBit(CFHashRef hc, CFIndex bit) {
+    __CFBitfieldSetValue(((CFRuntimeBase *)hc)->_cfinfo[CF_INFO_BITS], 0, 0, ((uintptr_t)bit & 0x1));
+}
+
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT CFIndex _CFSetGetKVOBit(CFHashRef hc) {
+    return __CFSetGetKVOBit(hc);
+}
+
+// This function is for Foundation's benefit; no one else should use it.
+CF_EXPORT void _CFSetSetKVOBit(CFHashRef hc, CFIndex bit) {
+    __CFSetSetKVOBit(hc, bit);
+}
+
+
+#if !defined(CF_OBJC_KVO_WILLCHANGE)
+#define CF_OBJC_KVO_WILLCHANGE(obj, key)
+#define CF_OBJC_KVO_DIDCHANGE(obj, key)
+#define CF_OBJC_KVO_WILLCHANGEALL(obj)
+#define CF_OBJC_KVO_DIDCHANGEALL(obj)
+#endif
 
 #if CFDictionary
 void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_pointer_t value) {
 #endif
 #if CFSet || CFBag
 void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
-#endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_addObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "addObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        if (hc->_bucketsUsed == hc->_bucketsCap || NULL == hc->_keys) {
-            __CFSetGrow(hc, 1);
-        }
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    CFIndex match, nomatch;
-    __CFSetFindBuckets2(hc, (any_t)key, &match, &nomatch);
-    if (kCFNotFound != match) {
-#if CFBag
-        CF_OBJC_KVO_WILLCHANGE(hc, hc->_keys[match]);
-        hc->_values[match]++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, hc->_keys[match]);
-#endif
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        GETNEWKEY(newKey, key);
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFSetFindNewMarker(hc);
-        }
-        if (hc->_keys[nomatch] == ~hc->_marker) {
-            hc->_deletes--;
-        }
-        CF_OBJC_KVO_WILLCHANGE(hc, key);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-        hc->_values[nomatch] = 1;
+    const_any_pointer_t value = key;
 #endif
-        hc->_bucketsUsed++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, key);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "addObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "addObject:", key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashAddValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 #if CFDictionary
@@ -1218,51 +597,18 @@ void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_p
 #endif
 #if CFSet || CFBag
 void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
-#endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "_replaceObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "_replaceObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFIndex match = __CFSetFindBuckets1(hc, (any_t)key);
-    if (kCFNotFound == match) return;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-#if CFSet || CFBag
-    GETNEWKEY(newKey, key);
-#endif
-#if CFDictionary
-    GETNEWVALUE(newValue);
+    const_any_pointer_t value = key;
 #endif
-    any_t oldKey = hc->_keys[match];
-    CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFSet || CFBag
-    CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-    CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-    if (__CFHashKeyIsMagic(hc, newKey)) {
-        __CFSetFindNewMarker(hc);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "replaceObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "replaceObject:", key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
-    CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-#endif
-#if CFDictionary
-    any_t oldValue = hc->_values[match];
-    CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-    CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-#endif
-    CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-#if CFSet || CFBag
-    RELEASEKEY(oldKey);
-#endif
-#if CFDictionary
-    RELEASEVALUE(oldValue);
-#endif
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashReplaceValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 #if CFDictionary
@@ -1270,198 +616,49 @@ void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key, const_any_point
 #endif
 #if CFSet || CFBag
 void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    #define value 0
-#endif
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFHashTypeID, void, hc, "setObject:forKey:", value, key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "_setObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        if (hc->_bucketsUsed == hc->_bucketsCap || NULL == hc->_keys) {
-            __CFSetGrow(hc, 1);
-        }
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    CFIndex match, nomatch;
-    __CFSetFindBuckets2(hc, (any_t)key, &match, &nomatch);
-    if (kCFNotFound == match) {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        GETNEWKEY(newKey, key);
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFSetFindNewMarker(hc);
-        }
-        if (hc->_keys[nomatch] == ~hc->_marker) {
-            hc->_deletes--;
-        }
-        CF_OBJC_KVO_WILLCHANGE(hc, key);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[nomatch], newKey);
-#if CFDictionary
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[nomatch], newValue);
-#endif
-#if CFBag
-        hc->_values[nomatch] = 1;
-#endif
-        hc->_bucketsUsed++;
-        hc->_count++;
-        CF_OBJC_KVO_DIDCHANGE(hc, key);
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-#if CFSet || CFBag
-        GETNEWKEY(newKey, key);
-#endif
-#if CFDictionary
-        GETNEWVALUE(newValue);
-#endif
-        any_t oldKey = hc->_keys[match];
-        CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFSet || CFBag
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-        if (__CFHashKeyIsMagic(hc, newKey)) {
-            __CFSetFindNewMarker(hc);
-        }
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], newKey);
-#endif
-#if CFDictionary
-        any_t oldValue = hc->_values[match];
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], newValue);
-#endif
-        CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-#if CFSet || CFBag
-        RELEASEKEY(oldKey);
-#endif
-#if CFDictionary
-        RELEASEVALUE(oldValue);
+    const_any_pointer_t value = key;
 #endif
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "setObject:forKey:", value, key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "_setObject:", key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+//#warning this for a dictionary used to not replace the key
+    CFBasicHashSetValue((CFBasicHashRef)hc, (uintptr_t)key, (uintptr_t)value);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 void CFSetRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "removeObjectForKey:", key);
-    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFHashTypeID, void, hc, "removeObject:", key);
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFIndex match = __CFSetFindBuckets1(hc, (any_t)key);
-    if (kCFNotFound == match) return;
-    if (1 < __CFHashGetOccurrenceCount(hc, match)) {
-#if CFBag
-        CF_OBJC_KVO_WILLCHANGE(hc, hc->_keys[match]);
-        hc->_values[match]--;
-        hc->_count--;
-        CF_OBJC_KVO_DIDCHANGE(hc, hc->_keys[match]);
-#endif
-    } else {
-        CFAllocatorRef allocator = __CFGetAllocator(hc);
-        any_t oldKey = hc->_keys[match];
-        CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-        CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[match], ~hc->_marker);
-#if CFDictionary
-        any_t oldValue = hc->_values[match];
-        CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-        CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[match], 0);
-#endif
-#if CFBag
-        hc->_values[match] = 0;
-#endif
-        hc->_count--;
-        hc->_bucketsUsed--;
-        hc->_deletes++;
-        CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-        RELEASEKEY(oldKey);
-#if CFDictionary
-        RELEASEVALUE(oldValue);
-#endif
-        if (__CFSetShouldShrink(hc)) {
-            __CFSetGrow(hc, 0);
-        } else {
-            // When the probeskip == 1 always and only, a DELETED slot followed by an EMPTY slot
-            // can be converted to an EMPTY slot.  By extension, a chain of DELETED slots followed
-            // by an EMPTY slot can be converted to EMPTY slots, which is what we do here.
-            if (match < hc->_bucketsNum - 1 && hc->_keys[match + 1] == hc->_marker) {
-                while (0 <= match && hc->_keys[match] == ~hc->_marker) {
-                    hc->_keys[match] = hc->_marker;
-                    hc->_deletes--;
-                    match--;
-                }
-            }
-        }
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "removeObjectForKey:", key);
+    if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "removeObject:", key);
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGE(hc, key);
+    CFBasicHashRemoveValue((CFBasicHashRef)hc, (uintptr_t)key);
+    CF_OBJC_KVO_DIDCHANGE(hc, key);
 }
 
 void CFSetRemoveAllValues(CFMutableHashRef hc) {
-    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, void, hc, "removeAllObjects");
-    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFHashTypeID, void, hc, "removeAllObjects");
-    __CFGenericValidateType(hc, __kCFHashTypeID);
-    switch (__CFHashGetType(hc)) {
-    case __kCFHashMutable:
-        break;
-    default:
-        CFAssert2(__CFHashGetType(hc) != __kCFHashImmutable, __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
-        break;
-    }
-    hc->_mutations++;
-    if (0 == hc->_bucketsUsed) return;
-    CFAllocatorRef allocator = __CFGetAllocator(hc);
-    any_t *keys = hc->_keys;
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        if (__CFHashKeyIsValue(hc, keys[idx])) {
-            any_t oldKey = keys[idx];
-            CF_OBJC_KVO_WILLCHANGE(hc, oldKey);
-#if CFDictionary || CFSet
-            hc->_count--;
-#endif
-#if CFBag
-            hc->_count -= hc->_values[idx];
-#endif
-            CFAllocatorRef keysAllocator = (hc->_xflags & __kCFHashWeakKeys) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(keysAllocator, hc->_keys[idx], ~hc->_marker);
-#if CFDictionary
-            any_t oldValue = hc->_values[idx];
-            CFAllocatorRef valuesAllocator = (hc->_xflags & __kCFHashWeakValues) ? kCFAllocatorNull : allocator;
-            CF_WRITE_BARRIER_ASSIGN(valuesAllocator, hc->_values[idx], 0);
-#endif
-#if CFBag
-            hc->_values[idx] = 0;
-#endif
-            hc->_bucketsUsed--;
-            hc->_deletes++;
-            CF_OBJC_KVO_DIDCHANGE(hc, oldKey);
-            RELEASEKEY(oldKey);
-#if CFDictionary
-            RELEASEVALUE(oldValue);
-#endif
-        }
-    }
-    for (CFIndex idx = 0, nbuckets = hc->_bucketsNum; idx < nbuckets; idx++) {
-        keys[idx] = hc->_marker;
-    }
-    hc->_deletes = 0;
-    hc->_bucketsUsed = 0;
-    hc->_count = 0;
-    if (__CFSetShouldShrink(hc) && (256 <= hc->_bucketsCap)) {
-        __CFSetGrow(hc, 128);
+    if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFSetTypeID, void, hc, "removeAllObjects");
+    if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFSetTypeID, void, hc, "removeAllObjects");
+    __CFGenericValidateType(hc, __kCFSetTypeID);
+    CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
+    if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
+        CFLog(3, CFSTR("%s(): immutable collection %p given to mutating function"), __PRETTY_FUNCTION__, hc);
     }
+    CF_OBJC_KVO_WILLCHANGEALL(hc);
+    CFBasicHashRemoveAllValues((CFBasicHashRef)hc);
+    CF_OBJC_KVO_DIDCHANGEALL(hc);
 }
 
 #undef CF_OBJC_KVO_WILLCHANGE
 #undef CF_OBJC_KVO_DIDCHANGE
+#undef CF_OBJC_KVO_WILLCHANGEALL
+#undef CF_OBJC_KVO_DIDCHANGEALL
 
diff --git a/CFSet.h b/CFSet.h
index 7da0aea5002c899555c43a3fc506a84e07c6bd9b..e9c11e7ab21ee87fbe0500b6230996414beb8bf5 100644 (file)
--- a/CFSet.h
+++ b/CFSet.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFSet.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 /*!
         @header CFSet
index 30b961e1895f682141ee7865009f83aca8a618bc..8f7e68d9a4ed12acd638e155b48bddcfd7a15034 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFSocket.c
-       Copyright (c) 1999-2007 Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
        Responsibility: Christopher Kane
 */
 
-#define _DARWIN_UNLIMITED_SELECT 1
+#define NEW_SOCKET 0
+
+#if NEW_SOCKET
+
+
+#include <CoreFoundation/CFSocket.h>
+#include "CFInternal.h"
+#include <dispatch/dispatch.h>
+#include <netinet/in.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+
+
+extern void _CFRunLoopSourceWakeUpRunLoops(CFRunLoopSourceRef rls);
+
+#define INVALID_SOCKET (CFSocketNativeHandle)(-1)
+#define MAX_SOCKADDR_LEN 256
+
+
+DISPATCH_HELPER_FUNCTIONS(sock, CFSocket)
+
+
+enum {
+    kCFSocketStateReady = 0,
+    kCFSocketStateInvalidating = 1,
+    kCFSocketStateInvalid = 2,
+    kCFSocketStateDeallocating = 3
+};
+
+struct __shared_blob {
+    dispatch_source_t _rdsrc;
+    dispatch_source_t _wrsrc;
+    CFRunLoopSourceRef _source;
+    CFSocketNativeHandle _socket;
+    uint8_t _closeFD;
+    uint8_t _refCnt;
+};
+
+struct __CFSocket {
+    CFRuntimeBase _base;
+    struct __shared_blob *_shared; /* non-NULL when valid, NULL when invalid */
+
+    uint8_t _state:2;         /* mutable, not written safely */
+    uint8_t _isSaneFD:1;      /* immutable */
+    uint8_t _connOriented:1;  /* immutable */
+    uint8_t _wantConnect:1;   /* immutable */
+    uint8_t _wantWrite:1;     /* immutable */
+    uint8_t _wantReadType:2;  /* immutable */
+
+    uint8_t _error;
+
+    uint8_t _rsuspended:1;
+    uint8_t _wsuspended:1;
+    uint8_t _readable:1;
+    uint8_t _writeable:1;
+    uint8_t _unused2:4;
+
+    uint8_t _reenableRead:1;
+    uint8_t _readDisabled:1;
+    uint8_t _reeanbleWrite:1;
+    uint8_t _writeDisabled:1;
+    uint8_t _connectDisabled:1;
+    uint8_t _connected:1;
+    uint8_t _leaveErrors:1;
+    uint8_t _closeOnInvalidate:1;
+
+    int32_t _runLoopCounter;
+
+    CFDataRef _address;         /* immutable, once created */
+    CFDataRef _peerAddress;     /* immutable, once created */
+    CFSocketCallBack _callout;  /* immutable */
+    CFSocketContext _context;   /* immutable */
+};
+
+
+CF_INLINE Boolean __CFSocketIsValid(CFSocketRef sock) {
+    return kCFSocketStateReady == sock->_state;
+}
+
+static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) {
+    CFSocketRef sock = (CFSocketRef)cf;
+    CFStringRef contextDesc = NULL;
+    if (NULL != sock->_context.info && NULL != sock->_context.copyDescription) {
+        contextDesc = sock->_context.copyDescription(sock->_context.info);
+    }
+    if (NULL == contextDesc) {
+        contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFSocket context %p>"), sock->_context.info);
+    }
+    Dl_info info;
+    void *addr = sock->_callout;
+    const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
+    int avail = -1;
+    ioctl(sock->_shared ? sock->_shared->_socket : -1, FIONREAD, &avail);
+    CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR(
+            "<CFSocket %p [%p]>{valid = %s, socket = %d, "
+            "want connect = %s, connect disabled = %s, "
+            "want write = %s, reenable write = %s, write disabled = %s, "
+            "want read = %s, reenable read = %s, read disabled = %s, "
+            "leave errors = %s, close on invalidate = %s, connected = %s, "
+            "last error code = %d, bytes available for read = %d, "
+            "source = %p, callout = %s (%p), context = %@}"),
+        cf, CFGetAllocator(sock), __CFSocketIsValid(sock) ? "Yes" : "No", sock->_shared ? sock->_shared->_socket : -1,
+        sock->_wantConnect ? "Yes" : "No", sock->_connectDisabled ? "Yes" : "No",
+        sock->_wantWrite ? "Yes" : "No", sock->_reeanbleWrite ? "Yes" : "No", sock->_writeDisabled ? "Yes" : "No",
+        sock->_wantReadType ? "Yes" : "No", sock->_reenableRead ? "Yes" : "No", sock->_readDisabled? "Yes" : "No",
+        sock->_leaveErrors ? "Yes" : "No", sock->_closeOnInvalidate ? "Yes" : "No", sock->_connected ? "Yes" : "No",
+        sock->_error, avail,
+        sock->_shared ? sock->_shared->_source : NULL, name, addr, contextDesc);
+    if (NULL != contextDesc) {
+        CFRelease(contextDesc);
+    }
+    return result;
+}
+
+static void __CFSocketDeallocate(CFTypeRef cf) {
+    CHECK_FOR_FORK_RET();
+    CFSocketRef sock = (CFSocketRef)cf;
+    /* Since CFSockets are cached, we can only get here sometime after being invalidated */
+    sock->_state = kCFSocketStateDeallocating;
+    if (sock->_peerAddress) {
+        CFRelease(sock->_peerAddress);
+        sock->_peerAddress = NULL;
+    }
+    if (sock->_address) {
+        CFRelease(sock->_address);
+        sock->_address = NULL;
+    }
+}
+
+static CFTypeID __kCFSocketTypeID = _kCFRuntimeNotATypeID;
+
+static const CFRuntimeClass __CFSocketClass = {
+    0,
+    "CFSocket",
+    NULL,      // init
+    NULL,      // copy
+    __CFSocketDeallocate,
+    NULL,      // equal
+    NULL,      // hash
+    NULL,      // 
+    __CFSocketCopyDescription
+};
+
+static CFMutableArrayRef __CFAllSockets = NULL;
+
+CFTypeID CFSocketGetTypeID(void) {
+    if (_kCFRuntimeNotATypeID == __kCFSocketTypeID) {
+        __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
+        __CFAllSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+        struct rlimit lim1;
+        int ret1 = getrlimit(RLIMIT_NOFILE, &lim1);
+        int mib[] = {CTL_KERN, KERN_MAXFILESPERPROC};
+        int maxfd = 0;
+        size_t len = sizeof(int);
+        int ret0 = sysctl(mib, 2, &maxfd, &len, NULL, 0);
+        if (0 == ret0 && 0 == ret1 && lim1.rlim_max < maxfd) maxfd = lim1.rlim_max;
+        if (0 == ret1 && lim1.rlim_cur < maxfd) {
+            struct rlimit lim2 = lim1;
+            lim2.rlim_cur += 2304;
+            if (maxfd < lim2.rlim_cur) lim2.rlim_cur = maxfd;
+            setrlimit(RLIMIT_NOFILE, &lim2);
+            // we try, but do not go to extraordinary measures
+        }
+    }
+    return __kCFSocketTypeID;
+}
+
+CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle ufd, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
+    CHECK_FOR_FORK_RET(NULL);
+
+    CFSocketGetTypeID(); // cause initialization if necessary
+
+    struct stat statbuf;
+    int ret = fstat(ufd, &statbuf);
+    if (ret < 0) ufd = INVALID_SOCKET;
+
+    Boolean sane = false;
+    if (INVALID_SOCKET != ufd) {
+        uint32_t type = (statbuf.st_mode & S_IFMT);
+        sane = (S_IFSOCK == type) || (S_IFIFO == type) || (S_IFCHR == type);
+        if (0 && !sane) {
+            CFLog(kCFLogLevelWarning, CFSTR("*** CFSocketCreateWithNative(): creating CFSocket with silly fd type (%07o) -- may or may not work"), type);
+        }
+    }
+
+    if (INVALID_SOCKET != ufd) {
+        Boolean canHandle = false;
+        int tmp_kq = kqueue();
+        if (0 <= tmp_kq) {
+            struct kevent ev[2];
+            EV_SET(&ev[0], ufd, EVFILT_READ, EV_ADD, 0, 0, 0);
+            EV_SET(&ev[1], ufd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
+            int ret = kevent(tmp_kq, ev, 2, NULL, 0, NULL);
+            canHandle = (0 <= ret); // if kevent(ADD) succeeds, can handle
+            close(tmp_kq);
+        }
+        if (0 && !canHandle) {
+            CFLog(kCFLogLevelWarning, CFSTR("*** CFSocketCreateWithNative(): creating CFSocket with unsupported fd type -- may or may not work"));
+        }
+    }
+
+    if (INVALID_SOCKET == ufd) {
+        // Historically, bad ufd was allowed, but gave an uncached and already-invalid CFSocketRef
+        SInt32 size = sizeof(struct __CFSocket) - sizeof(CFRuntimeBase);
+        CFSocketRef memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, CFSocketGetTypeID(), size, NULL);
+        if (NULL == memory) {
+            return NULL;
+        }
+        memory->_callout = callout;
+        memory->_state = kCFSocketStateInvalid;
+        return memory;
+    }
+
+    __block CFSocketRef sock = NULL;
+    dispatch_sync(__sockQueue(), ^{
+            for (CFIndex idx = 0, cnt = CFArrayGetCount(__CFAllSockets); idx < cnt; idx++) {
+                CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFAllSockets, idx);
+                if (s->_shared->_socket == ufd) {
+                    CFRetain(s);
+                    sock = s;
+                    return;
+                }
+            }
+
+            SInt32 size = sizeof(struct __CFSocket) - sizeof(CFRuntimeBase);
+            CFSocketRef memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, CFSocketGetTypeID(), size, NULL);
+            if (NULL == memory) {
+                return;
+            }
+
+            int socketType = 0;
+            if (INVALID_SOCKET != ufd) {
+                socklen_t typeSize = sizeof(socketType);
+                int ret = getsockopt(ufd, SOL_SOCKET, SO_TYPE, (void *)&socketType, (socklen_t *)&typeSize);
+                if (ret < 0) socketType = 0;
+            }
+
+            memory->_rsuspended = true;
+            memory->_wsuspended = true;
+            memory->_readable = false;
+            memory->_writeable = false;
+
+            memory->_isSaneFD = sane ? 1 : 0;
+            memory->_wantReadType = (callBackTypes & 0x3);
+            memory->_reenableRead = memory->_wantReadType ? true : false;
+            memory->_readDisabled = false;
+            memory->_wantWrite = (callBackTypes & kCFSocketWriteCallBack) ? true : false;
+            memory->_reeanbleWrite = false;
+            memory->_writeDisabled = false;
+            memory->_wantConnect = (callBackTypes & kCFSocketConnectCallBack) ? true : false;
+            memory->_connectDisabled = false;
+            memory->_leaveErrors = false;
+            memory->_closeOnInvalidate = true;
+            memory->_connOriented = (SOCK_STREAM == socketType || SOCK_SEQPACKET == socketType);
+            memory->_connected = (memory->_wantReadType == kCFSocketAcceptCallBack || !memory->_connOriented) ? true : false;
+
+            memory->_error = 0;
+            memory->_runLoopCounter = 0;
+            memory->_address = NULL;
+            memory->_peerAddress = NULL;
+            memory->_context.info = NULL;
+            memory->_context.retain = NULL;
+            memory->_context.release = NULL;
+            memory->_context.copyDescription = NULL;
+            memory->_callout = callout;
+            if (NULL != context) {
+                objc_memmove_collectable(&memory->_context, context, sizeof(CFSocketContext));
+                memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info;
+            }
+
+            struct __shared_blob *shared = malloc(sizeof(struct __shared_blob));
+            shared->_rdsrc = NULL;
+            shared->_wrsrc = NULL;
+            shared->_source = NULL;
+            shared->_socket = ufd;
+            shared->_closeFD = true; // copy of _closeOnInvalidate
+            shared->_refCnt = 1; // one for the CFSocket
+            memory->_shared = shared;
+
+            if (memory->_wantReadType) {
+                dispatch_source_t dsrc = NULL;
+                if (sane) {
+                    dsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ufd, 0, __sockQueue());
+                } else {
+                    dsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, __sockQueue());
+                    dispatch_source_set_timer(dsrc, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC / 2, NSEC_PER_SEC);
+                }
+                dispatch_block_t event_block = ^{
+                        memory->_readable = true;
+                        if (!memory->_rsuspended) {
+                            dispatch_suspend(dsrc);
+                            memory->_rsuspended = true;
+                        }
+                        if (shared->_source) {
+                            CFRunLoopSourceSignal(shared->_source);
+                            _CFRunLoopSourceWakeUpRunLoops(shared->_source);
+                        }
+                    };
+                dispatch_block_t cancel_block = ^{
+                        shared->_rdsrc = NULL;
+                        shared->_refCnt--;
+                        if (0 == shared->_refCnt) {
+                            if (shared->_closeFD) close(shared->_socket);
+                            free(shared);
+                        }
+                        dispatch_release(dsrc);
+                    };
+                dispatch_source_set_event_handler(dsrc, event_block);
+                dispatch_source_set_cancel_handler(dsrc, cancel_block);
+                shared->_rdsrc = dsrc;
+            }
+            if (memory->_wantWrite || memory->_wantConnect) {
+                dispatch_source_t dsrc = NULL;
+                if (sane) {
+                    dsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, ufd, 0, __sockQueue());
+                } else {
+                    dsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, __sockQueue());
+                    dispatch_source_set_timer(dsrc, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC / 2, NSEC_PER_SEC);
+                }
+                dispatch_block_t event_block = ^{
+                        memory->_writeable = true;
+                        if (!memory->_wsuspended) {
+                            dispatch_suspend(dsrc);
+                            memory->_wsuspended = true;
+                        }
+                        if (shared->_source) {
+                            CFRunLoopSourceSignal(shared->_source);
+                            _CFRunLoopSourceWakeUpRunLoops(shared->_source);
+                        }
+                    };
+                dispatch_block_t cancel_block = ^{
+                        shared->_wrsrc = NULL;
+                        shared->_refCnt--;
+                        if (0 == shared->_refCnt) {
+                            if (shared->_closeFD) close(shared->_socket);
+                            free(shared);
+                        }
+                        dispatch_release(dsrc);
+                    };
+                dispatch_source_set_event_handler(dsrc, event_block);
+                dispatch_source_set_cancel_handler(dsrc, cancel_block);
+                shared->_wrsrc = dsrc;
+            }
+
+            if (shared->_rdsrc) {
+                shared->_refCnt++;
+            }
+            if (shared->_wrsrc) {
+                shared->_refCnt++;
+            }
+
+            memory->_state = kCFSocketStateReady;
+            CFArrayAppendValue(__CFAllSockets, memory);
+            sock = memory;
+        });
+// CFLog(5, CFSTR("CFSocketCreateWithNative(): created socket %p with callbacks 0x%x"), sock, callBackTypes);
+    return sock;
+}
+
+CFSocketNativeHandle CFSocketGetNative(CFSocketRef sock) {
+    CHECK_FOR_FORK_RET(INVALID_SOCKET);
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    return sock->_shared ? sock->_shared->_socket : INVALID_SOCKET;
+}
+
+void CFSocketGetContext(CFSocketRef sock, CFSocketContext *context) {
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
+    objc_memmove_collectable(context, &sock->_context, sizeof(CFSocketContext));
+}
+
+CFDataRef CFSocketCopyAddress(CFSocketRef sock) {
+    CHECK_FOR_FORK_RET(NULL);
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    __block CFDataRef result = NULL;
+    dispatch_sync(__sockQueue(), ^{
+            if (!sock->_address) {
+                if (!__CFSocketIsValid(sock)) return;
+                uint8_t name[MAX_SOCKADDR_LEN];
+                int namelen = sizeof(name);
+                int ret = getsockname(sock->_shared->_socket, (struct sockaddr *)name, (socklen_t *)&namelen);
+                if (0 == ret && 0 < namelen) {
+                    sock->_address = CFDataCreate(CFGetAllocator(sock), name, namelen);
+                }
+            }
+            result = sock->_address ? (CFDataRef)CFRetain(sock->_address) : NULL;
+        });
+// CFLog(5, CFSTR("CFSocketCopyAddress(): created socket %p address %@"), sock, result);
+    return result;
+}
+
+CFDataRef CFSocketCopyPeerAddress(CFSocketRef sock) {
+    CHECK_FOR_FORK_RET(NULL);
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    __block CFDataRef result = NULL;
+    dispatch_sync(__sockQueue(), ^{
+            if (!sock->_peerAddress) {
+                if (!__CFSocketIsValid(sock)) return;
+                uint8_t name[MAX_SOCKADDR_LEN];
+                int namelen = sizeof(name);
+                int ret = getpeername(sock->_shared->_socket, (struct sockaddr *)name, (socklen_t *)&namelen);
+                if (0 == ret && 0 < namelen) {
+                    sock->_peerAddress = CFDataCreate(CFGetAllocator(sock), name, namelen);
+                }
+            }
+            result = sock->_peerAddress ? (CFDataRef)CFRetain(sock->_peerAddress) : NULL;
+        });
+// CFLog(5, CFSTR("CFSocketCopyPeerAddress(): created socket %p peer address %@"), sock, result);
+    return result;
+}
+
+CFOptionFlags CFSocketGetSocketFlags(CFSocketRef sock) {
+    CHECK_FOR_FORK();
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    __block CFOptionFlags flags = 0;
+    dispatch_sync(__sockQueue(), ^{
+            if (sock->_reenableRead) flags |= sock->_wantReadType; // flags are same as types here
+            if (sock->_reeanbleWrite) flags |= kCFSocketAutomaticallyReenableWriteCallBack;
+            if (sock->_leaveErrors) flags |= kCFSocketLeaveErrors;
+            if (sock->_closeOnInvalidate) flags |= kCFSocketCloseOnInvalidate;
+        });
+// CFLog(5, CFSTR("CFSocketGetSocketFlags(%p): -> 0x%x"), sock, flags);
+    return flags;
+}
+
+void CFSocketSetSocketFlags(CFSocketRef sock, CFOptionFlags flags) {
+    CHECK_FOR_FORK();
+// CFLog(5, CFSTR("CFSocketSetSocketFlags(%p, 0x%x) starting"), sock, flags);
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    dispatch_sync(__sockQueue(), ^{
+            sock->_reenableRead = (sock->_wantReadType && ((flags & 0x3) == sock->_wantReadType)) ? true : false;
+            sock->_reeanbleWrite = (sock->_wantWrite && (flags & kCFSocketAutomaticallyReenableWriteCallBack)) ? true : false;
+            sock->_leaveErrors = (flags & kCFSocketLeaveErrors) ? true : false;
+            sock->_closeOnInvalidate = (flags & kCFSocketCloseOnInvalidate) ? true : false;
+            if (sock->_shared) sock->_shared->_closeFD = sock->_closeOnInvalidate;
+        });
+// CFLog(5, CFSTR("CFSocketSetSocketFlags(%p, 0x%x) done"), sock, flags);
+}
+
+void CFSocketEnableCallBacks(CFSocketRef sock, CFOptionFlags callBackTypes) {
+    CHECK_FOR_FORK_RET();
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+// CFLog(5, CFSTR("CFSocketEnableCallBacks(%p, 0x%x) starting"), sock, callBackTypes);
+    dispatch_sync(__sockQueue(), ^{
+            if (!__CFSocketIsValid(sock)) return;
+            if (sock->_wantReadType && (callBackTypes & 0x3) == sock->_wantReadType) {
+                if (sock->_rsuspended && sock->_shared->_rdsrc) {
+                    sock->_rsuspended = false;
+                    dispatch_resume(sock->_shared->_rdsrc);
+                }
+                sock->_readDisabled = false;
+            }
+            if (sock->_wantWrite && (callBackTypes & kCFSocketWriteCallBack)) {
+                if (sock->_wsuspended && sock->_shared->_wrsrc) {
+                    sock->_wsuspended = false;
+                    dispatch_resume(sock->_shared->_wrsrc);
+                }
+                sock->_writeDisabled = false;
+            }
+            if (sock->_wantConnect && !sock->_connected && (callBackTypes & kCFSocketConnectCallBack)) {
+                if (sock->_wsuspended && sock->_shared->_wrsrc) {
+                    sock->_wsuspended = false;
+                    dispatch_resume(sock->_shared->_wrsrc);
+                }
+                sock->_connectDisabled = false;
+            }
+        });
+// CFLog(5, CFSTR("CFSocketEnableCallBacks(%p, 0x%x) done"), sock, callBackTypes);
+}
+
+void CFSocketDisableCallBacks(CFSocketRef sock, CFOptionFlags callBackTypes) {
+    CHECK_FOR_FORK_RET();
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+// CFLog(5, CFSTR("CFSocketDisableCallBacks(%p, 0x%x) starting"), sock, callBackTypes);
+    dispatch_sync(__sockQueue(), ^{
+            if (!__CFSocketIsValid(sock)) return;
+            if (sock->_wantReadType && (callBackTypes & 0x3) == sock->_wantReadType) {
+                if (!sock->_rsuspended && sock->_shared->_rdsrc) {
+                    dispatch_suspend(sock->_shared->_rdsrc);
+                    sock->_rsuspended = true;
+                }
+                sock->_readDisabled = true;
+            }
+            if (sock->_wantWrite && (callBackTypes & kCFSocketWriteCallBack)) {
+                if (!sock->_wsuspended && sock->_shared->_wrsrc) {
+                    dispatch_suspend(sock->_shared->_wrsrc);
+                    sock->_wsuspended = true;
+                }
+                sock->_writeDisabled = true;
+            }
+            if (sock->_wantConnect && !sock->_connected && (callBackTypes & kCFSocketConnectCallBack)) {
+                if (!sock->_wsuspended && sock->_shared->_wrsrc) {
+                    dispatch_suspend(sock->_shared->_wrsrc);
+                    sock->_wsuspended = true;
+                }
+                sock->_connectDisabled = true;
+            }
+        });
+// CFLog(5, CFSTR("CFSocketDisableCallBacks(%p, 0x%x) done"), sock, callBackTypes);
+}
+
+void CFSocketInvalidate(CFSocketRef sock) {
+    CHECK_FOR_FORK_RET();
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    CFRetain(sock);
+// CFLog(5, CFSTR("CFSocketInvalidate(%p) starting"), sock);
+    __block CFRunLoopSourceRef source = NULL;
+    __block Boolean wasReady = false;
+    dispatch_sync(__sockQueue(), ^{
+            wasReady = (sock->_state == kCFSocketStateReady);
+            if (wasReady) {
+                sock->_state = kCFSocketStateInvalidating;
+                OSMemoryBarrier();
+                for (CFIndex idx = 0, cnt = CFArrayGetCount(__CFAllSockets); idx < cnt; idx++) {
+                    CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFAllSockets, idx);
+                    if (s == sock) {
+                        CFArrayRemoveValueAtIndex(__CFAllSockets, idx);
+                        break;
+                    }
+                }
+                if (sock->_shared->_rdsrc) {
+                    dispatch_source_cancel(sock->_shared->_rdsrc);
+                    if (sock->_rsuspended) {
+                        sock->_rsuspended = false;
+                        dispatch_resume(sock->_shared->_rdsrc);
+                    }
+                }
+                if (sock->_shared->_wrsrc) {
+                    dispatch_source_cancel(sock->_shared->_wrsrc);
+                    if (sock->_wsuspended) {
+                        sock->_wsuspended = false;
+                        dispatch_resume(sock->_shared->_wrsrc);
+                    }
+                }
+                source = sock->_shared->_source;
+                sock->_shared->_source = NULL;
+                sock->_shared->_refCnt--;
+                if (0 == sock->_shared->_refCnt) {
+                    if (sock->_shared->_closeFD) close(sock->_shared->_socket);
+                    free(sock->_shared);
+                }
+                sock->_shared = NULL;
+            }
+        });
+    if (wasReady) {
+        if (NULL != source) {
+            CFRunLoopSourceInvalidate(source);
+            CFRelease(source);
+        }
+        void *info = sock->_context.info;
+        sock->_context.info = NULL;
+        if (sock->_context.release) {
+            sock->_context.release(info);
+        }
+        sock->_state = kCFSocketStateInvalid;
+        OSMemoryBarrier();
+    }
+// CFLog(5, CFSTR("CFSocketInvalidate(%p) done%s"), sock, wasReady ? " -- done on this thread" : "");
+    CFRelease(sock);
+}
+
+Boolean CFSocketIsValid(CFSocketRef sock) {
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    return __CFSocketIsValid(sock);
+}
+
+
+static void __CFSocketPerform(void *info) { // CFRunLoop should only call this on one thread at a time
+    CHECK_FOR_FORK_RET();
+    CFSocketRef sock = (CFSocketRef)info;
+
+// CFLog(5, CFSTR("__CFSocketPerform(%p) starting '%@'"), sock, sock);
+    __block Boolean doRead = false, doWrite = false, doConnect = false, isValid = false;
+    __block int fd = INVALID_SOCKET;
+    __block SInt32 errorCode = 0;
+    dispatch_sync(__sockQueue(), ^{
+            isValid = __CFSocketIsValid(sock);
+            if (!isValid) return;
+            doRead = sock->_readable && sock->_wantReadType && !sock->_readDisabled;
+            doWrite = sock->_writeable && sock->_wantWrite && !sock->_writeDisabled;
+            doConnect = sock->_writeable && sock->_wantConnect && !sock->_connectDisabled && !sock->_connected;
+            if (doRead) sock->_readable = false;
+            if (doWrite || doConnect) sock->_writeable = false;
+            if (isValid) {
+                fd = sock->_shared->_socket;
+            }
+            if (isValid && !sock->_leaveErrors && (doWrite || doConnect)) { // not on read, for whatever reason
+                int errorSize = sizeof(errorCode);
+                int ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&errorCode, (socklen_t *)&errorSize);
+                if (0 != ret) errorCode = 0;
+                sock->_error = errorCode;
+            }
+            sock->_connected = true;
+        });
+// CFLog(5, CFSTR("__CFSocketPerform(%p) isValid:%d, doRead:%d, doWrite:%d, doConnect:%d error:%d"), sock, isValid, doRead, doWrite, doConnect, errorCode);
+    if (!isValid) return;
+
+    void *context_info = NULL;
+    void (*context_release)(const void *) = NULL;
+    if (sock->_context.retain) {
+        context_info = (void *)sock->_context.retain(sock->_context.info);
+        context_release = sock->_context.release;
+    } else {
+        context_info = sock->_context.info;
+    }
+
+    Boolean calledOut = false;
+    if (doConnect) {
+// CFLog(5, CFSTR("__CFSocketPerform(%p) doing connect callback"), sock);
+        if (sock->_callout) sock->_callout(sock, kCFSocketConnectCallBack, NULL, (0 != errorCode) ? &errorCode : NULL, context_info);
+// CFLog(5, CFSTR("__CFSocketPerform(%p) doing connect callback done"), sock);
+        calledOut = true;
+    }
+    if (doRead && (!calledOut || __CFSocketIsValid(sock))) {
+        switch (sock->_wantReadType) {
+        case kCFSocketReadCallBack:
+// CFLog(5, CFSTR("__CFSocketPerform(%p) doing read callback"), sock);
+            if (sock->_callout) sock->_callout(sock, kCFSocketReadCallBack, NULL, NULL, context_info);
+// CFLog(5, CFSTR("__CFSocketPerform(%p) doing read callback done"), sock);
+            calledOut = true;
+            break;
+        case kCFSocketAcceptCallBack: {
+            uint8_t name[MAX_SOCKADDR_LEN];
+            int namelen = sizeof(name);
+            int new_fd = accept(fd, (struct sockaddr *)name, (socklen_t *)&namelen);
+            if (INVALID_SOCKET != new_fd) {
+                CFDataRef address = CFDataCreate(CFGetAllocator(sock), name, namelen);
+                if (sock->_callout) sock->_callout(sock, kCFSocketAcceptCallBack, address, &new_fd, context_info);
+                calledOut = true;
+                CFRelease(address);
+            }
+            break;
+        }
+        case kCFSocketDataCallBack: {
+            uint8_t name[MAX_SOCKADDR_LEN];
+            int namelen = sizeof(name);
+            int avail = 0;
+            int ret = ioctl(fd, FIONREAD, &avail);
+            if (ret < 0 || avail < 256) avail = 256;
+            if ((1 << 20) < avail) avail = (1 << 20);
+            CFMutableDataRef data = CFDataCreateMutable(CFGetAllocator(sock), 0);
+            CFDataSetLength(data, avail);
+            ssize_t len = recvfrom(fd, CFDataGetMutableBytePtr(data), avail, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
+            CFIndex datalen = (len < 0) ? 0 : len;
+            CFDataSetLength(data, datalen);
+            CFDataRef address = NULL;
+            if (0 < namelen) {
+                address = CFDataCreate(CFGetAllocator(sock), name, namelen);
+            } else if (sock->_connOriented) {
+                address = CFSocketCopyPeerAddress(sock);
+            }
+            if (NULL == address) {
+                address = CFDataCreate(CFGetAllocator(sock), NULL, 0);
+            }
+            if (sock->_callout) sock->_callout(sock, kCFSocketDataCallBack, address, data, context_info);
+            calledOut = true;
+            if (0 == datalen) CFSocketInvalidate(sock);
+            if (address) CFRelease(address);
+            CFRelease(data);
+            break;
+        }
+        }
+    }
+    if (doWrite && (!calledOut || __CFSocketIsValid(sock))) {
+        if (0 == errorCode) {
+// CFLog(5, CFSTR("__CFSocketPerform(%p) doing write callback"), sock);
+            if (sock->_callout) sock->_callout(sock, kCFSocketWriteCallBack, NULL, NULL, context_info);
+// CFLog(5, CFSTR("__CFSocketPerform(%p) doing write callback done"), sock);
+            calledOut = true;
+        }
+    }
+// CFLog(5, CFSTR("__CFSocketPerform(%p) callouts done"), sock);
+
+    dispatch_sync(__sockQueue(), ^{
+            if (!__CFSocketIsValid(sock)) return;
+            if (doRead && sock->_reenableRead) {
+// CFLog(5, CFSTR("__CFSocketPerform(%p) reenabling read"), sock);
+                if (sock->_rsuspended && sock->_shared->_rdsrc) {
+                    sock->_rsuspended = false;
+                    dispatch_resume(sock->_shared->_rdsrc);
+                }
+            }
+            if (doWrite && sock->_reeanbleWrite) {
+// CFLog(5, CFSTR("__CFSocketPerform(%p) reenabling write"), sock);
+                if (sock->_wsuspended && sock->_shared->_wrsrc) {
+                    sock->_wsuspended = false;
+                    dispatch_resume(sock->_shared->_wrsrc);
+                }
+            }
+        });
+
+    if (context_release) {
+        context_release(context_info);
+    }
+    CHECK_FOR_FORK_RET();
+// CFLog(5, CFSTR("__CFSocketPerform(%p) done"), sock);
+}
+
+static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
+    CFSocketRef sock = (CFSocketRef)info;
+    int32_t newVal = OSAtomicIncrement32Barrier(&sock->_runLoopCounter);
+    if (1 == newVal) { // on a transition from 0->1, the old code forced all desired callbacks enabled
+        CFOptionFlags types = sock->_wantReadType | (sock->_wantWrite ? kCFSocketWriteCallBack : 0) | (sock->_wantConnect ? kCFSocketConnectCallBack : 0);
+        CFSocketEnableCallBacks(sock, types);
+    }
+    CFRunLoopWakeUp(rl);
+}
+
+static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
+    CFSocketRef sock = (CFSocketRef)info;
+    OSAtomicDecrement32Barrier(&sock->_runLoopCounter);
+    CFRunLoopWakeUp(rl);
+}
+
+CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef sock, CFIndex order) {
+    CHECK_FOR_FORK_RET(NULL);
+    __CFGenericValidateType(sock, CFSocketGetTypeID());
+    __block CFRunLoopSourceRef result = NULL;
+    dispatch_sync(__sockQueue(), ^{
+            if (!__CFSocketIsValid(sock)) return;
+            if (NULL == sock->_shared->_source) {
+                CFRunLoopSourceContext context;
+                context.version = 0;
+                context.info = (void *)sock;
+                context.retain = (const void *(*)(const void *))CFRetain;
+                context.release = (void (*)(const void *))CFRelease;
+                context.copyDescription = (CFStringRef (*)(const void *))__CFSocketCopyDescription;
+                context.equal = NULL;
+                context.hash = NULL;
+                context.schedule = __CFSocketSchedule;
+                context.cancel = __CFSocketCancel;
+                context.perform = __CFSocketPerform;
+                sock->_shared->_source = CFRunLoopSourceCreate(allocator, order, (CFRunLoopSourceContext *)&context);
+                if (sock->_shared->_source) {
+                    if (sock->_wantReadType) {
+                        if (sock->_rsuspended && sock->_shared->_rdsrc) {
+                            sock->_rsuspended = false;
+                            dispatch_resume(sock->_shared->_rdsrc);
+                        }
+                    }
+                    if (sock->_wantWrite || (sock->_wantConnect && !sock->_connected)) {
+                        if (sock->_wsuspended && sock->_shared->_wrsrc) {
+                            sock->_wsuspended = false;
+                            dispatch_resume(sock->_shared->_wrsrc);
+                        }
+                    }
+                }
+            }
+            result = sock->_shared->_source ? (CFRunLoopSourceRef)CFRetain(sock->_shared->_source) : NULL;
+        });
+// CFLog(5, CFSTR("CFSocketCreateRunLoopSource(%p) => %p"), sock, result);
+    return result;
+}
+
+
+void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, CFIndex length) {
+}
+
+CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error) {
+    *error = 0;
+    int ret = read(CFSocketGetNative(s), buffer, length);
+    if (ret < 0) {
+        *error = errno;
+    }
+    return ret;
+}
+
+Boolean __CFSocketGetBytesAvailable(CFSocketRef s, CFIndex* ctBytesAvailable) {
+    int bytesAvailable;
+    int ret = ioctl(CFSocketGetNative(s), FIONREAD, &bytesAvailable);
+    if (ret < 0) return false;
+    *ctBytesAvailable = (CFIndex)bytesAvailable;
+    return true;
+}
+
+
+#else /* not NEW_SOCKET */
+
 
 #include <CoreFoundation/CFSocket.h>
 #include <sys/types.h>
 #include <math.h>
 #include <limits.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
 #include <CoreFoundation/CFArray.h>
 #include <CoreFoundation/CFData.h>
 #include <CoreFoundation/CFDictionary.h>
 #include "CFInternal.h"
 #include <libc.h>
 #include <dlfcn.h>
-#include "auto_stubs.h"
 
 // On Mach we use a v0 RunLoopSource to make client callbacks.  That source is signalled by a
 // separate SocketManager thread who uses select() to watch the sockets' fds.
 
 #define INVALID_SOCKET (CFSocketNativeHandle)(-1)
 
-enum {
-    kCFSocketLeaveErrors = 64   // candidate for publicization in future
-};
-
-static uint16_t __CFSocketDefaultNameRegistryPortNumber = 2454;
-
-CONST_STRING_DECL(kCFSocketCommandKey, "Command")
-CONST_STRING_DECL(kCFSocketNameKey, "Name")
-CONST_STRING_DECL(kCFSocketValueKey, "Value")
-CONST_STRING_DECL(kCFSocketResultKey, "Result")
-CONST_STRING_DECL(kCFSocketErrorKey, "Error")
-CONST_STRING_DECL(kCFSocketRegisterCommand, "Register")
-CONST_STRING_DECL(kCFSocketRetrieveCommand, "Retrieve")
-CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode, "CFSocketRegistryRequest")
-
 #define closesocket(a) close((a))
 #define ioctlsocket(a,b,c) ioctl((a),(b),(c))
 
@@ -98,13 +864,6 @@ CF_INLINE Boolean __CFSocketFdSet(CFSocketNativeHandle sock, CFMutableDataRef fd
 }
 
 
-#define NEW_SOCKET 0
-#if NEW_SOCKET
-
-__private_extern__ void __CFSocketInitialize(void) {}
-
-#else
-
 #define MAX_SOCKADDR_LEN 256
 #define MAX_DATA_SIZE 65535
 #define MAX_CONNECTION_ORIENTED_DATA_SIZE 32768
@@ -128,7 +887,6 @@ static Boolean __CFReadSocketsTimeoutInvalid = true;  /* rebuild the timeout val
 static CFSocketNativeHandle __CFWakeupSocketPair[2] = {INVALID_SOCKET, INVALID_SOCKET};
 static void *__CFSocketManagerThread = NULL;
 
-static CFTypeID __kCFSocketTypeID = _kCFRuntimeNotATypeID;
 static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock);
 
 struct __CFSocket {
@@ -294,10 +1052,12 @@ CF_INLINE Boolean __CFSocketClearFDForRead(CFSocketRef s) {
 }
 
 CF_INLINE Boolean __CFSocketSetFDForWrite(CFSocketRef s) {
+// CFLog(5, CFSTR("__CFSocketSetFDForWrite(%p)"), s);
     return __CFSocketFdSet(s->_socket, __CFWriteSocketsFds);
 }
 
 CF_INLINE Boolean __CFSocketClearFDForWrite(CFSocketRef s) {
+// CFLog(5, CFSTR("__CFSocketClearFDForWrite(%p)"), s);
     return __CFSocketFdClr(s->_socket, __CFWriteSocketsFds);
 }
 
@@ -386,6 +1146,7 @@ static void __CFSocketHandleWrite(CFSocketRef s, Boolean callBackNow) {
     }
     s->_errorCode = errorCode;
     __CFSocketSetWriteSignalled(s);
+// CFLog(5, CFSTR("__CFSocketHandleWrite() signalling write on socket %p"), s);
 #if defined(LOG_CFSOCKET)
     fprintf(stdout, "write signaling source for socket %d\n", s->_socket);
 #endif
@@ -609,10 +1370,10 @@ static struct timeval* intervalToTimeval(CFTimeInterval timeout, struct timeval*
  the dictionary apply, since we've got the active sockets lock held */
 static void _calcMinTimeout_locked(const void* val, void* ctxt)
 {
-       CFSocketRef s = (CFSocketRef) val;
-       struct timeval** minTime = (struct timeval**) ctxt;
-       if (timerisset(&s->_readBufferTimeout) && (*minTime == NULL || timercmp(&s->_readBufferTimeout, *minTime, <)))
-               *minTime = &s->_readBufferTimeout;
+    CFSocketRef s = (CFSocketRef) val;
+    struct timeval** minTime = (struct timeval**) ctxt;
+    if (timerisset(&s->_readBufferTimeout) && (*minTime == NULL || timercmp(&s->_readBufferTimeout, *minTime, <)))
+        *minTime = &s->_readBufferTimeout;
     else if (s->_leftoverBytes) {
         /* If there's anyone with leftover bytes, they'll need to be awoken immediately */
         static struct timeval sKickerTime = { 0, 0 };
@@ -623,72 +1384,72 @@ static void _calcMinTimeout_locked(const void* val, void* ctxt)
 void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, CFIndex length)
 {
     struct timeval timeoutVal;
-
+    
     intervalToTimeval(timeout, &timeoutVal);
-
-       /* lock ordering is socket lock, activesocketslock */
-       /* activesocketslock protects our timeout calculation */
+    
+    /* lock ordering is socket lock, activesocketslock */
+    /* activesocketslock protects our timeout calculation */
     __CFSocketLock(s);
-       __CFSpinLock(&__CFActiveSocketsLock);
-
+    __CFSpinLock(&__CFActiveSocketsLock);
+    
 #if defined(LOG_CFSOCKET)
     s->didLogSomething = false;
 #endif
     
-       if (s->_bytesToBuffer != length) {
+    if (s->_bytesToBuffer != length) {
         CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
         
         if (ctBuffer) {
-                       /* As originally envisaged, you were supposed to be sure to drain the buffer before 
-                        * issuing another request on the socket.  In practice, there seem to be times when we want to re-use 
-                        * the stream (or perhaps, are on our way to closing it out) and this policy doesn't work so well.  
-                        * So, if someone changes the buffer size while we have bytes already buffered, we put them 
-                        * aside and use them to satisfy any subsequent reads. 
-                        */
+            /* As originally envisaged, you were supposed to be sure to drain the buffer before 
+             * issuing another request on the socket.  In practice, there seem to be times when we want to re-use 
+             * the stream (or perhaps, are on our way to closing it out) and this policy doesn't work so well.  
+             * So, if someone changes the buffer size while we have bytes already buffered, we put them 
+             * aside and use them to satisfy any subsequent reads. 
+             */
 #if defined(LOG_CFSOCKET)
             __socketLog("%s(%d): WARNING: shouldn't set read buffer length while data (%d bytes) is still in the read buffer (leftover total %d)", __FUNCTION__, __LINE__, ctBuffer, s->_leftoverBytes? CFDataGetLength(s->_leftoverBytes) : 0);
 #endif
             
-                       if (s->_leftoverBytes == NULL)
-                               s->_leftoverBytes = CFDataCreateMutable(CFGetAllocator(s), 0);
-                               
-                       /* append the current buffered bytes over.  We'll keep draining _leftoverBytes while we have them... */
+            if (s->_leftoverBytes == NULL)
+                s->_leftoverBytes = CFDataCreateMutable(CFGetAllocator(s), 0);
+            
+            /* append the current buffered bytes over.  We'll keep draining _leftoverBytes while we have them... */
             CFDataAppendBytes(s->_leftoverBytes, CFDataGetBytePtr(s->_readBuffer) + s->_bytesToBufferReadPos, ctBuffer);
-                       CFRelease(s->_readBuffer);
-                       s->_readBuffer = NULL;
-                               
-                       s->_bytesToBuffer = 0;
-                       s->_bytesToBufferPos = 0;
-                       s->_bytesToBufferReadPos = 0;
-               }
-               if (length == 0) {
-                       s->_bytesToBuffer = 0;
-                       s->_bytesToBufferPos = 0;
-                       s->_bytesToBufferReadPos = 0;
-                       if (s->_readBuffer) {
-                               CFRelease(s->_readBuffer);
-                               s->_readBuffer = NULL;
-                       }
-                       // Zero length buffer, smash the timeout
-                       timeoutVal = (struct timeval) { 0, 0 };
-               } else {
-                       /* if the buffer shrank, we can re-use the old one */
-                       if (length > s->_bytesToBuffer) {
-                               if (s->_readBuffer) {
-                                       CFRelease(s->_readBuffer);
-                                       s->_readBuffer = NULL;
-                               }
-                       }
-                       
-                       s->_bytesToBuffer = length;
-                       s->_bytesToBufferPos = 0;
-                       s->_bytesToBufferReadPos = 0;
-                       if (s->_readBuffer == NULL) {
+            CFRelease(s->_readBuffer);
+            s->_readBuffer = NULL;
+            
+            s->_bytesToBuffer = 0;
+            s->_bytesToBufferPos = 0;
+            s->_bytesToBufferReadPos = 0;
+        }
+        if (length == 0) {
+            s->_bytesToBuffer = 0;
+            s->_bytesToBufferPos = 0;
+            s->_bytesToBufferReadPos = 0;
+            if (s->_readBuffer) {
+                CFRelease(s->_readBuffer);
+                s->_readBuffer = NULL;
+            }
+            // Zero length buffer, smash the timeout
+            timeoutVal = (struct timeval) { 0, 0 };
+        } else {
+            /* if the buffer shrank, we can re-use the old one */
+            if (length > s->_bytesToBuffer) {
+                if (s->_readBuffer) {
+                    CFRelease(s->_readBuffer);
+                    s->_readBuffer = NULL;
+                }
+            }
+            
+            s->_bytesToBuffer = length;
+            s->_bytesToBufferPos = 0;
+            s->_bytesToBufferReadPos = 0;
+            if (s->_readBuffer == NULL) {
                 s->_readBuffer = CFDataCreateMutable(kCFAllocatorSystemDefault, length);
-                               CFDataSetLength(s->_readBuffer, length);
-                       }
-               }
-       }
+                CFDataSetLength(s->_readBuffer, length);
+            }
+        }
+    }
     
     if (timercmp(&s->_readBufferTimeout, &timeoutVal, !=)) {
         s->_readBufferTimeout = timeoutVal;
@@ -696,35 +1457,9 @@ void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, C
     }
     
     __CFSpinUnlock(&__CFActiveSocketsLock);
-       __CFSocketUnlock(s);
-}
-
-void __CFSocketSetReadBufferTimeout(CFSocketRef s, CFTimeInterval timeout)
-{
-#if defined(LOG_CFSOCKET)
-    __socketLog("### (%s DEPRECATED) SET READ BUFFER TIMEOUT for %p (bufferSize %d, timeout %d.%d)\n", __FUNCTION__, s, s->_bytesToBuffer, s->_readBufferTimeout.tv_sec, s->_readBufferTimeout.tv_usec);
-#endif
-    
-    __CFSocketSetSocketReadBufferAttrs(s, timeout, s->_bytesToBuffer);
-}
-
-void __CFSocketSetReadBufferLength(CFSocketRef s, CFIndex length)
-{
-#if defined(LOG_CFSOCKET)
-    __socketLog("### (%s DEPRECATED) SET READ BUFFER LENGTH for %p (bufferSize %d, timeout %d.%d)\n", __FUNCTION__, s, s->_bytesToBuffer, s->_readBufferTimeout.tv_sec, s->_readBufferTimeout.tv_usec);
-#endif
-    
-    CFTimeInterval timeout;
-    
-    if (! timerisset(&s->_readBufferTimeout))
-        timeout = 0;
-    else
-        timeout = 0.1;
-    
-    __CFSocketSetSocketReadBufferAttrs(s, timeout, length);
+    __CFSocketUnlock(s);
 }
 
-
 CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error)
 {
 #if defined(LOG_CFSOCKET)
@@ -741,7 +1476,7 @@ CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error)
        if (s->_leftoverBytes) {
                CFIndex ctBuffer = CFDataGetLength(s->_leftoverBytes);
 #if defined(DEBUG)
-               fprintf(stderr, "%s(%ld): WARNING: Draining %d leftover bytes first\n\n", __FUNCTION__, __LINE__, (long)ctBuffer);
+               fprintf(stderr, "%s(%ld): WARNING: Draining %ld leftover bytes first\n\n", __FUNCTION__, (long)__LINE__, (long)ctBuffer);
 #endif
                if (ctBuffer > length)
                        ctBuffer = length;
@@ -868,7 +1603,7 @@ __attribute__ ((noreturn)) // mostly interesting for shutting up a warning
 #endif /* __GNUC__ */
 static void __CFSocketManager(void * arg)
 {
-    if (objc_collecting_enabled()) auto_zone_register_thread(auto_zone());
+    if (objc_collectingEnabled()) auto_zone_register_thread(auto_zone());
     SInt32 nrfds, maxnrfds, fdentries = 1;
     SInt32 rfds, wfds;
     fd_set *exceptfds = NULL;
@@ -881,10 +1616,10 @@ static void __CFSocketManager(void * arg)
     CFMutableArrayRef selectedReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
     CFIndex selectedWriteSocketsIndex = 0, selectedReadSocketsIndex = 0;
     
-       struct timeval tv;
-       struct timeval* pTimeout = NULL;
-       struct timeval timeBeforeSelect;
-       
+    struct timeval tv;
+    struct timeval* pTimeout = NULL;
+    struct timeval timeBeforeSelect;
+    
     for (;;) {       
         __CFSpinLock(&__CFActiveSocketsLock);
         __CFSocketManagerIteration++;
@@ -1053,6 +1788,7 @@ static void __CFSocketManager(void * arg)
                     /* socket is removed from fds here, restored by CFSocketReschedule */
                     if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFWriteSocketsFds);
                     FD_CLR(sock, tempfds);
+// CFLog(5, CFSTR("Manager: cleared socket %p from write fds"), s);
                 }
             }
         }
@@ -1097,7 +1833,7 @@ static void __CFSocketManager(void * arg)
         }
         selectedReadSocketsIndex = 0;
     }
-    if (objc_collecting_enabled()) auto_zone_unregister_thread(auto_zone());
+    if (objc_collectingEnabled()) auto_zone_unregister_thread(auto_zone());
 }
 
 static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) {
@@ -1150,6 +1886,8 @@ static void __CFSocketDeallocate(CFTypeRef cf) {
        s->_bufferedReadError = 0;
 }
 
+static CFTypeID __kCFSocketTypeID = _kCFRuntimeNotATypeID;
+
 static const CFRuntimeClass __CFSocketClass = {
     0,
     "CFSocket",
@@ -1162,11 +1900,24 @@ static const CFRuntimeClass __CFSocketClass = {
     __CFSocketCopyDescription
 };
 
-__private_extern__ void __CFSocketInitialize(void) {
-    __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
-}
-
 CFTypeID CFSocketGetTypeID(void) {
+    if (_kCFRuntimeNotATypeID == __kCFSocketTypeID) {
+       __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
+        struct rlimit lim1;
+        int ret1 = getrlimit(RLIMIT_NOFILE, &lim1);
+        int mib[] = {CTL_KERN, KERN_MAXFILESPERPROC};
+        int maxfd = 0;
+        size_t len = sizeof(int);
+        int ret0 = sysctl(mib, 2, &maxfd, &len, NULL, 0);
+        if (0 == ret0 && 0 == ret1 && lim1.rlim_max < maxfd) maxfd = lim1.rlim_max;
+        if (0 == ret1 && lim1.rlim_cur < maxfd) {
+            struct rlimit lim2 = lim1;
+            lim2.rlim_cur += 2304;
+            if (maxfd < lim2.rlim_cur) lim2.rlim_cur = maxfd;
+            setrlimit(RLIMIT_NOFILE, &lim2);
+            // we try, but do not go to extraordinary measures
+        }
+    }
     return __kCFSocketTypeID;
 }
 
@@ -1195,7 +1946,7 @@ static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketN
                        __CFSpinLock(&__CFAllSocketsLock);
                }
     }
-    memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, __kCFSocketTypeID, sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL);
+    memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, CFSocketGetTypeID(), sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL);
     if (NULL == memory) {
         __CFSpinUnlock(&__CFAllSocketsLock);
         return NULL;
@@ -1231,14 +1982,14 @@ static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketN
     memory->_context.release = 0;
     memory->_context.copyDescription = 0;
     timerclear(&memory->_readBufferTimeout);
-       memory->_readBuffer = NULL;
-       memory->_bytesToBuffer = 0;
-       memory->_bytesToBufferPos = 0;
-       memory->_bytesToBufferReadPos = 0;
-       memory->_atEOF = false;
-       memory->_bufferedReadError = 0;
-       memory->_leftoverBytes = NULL;
-       
+    memory->_readBuffer = NULL;
+    memory->_bytesToBuffer = 0;
+    memory->_bytesToBufferPos = 0;
+    memory->_bytesToBufferReadPos = 0;
+    memory->_atEOF = false;
+    memory->_bufferedReadError = 0;
+    memory->_leftoverBytes = NULL;
+    
     if (INVALID_SOCKET != sock) CFDictionaryAddValue(__CFAllSockets, (void *)(uintptr_t)sock, memory);
     __CFSpinUnlock(&__CFAllSocketsLock);
     if (NULL != context) {
@@ -1250,6 +2001,7 @@ static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketN
         memory->_context.info = contextInfo;
         __CFSocketUnlock(memory);
     }
+// CFLog(5, CFSTR("CFSocketCreateWithNative(): created socket %p with callbacks 0x%x"), memory, callBackTypes);
     return memory;
 }
 
@@ -1258,9 +2010,10 @@ CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHan
 }
 
 void CFSocketInvalidate(CFSocketRef s) {
+// CFLog(5, CFSTR("CFSocketInvalidate(%p) starting"), s);
     CHECK_FOR_FORK();
     UInt32 previousSocketManagerIteration;
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
 #if defined(LOG_CFSOCKET)
     fprintf(stdout, "invalidating socket %d with flags 0x%x disabled 0x%x connected 0x%x\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected);
 #endif
@@ -1331,75 +2084,79 @@ void CFSocketInvalidate(CFSocketRef s) {
     }
     __CFSpinUnlock(&__CFAllSocketsLock);
     CFRelease(s);
+// CFLog(5, CFSTR("CFSocketInvalidate(%p) done"), s);
 }
 
 Boolean CFSocketIsValid(CFSocketRef s) {
     CHECK_FOR_FORK();
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     return __CFSocketIsValid(s);
 }
 
 CFSocketNativeHandle CFSocketGetNative(CFSocketRef s) {
     CHECK_FOR_FORK();
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     return s->_socket;
 }
 
 CFDataRef CFSocketCopyAddress(CFSocketRef s) {
     CHECK_FOR_FORK();
     CFDataRef result = NULL;
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     __CFSocketLock(s);
     __CFSocketEstablishAddress(s);
     if (NULL != s->_address) {
         result = CFRetain(s->_address);
     }
     __CFSocketUnlock(s);
+// CFLog(5, CFSTR("CFSocketCopyAddress(): created socket %p address %@"), s, result);
     return result;
 }
 
 CFDataRef CFSocketCopyPeerAddress(CFSocketRef s) {
     CHECK_FOR_FORK();
     CFDataRef result = NULL;
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     __CFSocketLock(s);
     __CFSocketEstablishPeerAddress(s);
     if (NULL != s->_peerAddress) {
         result = CFRetain(s->_peerAddress);
     }
     __CFSocketUnlock(s);
+// CFLog(5, CFSTR("CFSocketCopyAddress(): created socket %p peer address %@"), s, result);
     return result;
 }
 
 void CFSocketGetContext(CFSocketRef s, CFSocketContext *context) {
     CHECK_FOR_FORK();
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
     *context = s->_context;
 }
 
 CFOptionFlags CFSocketGetSocketFlags(CFSocketRef s) {
     CHECK_FOR_FORK();
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     return s->_f.client;
 }
 
 void CFSocketSetSocketFlags(CFSocketRef s, CFOptionFlags flags) {
     CHECK_FOR_FORK();
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     __CFSocketLock(s);
 #if defined(LOG_CFSOCKET)
         fprintf(stdout, "setting flags for socket %d, from 0x%x to 0x%lx\n", s->_socket, s->_f.client, flags);
 #endif
     s->_f.client = flags;
     __CFSocketUnlock(s);
+// CFLog(5, CFSTR("CFSocketSetSocketFlags(%p, 0x%x)"), s, flags);
 }
 
 void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
     CHECK_FOR_FORK();
     Boolean wakeup = false;
     uint8_t readCallBackType;
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     __CFSocketLock(s);
     if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
         callBackTypes &= __CFSocketCallBackTypes(s);
@@ -1475,6 +2232,7 @@ void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boole
                 if (force) {
                     SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
                     if (kCFNotFound == idx) CFArrayAppendValue(__CFWriteSockets, s);
+//                     if (kCFNotFound == idx) CFLog(5, CFSTR("__CFSocketEnableCallBacks: put %p in __CFWriteSockets list due to force and non-presence"), s);
                 }
                 if (__CFSocketSetFDForWrite(s)) wakeup = true;
             }
@@ -1495,9 +2253,10 @@ void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boole
 
 void CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
     CHECK_FOR_FORK();
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     __CFSocketLock(s);
     __CFSocketEnableCallBacks(s, callBackTypes, TRUE, 'r');
+// CFLog(5, CFSTR("CFSocketEnableCallBacks(%p, 0x%x) done"), s, callBackTypes);
 }
 
 static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
@@ -1514,6 +2273,7 @@ static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
 #if defined(LOG_CFSOCKET)
             fprintf(stdout, "scheduling socket %d\n", s->_socket);
 #endif
+// CFLog(5, CFSTR("__CFSocketSchedule(%p, %p, %p)"), s, rl, mode);
             __CFSocketEnableCallBacks(s, __CFSocketCallBackTypes(s), TRUE, 's');  // unlocks s
         } else
             __CFSocketUnlock(s);
@@ -1530,6 +2290,7 @@ static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
         __CFSpinLock(&__CFActiveSocketsLock);
         idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
         if (0 <= idx) {
+// CFLog(5, CFSTR("__CFSocketCancel: removing %p from __CFWriteSockets list"), s);
             CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
             __CFSocketClearFDForWrite(s);
         }
@@ -1575,6 +2336,7 @@ static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef addres
     __CFSocketUnlock(s);
     if ((callBackTypes & kCFSocketConnectCallBack) != 0) {
         if (connectSignalled && (!calledOut || CFSocketIsValid(s))) {
+// CFLog(5, CFSTR("__CFSocketPerformV0(%p) doing connect callback, error: %d"), s, errorCode);
             if (errorCode) {
 #if defined(LOG_CFSOCKET)
                 fprintf(stdout, "perform calling out error %ld to socket %d\n", errorCode, s->_socket);
@@ -1613,6 +2375,7 @@ static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef addres
 #if defined(LOG_CFSOCKET)
             fprintf(stdout, "perform calling out read to socket %d\n", s->_socket);
 #endif
+// CFLog(5, CFSTR("__CFSocketPerformV0(%p) doing read callback"), s);
             if (callout) callout(s, kCFSocketReadCallBack, NULL, NULL, contextInfo);
             calledOut = true;
         }
@@ -1622,6 +2385,7 @@ static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef addres
 #if defined(LOG_CFSOCKET)
             fprintf(stdout, "perform calling out write to socket %d\n", s->_socket);
 #endif
+// CFLog(5, CFSTR("__CFSocketPerformV0(%p) doing write callback"), s);
             if (callout) callout(s, kCFSocketWriteCallBack, NULL, NULL, contextInfo);
             calledOut = true;
         }
@@ -1635,6 +2399,7 @@ static void __CFSocketPerformV0(void *info) {
     CFSocketNativeHandle sock = INVALID_SOCKET;
     uint8_t readCallBackType, callBackTypes;
     CFRunLoopRef rl = NULL;
+// CFLog(5, CFSTR("__CFSocketPerformV0(%p) starting"), s);
 
     __CFSocketLock(s);
     if (!__CFSocketIsValid(s)) {
@@ -1688,12 +2453,13 @@ static void __CFSocketPerformV0(void *info) {
         CFRunLoopWakeUp(rl);
         CFRelease(rl);
     }
+// CFLog(5, CFSTR("__CFSocketPerformV0(%p) done"), s);
 }
 
 CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef s, CFIndex order) {
     CHECK_FOR_FORK();
     CFRunLoopSourceRef result = NULL;
-    __CFGenericValidateType(s, __kCFSocketTypeID);
+    __CFGenericValidateType(s, CFSocketGetTypeID());
     __CFSocketLock(s);
     if (__CFSocketIsValid(s)) {
         if (NULL == s->_source0) {
@@ -1719,6 +2485,19 @@ CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocke
 
 #endif /* NEW_SOCKET */
 
+
+
+static uint16_t __CFSocketDefaultNameRegistryPortNumber = 2454;
+
+CONST_STRING_DECL(kCFSocketCommandKey, "Command")
+CONST_STRING_DECL(kCFSocketNameKey, "Name")
+CONST_STRING_DECL(kCFSocketValueKey, "Value")
+CONST_STRING_DECL(kCFSocketResultKey, "Result")
+CONST_STRING_DECL(kCFSocketErrorKey, "Error")
+CONST_STRING_DECL(kCFSocketRegisterCommand, "Register")
+CONST_STRING_DECL(kCFSocketRetrieveCommand, "Retrieve")
+CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode, "CFSocketRegistryRequest")
+
 static CFSpinLock_t __CFSocketWriteLock_ = CFSpinLockInit;
 //#warning can only send on one socket at a time now
 
@@ -1730,6 +2509,36 @@ CF_INLINE void __CFSocketWriteUnlock(CFSocketRef s) {
     __CFSpinUnlock(& __CFSocketWriteLock_);
 }
 
+#if NEW_SOCKET
+
+CF_INLINE CFIndex __CFSocketFdGetSize(CFDataRef fdSet) {
+    return NBBY * CFDataGetLength(fdSet);
+}
+
+CF_INLINE Boolean __CFSocketFdSet(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
+    /* returns true if a change occurred, false otherwise */
+    Boolean retval = false;
+    if (INVALID_SOCKET != sock && 0 <= sock) {
+        CFIndex numFds = NBBY * CFDataGetLength(fdSet);
+        fd_mask *fds_bits;
+        if (sock >= numFds) {
+            CFIndex oldSize = numFds / NFDBITS, newSize = (sock + NFDBITS) / NFDBITS, changeInBytes = (newSize - oldSize) * sizeof(fd_mask);
+            CFDataIncreaseLength(fdSet, changeInBytes);
+            fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
+            memset(fds_bits + oldSize, 0, changeInBytes);
+        } else {
+            fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
+        }
+        if (!FD_ISSET(sock, (fd_set *)fds_bits)) {
+            retval = true;
+            FD_SET(sock, (fd_set *)fds_bits);
+        }
+    }
+    return retval;
+}
+
+#endif
+
 //??? need timeout, error handling, retries
 CFSocketError CFSocketSendData(CFSocketRef s, CFDataRef address, CFDataRef data, CFTimeInterval timeout) {
     CHECK_FOR_FORK();
@@ -1748,8 +2557,8 @@ CFSocketError CFSocketSendData(CFSocketRef s, CFDataRef address, CFDataRef data,
     if (INVALID_SOCKET != sock) {
         CFRetain(s);
         __CFSocketWriteLock(s);
-        tv.tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
-        tv.tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
+        tv.tv_sec = (timeout <= 0.0 || (CFTimeInterval)INT_MAX <= timeout) ? INT_MAX : (int)floor(timeout);
+        tv.tv_usec = (int)floor(1.0e+6 * (timeout - floor(timeout)));
         setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(tv));    // cast for WinSock bad API
         if (NULL != addrptr && 0 < addrlen) {
             size = sendto(sock, dataptr, datalen, 0, (struct sockaddr *)addrptr, addrlen);
@@ -1801,10 +2610,10 @@ CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeI
     {
         SInt32 flags = fcntl(sock, F_GETFL, 0);
         if (flags >= 0) wasBlocking = ((flags & O_NONBLOCK) == 0);
-        if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, &yes);
+        if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctl(sock, FIONBIO, &yes);
         result = connect(sock, (struct sockaddr *)name, namelen);
         if (result != 0) {
-            connect_err = __CFSocketLastError();
+            connect_err = thread_errno();
         }
 #if defined(LOG_CFSOCKET)
         fprintf(stdout, "connection attempt returns %ld error %ld on socket %d (flags 0x%lx blocking %d)\n", result, connect_err, sock, flags, wasBlocking);
@@ -1816,11 +2625,11 @@ CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeI
             struct timeval tv;
             CFMutableDataRef fds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
             __CFSocketFdSet(sock, fds);
-            tv.tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
-            tv.tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
+            tv.tv_sec = (timeout <= 0.0 || (CFTimeInterval)INT_MAX <= timeout) ? INT_MAX : (int)floor(timeout);
+            tv.tv_usec = (int)floor(1.0e+6 * (timeout - floor(timeout)));
             nrfds = select(__CFSocketFdGetSize(fds), NULL, (fd_set *)CFDataGetMutableBytePtr(fds), NULL, &tv);
             if (nrfds < 0) {
-                select_err = __CFSocketLastError();
+                select_err = thread_errno();
                 result = -1;
             } else if (nrfds == 0) {
                 result = -2;
@@ -1833,7 +2642,7 @@ CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeI
             fprintf(stdout, "timed connection attempt %s on socket %d, result %ld, select returns %ld error %ld\n", (result == 0) ? "succeeds" : "fails", sock, result, nrfds, select_err);
 #endif
         }
-        if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, &no);
+        if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctl(sock, FIONBIO, &no);
         if (EINPROGRESS == connect_err && timeout < 0.0) {
             result = 0;
 #if defined(LOG_CFSOCKET)
@@ -1858,7 +2667,7 @@ CFSocketRef CFSocketCreate(CFAllocatorRef allocator, SInt32 protocolFamily, SInt
     if (PF_LOCAL == protocolFamily && 0 >= socketType) socketType = SOCK_STREAM;
     sock = socket(protocolFamily, socketType, protocol);
     if (INVALID_SOCKET != sock) {
-        s = _CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context, FALSE);
+        s = CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context);
     }
     return s;
 }
@@ -2075,4 +2884,3 @@ CF_EXPORT uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
     return __CFSocketDefaultNameRegistryPortNumber;
 }
 
-
index 9d509be3d97404ce85a6e7ea00a9a3c86acafe56..7e6f71c961350ba668683f363dfc9b0840a2bf70 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFSocket.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSOCKET__)
 #define __COREFOUNDATION_CFSOCKET__ 1
 
-#if defined(__WIN32__)
-// This needs to be early in the file, before sys/types gets included, or winsock.h complains
-// about "fd_set and associated macros have been defined".
-#include <winsock2.h>
-typedef SOCKET CFSocketNativeHandle;
+#include <TargetConditionals.h>
+
+#if TARGET_OS_WIN32
+typedef uintptr_t CFSocketNativeHandle;
 #else
 typedef int CFSocketNativeHandle;
 #endif
@@ -156,6 +155,9 @@ enum {
     kCFSocketAutomaticallyReenableAcceptCallBack = 2,
     kCFSocketAutomaticallyReenableDataCallBack = 3,
     kCFSocketAutomaticallyReenableWriteCallBack = 8,
+#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
+    kCFSocketLeaveErrors = 64,
+#endif
     kCFSocketCloseOnInvalidate = 128
 };
 #endif
index ea699ae752912f7251960b445d72bc81f0ce97d8..69d449faddb19cc2d922c02ab878ba86bf976fd6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFSocketStream.c
-       Copyright 2000-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc. All rights reserved.
        Responsibility: Jeremy Wyld
 */
 //     Original Author: Becky Willrich
@@ -31,7 +31,7 @@
 #include "CFStreamInternal.h"
 #include "CFStreamPriv.h"
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 // On Mach these live in CF for historical reasons, even though they are declared in CFNetwork
 
 const int kCFStreamErrorDomainSSL = 3;
@@ -58,6 +58,14 @@ CONST_STRING_DECL(kCFStreamSocketSecurityLevelNegotiatedSSL, "kCFStreamSocketSec
 
 #endif
 
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_WINDOWS
+typedef void (*CF_SOCKET_STREAM_PAIR)(CFAllocatorRef, CFStringRef, UInt32, CFSocketNativeHandle, const CFSocketSignature*, CFReadStreamRef*, CFWriteStreamRef*);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
 // These are duplicated in CFNetwork, who actually externs them in its headers
 CONST_STRING_DECL(kCFStreamPropertySocketSSLContext, "kCFStreamPropertySocketSSLContext")
 CONST_STRING_DECL(_kCFStreamPropertySocketSecurityAuthenticatesServerCertificate, "_kCFStreamPropertySocketSecurityAuthenticatesServerCertificate");
@@ -97,12 +105,24 @@ enum {
 static struct {
     CFSpinLock_t lock;
     UInt32     flags;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_WINDOWS
+    HMODULE    image;
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
     void (*_CFSocketStreamCreatePair)(CFAllocatorRef, CFStringRef, UInt32, CFSocketNativeHandle, const CFSocketSignature*, CFReadStreamRef*, CFWriteStreamRef*);
     CFErrorRef (*_CFErrorCreateWithStreamError)(CFAllocatorRef, CFStreamError*);
     CFStreamError (*_CFStreamErrorFromCFError)(CFErrorRef);
 } CFNetworkSupport = {
     CFSpinLockInit,
     0x0,
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_WINDOWS
+    NULL,
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
     NULL,
     NULL,
     NULL
@@ -110,17 +130,53 @@ static struct {
 
 #define CFNETWORK_CALL(sym, args)              ((CFNetworkSupport.sym)args)
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define CFNETWORK_LOAD_SYM(sym)   __CFLookupCFNetworkFunction(#sym)
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define CFNETWORK_LOAD_SYM(sym)   (void *)GetProcAddress(CFNetworkSupport.image, #sym)
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 static void initializeCFNetworkSupport(void) {
     __CFBitSet(CFNetworkSupport.flags, kTriedToLoad);
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     CFNetworkSupport._CFSocketStreamCreatePair = CFNETWORK_LOAD_SYM(_CFSocketStreamCreatePair);
     CFNetworkSupport._CFErrorCreateWithStreamError = CFNETWORK_LOAD_SYM(_CFErrorCreateWithStreamError);
     CFNetworkSupport._CFStreamErrorFromCFError = CFNETWORK_LOAD_SYM(_CFStreamErrorFromCFError);
+#elif DEPLOYMENT_TARGET_WINDOWS
+    if (!CFNetworkSupport.image) {
+#if _DEBUG
+        CFNetworkSupport.image = GetModuleHandleW(L"CFNetwork_debug.dll");
+#else
+        CFNetworkSupport.image = GetModuleHandleW(L"CFNetwork.dll");
+#endif
+    }
+
+    if (!CFNetworkSupport.image) {
+        // not loaded yet, try to load from the filesystem
+        char path[MAX_PATH+1];
+        if (!CFNetworkSupport.image) {
+            strlcpy(path, (const char *)_CFDLLPath(), sizeof(path));
+#if _DEBUG
+            strlcat(path, "\\CFNetwork_debug.dll", sizeof(path));
+#else
+            strlcat(path, "\\CFNetwork.dll", sizeof(path));
+#endif
+            CFNetworkSupport.image = LoadLibraryA(path);
+        }
+    }
+            
+    if (!CFNetworkSupport.image) {
+        CFLog(__kCFLogAssertion, CFSTR("CoreFoundation: failed to dynamically load CFNetwork"));
+    } else  {
+        CFNetworkSupport._CFSocketStreamCreatePair = (CF_SOCKET_STREAM_PAIR)CFNETWORK_LOAD_SYM(_CFSocketStreamCreatePair);
+        CFNetworkSupport._CFErrorCreateWithStreamError = (CFErrorRef(*)(CFAllocatorRef, CFStreamError *))CFNETWORK_LOAD_SYM(_CFErrorCreateWithStreamError);
+        CFNetworkSupport._CFStreamErrorFromCFError = (CFStreamError(*)(CFErrorRef))CFNETWORK_LOAD_SYM(_CFStreamErrorFromCFError);
+    }
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
     if (!CFNetworkSupport._CFSocketStreamCreatePair) CFLog(__kCFLogAssertion, CFSTR("CoreFoundation: failed to dynamically link symbol _CFSocketStreamCreatePair"));
@@ -147,15 +203,15 @@ createPair(CFAllocatorRef alloc, CFStringRef host, UInt32 port, CFSocketNativeHa
 }
 
 
-extern void CFStreamCreatePairWithSocket(CFAllocatorRef alloc, CFSocketNativeHandle sock, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream) {
+CF_EXPORT void CFStreamCreatePairWithSocket(CFAllocatorRef alloc, CFSocketNativeHandle sock, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream) {
     createPair(alloc, NULL, 0, sock, NULL, readStream, writeStream);
 }
 
-extern void CFStreamCreatePairWithSocketToHost(CFAllocatorRef alloc, CFStringRef host, UInt32 port, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream) {
+CF_EXPORT void CFStreamCreatePairWithSocketToHost(CFAllocatorRef alloc, CFStringRef host, UInt32 port, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream) {
     createPair(alloc, host, port, 0, NULL, readStream, writeStream);
 }
 
-extern void CFStreamCreatePairWithPeerSocketSignature(CFAllocatorRef alloc, const CFSocketSignature* sig, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream) {
+CF_EXPORT void CFStreamCreatePairWithPeerSocketSignature(CFAllocatorRef alloc, const CFSocketSignature* sig, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream) {
     createPair(alloc, NULL, 0, 0, sig, readStream, writeStream);
 }
 
index 6a1ce6bea69e25f80560ba53c6f323124fdb0927..92750590e9e8c90f50bb84c715ceda6bcf1da8d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFSortFunctions.c
-       Copyright 1999-2007, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
-/* This file contains code copied from the Libc project's files
-   qsort.c and merge.c, and modified to suit the
-   needs of CF, which needs the comparison callback to have an
-   additional parameter. The code is collected into this one
-   file so that the individual BSD sort routines can remain
-   private and static.
-*/
-
 #include <CoreFoundation/CFBase.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-#include <sys/types.h>
-#else
-#define EINVAL         22
-#endif
 #include "CFInternal.h"
-
-
-/* stdlib.subproj/qsort.c ============================================== */
-
-/*-
- * Copyright (c) 1992, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if 0
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)qsort.c    8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.12 2002/09/10 02:04:49 wollman Exp $");
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#include <dispatch/dispatch.h>
+#include <sys/sysctl.h>
 #endif
 
-#include <stdlib.h>
 
-#ifdef I_AM_QSORT_R
-typedef int             cmp_t(void *, const void *, const void *);
-#else
-typedef CFComparisonResult              cmp_t(const void *, const void *, void *);
-#endif
-static inline char     *med3(char *, char *, char *, cmp_t *, void *);
-static inline void      swapfunc(char *, char *, long, long);
+enum {
+    kCFSortConcurrent = (1 << 0),
+    kCFSortStable = (1 << 4),
+};
+
+typedef CFIndex VALUE_TYPE;
+typedef CFIndex INDEX_TYPE;
+typedef CFComparisonResult CMP_RESULT_TYPE;
+typedef CMP_RESULT_TYPE (^COMPARATOR_BLOCK)(VALUE_TYPE, VALUE_TYPE);
 
-#if !defined(min)
-#define min(a, b)      (a) < (b) ? a : b
-#endif
 /*
- * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
- */
-#define swapcode(TYPE, parmi, parmj, n) {              \
-       long i = (n) / sizeof (TYPE);                   \
-       TYPE *pi = (TYPE *) (parmi);            \
-       TYPE *pj = (TYPE *) (parmj);            \
-       do {                                            \
-               TYPE    t = *pi;                \
-               *pi++ = *pj;                            \
-               *pj++ = t;                              \
-        } while (--i > 0);                             \
-}
+Number of elements in a list and expected number of compares,
+when the initial short-circuiting compare is not done.
+1      0
+2      1
+3      2.667
+4      4.667
+5      7.167
+6      9.833
+7      12.733
+8      15.733
+9      19.167
+10     22.667
+11     26.2857
+12     29.9524
+*/
 
-#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
-       es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+static void __CFSimpleMerge(VALUE_TYPE listp[], INDEX_TYPE cnt1, INDEX_TYPE cnt2, VALUE_TYPE tmp[], COMPARATOR_BLOCK cmp) {
+    if (cnt1 <= 0 || cnt2 <= 0) return;
+    // if the last element of listp1 <= the first of listp2, lists are already ordered
+    if (16 < cnt1 + cnt2 && cmp(listp[cnt1 - 1], listp[cnt1]) <= 0) return;
+
+    INDEX_TYPE idx = 0, idx1 = 0, idx2 = cnt1;
+    for (;;) {
+        if (cnt1 <= idx1) {
+            while (idx--) {
+                listp[idx] = tmp[idx];
+            }
+            return;
+        }
+        if (cnt1 + cnt2 <= idx2) {
+            for (INDEX_TYPE t = cnt1 + cnt2 - 1; idx <= t; t--) {
+                listp[t] = listp[t - cnt2];
+            }
+            while (idx--) {
+                listp[idx] = tmp[idx];
+            }
+            return;
+        }
+        VALUE_TYPE v1 = listp[idx1], v2 = listp[idx2];
+        if (cmp(v1, v2) <= 0) {
+            tmp[idx] = v1;
+            idx1++;
+        } else {
+            tmp[idx] = v2;
+            idx2++;
+        }
+        idx++;
+    }
+}
 
-static inline void
-swapfunc(char *a, char *b, long n, long swaptype)
-{
-       if(swaptype <= 1)
-               swapcode(long, a, b, n)
-       else
-               swapcode(char, a, b, n)
+static void __CFSimpleMergeSort(VALUE_TYPE listp[], INDEX_TYPE cnt, VALUE_TYPE tmp[], COMPARATOR_BLOCK cmp) {
+    if (cnt < 2) {
+        /* do nothing */
+    } else if (2 == cnt) {
+        VALUE_TYPE v0 = listp[0], v1 = listp[1];
+        if (0 < cmp(v0, v1)) {
+            listp[0] = v1;
+            listp[1] = v0;
+        }
+    } else if (3 == cnt) {
+        VALUE_TYPE v0 = listp[0], v1 = listp[1], v2 = listp[2], vt;
+        if (0 < cmp(v0, v1)) {
+            vt = v0;
+            v0 = v1;
+            v1 = vt;
+        }
+        if (0 < cmp(v1, v2)) {
+            vt = v1;
+            v1 = v2;
+            v2 = vt;
+            if (0 < cmp(v0, v1)) {
+                vt = v0;
+                v0 = v1;
+                v1 = vt;
+            }
+        }
+        listp[0] = v0;
+        listp[1] = v1;
+        listp[2] = v2;
+    } else {
+        INDEX_TYPE half_cnt = cnt / 2;
+        __CFSimpleMergeSort(listp, half_cnt, tmp, cmp);
+        __CFSimpleMergeSort(listp + half_cnt, cnt - half_cnt, tmp, cmp);
+        __CFSimpleMerge(listp, half_cnt, cnt - half_cnt, tmp, cmp);
+    }
 }
 
-#define swap(a, b)                                     \
-       if (swaptype == 0) {                            \
-               long t = *(long *)(a);                  \
-               *(long *)(a) = *(long *)(b);            \
-               *(long *)(b) = t;                       \
-       } else                                          \
-               swapfunc(a, b, es, swaptype)
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+// if !right, put the cnt1 smallest values in tmp, else put the cnt2 largest values in tmp
+static void __CFSortIndexesNMerge(VALUE_TYPE listp1[], INDEX_TYPE cnt1, VALUE_TYPE listp2[], INDEX_TYPE cnt2, VALUE_TYPE tmp[], size_t right, COMPARATOR_BLOCK cmp) {
+    // if the last element of listp1 <= the first of listp2, lists are already ordered
+    if (16 < cnt1 + cnt2 && cmp(listp1[cnt1 - 1], listp2[0]) <= 0) {
+        memmove(tmp, (right ? listp2 : listp1), (right ? cnt2 : cnt1) * sizeof(VALUE_TYPE));
+        return;
+    }
 
-#define vecswap(a, b, n)       if ((n) > 0) swapfunc(a, b, n, swaptype)
+    if (right) {
+        VALUE_TYPE *listp1_end = listp1;
+        VALUE_TYPE *listp2_end = listp2;
+        VALUE_TYPE *tmp_end = tmp;
+        listp1 += cnt1 - 1;
+        listp2 += cnt2 - 1;
+        tmp += cnt2;
+        while (tmp_end < tmp) {
+            tmp--;
+            if (listp2 < listp2_end) {
+                listp1--;
+                *tmp = *listp1;
+            } else if (listp1 < listp1_end) {
+                listp2--;
+                *tmp = *listp2;
+            } else {
+                VALUE_TYPE v1 = *listp1, v2 = *listp2;
+                CMP_RESULT_TYPE res = cmp(v1, v2);
+                if (res <= 0) {
+                    *tmp = v2;
+                    listp2--;
+                } else {
+                    *tmp = v1;
+                    listp1--;
+                }
+            }
+        }
+    } else {
+        VALUE_TYPE *listp1_end = listp1 + cnt1;
+        VALUE_TYPE *listp2_end = listp2 + cnt2;
+        VALUE_TYPE *tmp_end = tmp + cnt1;
+        while (tmp < tmp_end) {
+            if (listp2_end <= listp2) {
+                *tmp = *listp1;
+                listp1++;
+            } else if (listp1_end <= listp1) {
+                *tmp = *listp2;
+                listp2++;
+            } else {
+                VALUE_TYPE v1 = *listp1, v2 = *listp2;
+                CMP_RESULT_TYPE res = cmp(v1, v2);
+                if (res <= 0) {
+                    *tmp = v1;
+                    listp1++;
+                } else {
+                    *tmp = v2;
+                    listp2++;
+                }
+            }
+            tmp++;
+        }
+    }
+}
 
-#ifdef I_AM_QSORT_R
-#define        CMP(t, x, y) (cmp((t), (x), (y)))
-#else
-#define        CMP(t, x, y) (cmp((x), (y), (t)))
-#endif
+/* Merging algorithm based on
+    "A New Parallel Sorting Algorithm based on Odd-Even Mergesort", Ezequiel Herruzo, et al
+*/
+static void __CFSortIndexesN(VALUE_TYPE listp[], INDEX_TYPE count, int32_t ncores, CMP_RESULT_TYPE (^cmp)(INDEX_TYPE, INDEX_TYPE)) {
+    /* Divide the array up into up to ncores, multiple-of-16-sized, chunks */
+    INDEX_TYPE sz = ((((count + ncores - 1) / ncores) + 15) / 16) * 16;
+    INDEX_TYPE num_sect = (count + sz - 1) / sz;
+    INDEX_TYPE last_sect_len = count + sz - sz * num_sect;
+
+    STACK_BUFFER_DECL(VALUE_TYPE *, stack_tmps, num_sect);
+    for (INDEX_TYPE idx = 0; idx < num_sect; idx++) {
+        stack_tmps[idx] = malloc(sz * sizeof(VALUE_TYPE));
+    }
+    VALUE_TYPE **tmps = stack_tmps;
+
+    dispatch_queue_t q = dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT);
+    dispatch_apply(num_sect, q, ^(size_t sect) {
+            INDEX_TYPE sect_len = (sect < num_sect - 1) ? sz : last_sect_len;
+            __CFSimpleMergeSort(listp + sect * sz, sect_len, tmps[sect], cmp); // naturally stable
+        });
+
+    INDEX_TYPE even_phase_cnt = ((num_sect / 2) * 2);
+    INDEX_TYPE odd_phase_cnt = (((num_sect - 1) / 2) * 2);
+    for (INDEX_TYPE idx = 0; idx < (num_sect + 1) / 2; idx++) {
+        dispatch_apply(even_phase_cnt, q, ^(size_t sect) { // merge even
+                size_t right = sect & (size_t)0x1;
+                VALUE_TYPE *left_base = listp + sect * sz - (right ? sz : 0);
+                VALUE_TYPE *right_base = listp + sect * sz + (right ? 0 : sz);
+                INDEX_TYPE sect2_len = (sect + 1 + (right ? 0 : 1) == num_sect) ? last_sect_len : sz;
+                __CFSortIndexesNMerge(left_base, sz, right_base, sect2_len, tmps[sect], right, cmp);
+            });
+        if (num_sect & 0x1) {
+            memmove(tmps[num_sect - 1], listp + (num_sect - 1) * sz, last_sect_len * sizeof(VALUE_TYPE));
+        }
+        dispatch_apply(odd_phase_cnt, q, ^(size_t sect) { // merge odd
+                size_t right = sect & (size_t)0x1;
+                VALUE_TYPE *left_base = tmps[sect + (right ? 0 : 1)];
+                VALUE_TYPE *right_base = tmps[sect + (right ? 1 : 2)];
+                INDEX_TYPE sect2_len = (sect + 1 + (right ? 1 : 2) == num_sect) ? last_sect_len : sz;
+                __CFSortIndexesNMerge(left_base, sz, right_base, sect2_len, listp + sect * sz + sz, right, cmp);
+            });
+        memmove(listp + 0 * sz, tmps[0], sz * sizeof(VALUE_TYPE));
+        if (!(num_sect & 0x1)) {
+            memmove(listp + (num_sect - 1) * sz, tmps[num_sect - 1], last_sect_len * sizeof(VALUE_TYPE));
+        }
+    }
 
-static inline char *
-med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk)
-{
-       return CMP(thunk, a, b) < 0 ?
-              (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
-              :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+    for (INDEX_TYPE idx = 0; idx < num_sect; idx++) {
+        free(stack_tmps[idx]);
+    }
 }
-
-#ifdef I_AM_QSORT_R
-void
-qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
-#else
-static void
-bsd_qsort(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk)
 #endif
-{
-       char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
-       long d, r, swaptype, swap_cnt;
-
-loop:  SWAPINIT(a, es);
-       swap_cnt = 0;
-       if (n < 7) {
-               for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
-                       for (pl = pm; 
-                            pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
-                            pl -= es)
-                               swap(pl, pl - es);
-               return;
-       }
-       pm = (char *)a + (n / 2) * es;
-       if (n > 7) {
-               pl = a;
-               pn = (char *)a + (n - 1) * es;
-               if (n > 40) {
-                       d = (n / 8) * es;
-                       pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
-                       pm = med3(pm - d, pm, pm + d, cmp, thunk);
-                       pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
-               }
-               pm = med3(pl, pm, pn, cmp, thunk);
-       }
-       swap(a, pm);
-       pa = pb = (char *)a + es;
-
-       pc = pd = (char *)a + (n - 1) * es;
-       for (;;) {
-               while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
-                       if (r == 0) {
-                               swap_cnt = 1;
-                               swap(pa, pb);
-                               pa += es;
-                       }
-                       pb += es;
-               }
-               while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
-                       if (r == 0) {
-                               swap_cnt = 1;
-                               swap(pc, pd);
-                               pd -= es;
-                       }
-                       pc -= es;
-               }
-               if (pb > pc)
-                       break;
-               swap(pb, pc);
-               swap_cnt = 1;
-               pb += es;
-               pc -= es;
-       }
-       if (swap_cnt == 0) {  /* Switch to insertion sort */
-               for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
-                       for (pl = pm; 
-                            pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
-                            pl -= es)
-                               swap(pl, pl - es);
-               return;
-       }
 
-       pn = (char *)a + n * es;
-       r = min(pa - (char *)a, pb - pa);
-       vecswap(a, pb - r, r);
-       r = min(pd - pc, pn - pd - es);
-       vecswap(pb, pn - r, r);
-       if ((r = pb - pa) > es)
-#ifdef I_AM_QSORT_R
-               qsort_r(a, r / es, es, thunk, cmp);
+// returns an array of indexes (of length count) giving the indexes 0 - count-1, as sorted by the comparator block
+CFIndex *CFSortIndexes(CFIndex count, CFOptionFlags opts, CFComparisonResult (^cmp)(CFIndex, CFIndex)) {
+    if (count < 1) return NULL;
+    if (INTPTR_MAX / sizeof(CFIndex) < count) return NULL;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    int32_t ncores = 0;
+    if (opts & kCFSortConcurrent) {
+        int32_t mib[2] = {CTL_HW, HW_AVAILCPU};
+        size_t len = sizeof(ncores);
+        sysctl(mib, 2, &ncores, &len, NULL, 0);
+        if (count < 160 || ncores < 2) {
+            opts = (opts & ~kCFSortConcurrent);
+        } else if (count < 640 && 2 < ncores) {
+            ncores = 2;
+        } else if (count < 3200 && 4 < ncores) {
+            ncores = 4;
+        } else if (count < 16000 && 8 < ncores) {
+            ncores = 8;
+        }
+        if (16 < ncores) {
+            ncores = 16;
+        }
+    }
+    CFIndex *idxs = malloc_zone_memalign(malloc_default_zone(), 64, count * sizeof(CFIndex));
+    if (!idxs) return NULL;
+    if (count <= 65536) {
+        for (CFIndex idx = 0; idx < count; idx++) idxs[idx] = idx;
+    } else {
+        /* Specifically hard-coded to 8; the count has to be very large before more chunks and/or cores is worthwhile. */
+        CFIndex sz = ((((size_t)count + 15) / 16) * 16) / 8;
+        dispatch_apply(8, dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT), ^(size_t n) {
+                CFIndex idx = n * sz, lim = __CFMin(idx + sz, count);
+                for (; idx < lim; idx++) idxs[idx] = idx;
+            });
+    }
+    if (opts & kCFSortConcurrent) {
+        __CFSortIndexesN(idxs, count, ncores, cmp); // naturally stable
+        return idxs;
+    }
 #else
-               bsd_qsort(a, r / es, es, cmp, thunk);
+    CFIndex *idxs = (CFIndex *)malloc(count * sizeof(CFIndex));
+    if (!idxs) return NULL;
+    for (CFIndex idx = 0; idx < count; idx++) idxs[idx] = idx;
 #endif
-       if ((r = pd - pc) > es) {
-               /* Iterate rather than recurse to save stack space */
-               a = pn - r;
-               n = r / es;
-               goto loop;
-       }
-/*             qsort(pn - r, r / es, es, cmp);*/
-}
-
-
-/* And now for something not so completely different, a copy/paste version that uses write-barriers so as to notify GC as necessary of changes */
-#define ASSIGN __CFObjCStrongAssign
-//#define ASSIGN objc_assign_strongCast
-
-#define swapcode_wb(TYPE, parmi, parmj, n) {           \
-       long i = (n) / sizeof (TYPE);                   \
-       TYPE *pi = (TYPE *) (parmi);            \
-       TYPE *pj = (TYPE *) (parmj);            \
-       do {                                            \
-               TYPE    t = *pi;                \
-                ASSIGN(*pj, pi++);   \
-                ASSIGN(t, pj++); \
-        } while (--i > 0);                             \
-}
-
-
-static inline void
-swapfunc_wb(char *a, char *b, long n, long swaptype)
-{
-       if(swaptype <= 1)
-               swapcode_wb(void *, a, b, n)
-       else
-               swapcode(char, a, b, n)
-}
-
-#define swap_wb(a, b)                                  \
-       if (swaptype == 0) {                            \
-               const void *t = *(const void **)(a);                    \
-               ASSIGN(*(void **)(b), (const void **)a); \
-               ASSIGN(t, (const void **)(b));    \
-       } else \
-               printf("bad things happening\n");
-                //swapfunc_wb(a, b, es, swaptype)
-
-#define vecswap_wb(a, b, n)    if ((n) > 0) swapfunc_wb(a, b, n, swaptype)
-
-static void
-bsd_qsort_wb(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk)
-{
-       char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
-       long d, r, swaptype, swap_cnt;
-
-loop:  SWAPINIT(a, es);
-       swap_cnt = 0;
-       if (n < 7) {
-               for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
-                       for (pl = pm; 
-                            pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
-                            pl -= es)
-                               swap_wb(pl, pl - es);
-               return;
-       }
-       pm = (char *)a + (n / 2) * es;
-       if (n > 7) {
-               pl = a;
-               pn = (char *)a + (n - 1) * es;
-               if (n > 40) {
-                       d = (n / 8) * es;
-                       pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
-                       pm = med3(pm - d, pm, pm + d, cmp, thunk);
-                       pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
-               }
-               pm = med3(pl, pm, pn, cmp, thunk);
-       }
-       swap_wb(a, pm);
-       pa = pb = (char *)a + es;
-
-       pc = pd = (char *)a + (n - 1) * es;
-       for (;;) {
-               while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
-                       if (r == 0) {
-                               swap_cnt = 1;
-                               swap_wb(pa, pb);
-                               pa += es;
-                       }
-                       pb += es;
-               }
-               while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
-                       if (r == 0) {
-                               swap_cnt = 1;
-                               swap_wb(pc, pd);
-                               pd -= es;
-                       }
-                       pc -= es;
-               }
-               if (pb > pc)
-                       break;
-               swap_wb(pb, pc);
-               swap_cnt = 1;
-               pb += es;
-               pc -= es;
-       }
-       if (swap_cnt == 0) {  /* Switch to insertion sort */
-               for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
-                       for (pl = pm; 
-                            pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
-                            pl -= es)
-                               swap_wb(pl, pl - es);
-               return;
-       }
-
-       pn = (char *)a + n * es;
-       r = min(pa - (char *)a, pb - pa);
-       vecswap_wb(a, pb - r, r);
-       r = min(pd - pc, pn - pd - es);
-       vecswap_wb(pb, pn - r, r);
-       if ((r = pb - pa) > es)
-               bsd_qsort_wb(a, r / es, es, cmp, thunk);
-       if ((r = pd - pc) > es) {
-               /* Iterate rather than recurse to save stack space */
-               a = pn - r;
-               n = r / es;
-               goto loop;
-       }
-/*             qsort(pn - r, r / es, es, cmp);*/
+    STACK_BUFFER_DECL(VALUE_TYPE, local, count <= 16384 ? count : 1);
+    VALUE_TYPE *tmp = (count <= 16384) ? local : (VALUE_TYPE *)malloc(count * sizeof(VALUE_TYPE));
+    __CFSimpleMergeSort(idxs, count, tmp, cmp); // naturally stable
+    if (local != tmp) free(tmp);
+    return idxs;
 }
 
 /* Comparator is passed the address of the values. */
 void CFQSortArray(void *list, CFIndex count, CFIndex elementSize, CFComparatorFunction comparator, void *context) {
-    if (CF_USING_COLLECTABLE_MEMORY && (auto_zone_get_layout_type(__CFCollectableZone, list) & AUTO_UNSCANNED) == 0)
-        bsd_qsort_wb(list, count, elementSize, comparator, context);
-    else
-        bsd_qsort(list, count, elementSize, comparator, context);
-}
-
-#undef thunk
-#undef CMP
-#undef vecswap
-//#undef swap
-#undef SWAPINIT
-#undef swapcode
-#undef min
-
-/* stdlib.subproj/mergesort.c ========================================== */
-
-/*-
- * Copyright (c) 1992, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Peter McIlroy.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if 0
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)merge.c    8.2 (Berkeley) 2/14/94";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdlib/merge.c,v 1.6 2002/03/21 22:48:42 obrien Exp $");
-#endif
-
-/*
- * Hybrid exponential search/linear search merge sort with hybrid
- * natural/pairwise first pass.  Requires about .3% more comparisons
- * for random data than LSMS with pairwise first pass alone.
- * It works for objects as small as two bytes.
- */
-
-#define NATURAL
-#define THRESHOLD 16   /* Best choice for natural merge cut-off. */
-
-/* #define NATURAL to get hybrid natural merge.
- * (The default is pairwise merging.)
- */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-static void setup(u_char *, u_char *, size_t, size_t, CFComparisonResult (*)(), void *);
-static void insertionsort(u_char *, size_t, size_t, CFComparisonResult (*)(), void *);
-
-#define ISIZE sizeof(long)
-#define PSIZE sizeof(u_char *)
-#define ICOPY_LIST(src, dst, last)                             \
-       do                                                      \
-       *(long*)dst = *(long*)src, src += ISIZE, dst += ISIZE;  \
-       while(src < last)
-#define ICOPY_ELT(src, dst, i)                                 \
-       do                                                      \
-       *(long*) dst = *(long*) src, src += ISIZE, dst += ISIZE;        \
-       while (i -= ISIZE)
-
-#define CCOPY_LIST(src, dst, last)             \
-       do                                      \
-               *dst++ = *src++;                \
-       while (src < last)
-#define CCOPY_ELT(src, dst, i)                 \
-       do                                      \
-               *dst++ = *src++;                \
-       while (i -= 1)
-
-/*
- * Find the next possible pointer head.  (Trickery for forcing an array
- * to do double duty as a linked list when objects do not align with word
- * boundaries.
- */
-/* Assumption: PSIZE is a power of 2. */
-#define EVAL(p) (u_char **)                                            \
-       ((u_char *)0 +                                                  \
-           (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1)))
-
-/*
- * Arguments are as for qsort.
- */
-static int
-bsd_mergesort(void *base, size_t nmemb, size_t size, CFComparisonResult (*cmp)(const void *, const void *, void *), void *context)
-{
-       long i, sense;
-       long big, iflag;
-       u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
-       u_char *list2, *list1, *p2, *p, *last, **p1;
-
-       if (size < PSIZE / 2) {         /* Pointers must fit into 2 * size. */
-               errno = EINVAL;
-               return (-1);
-       }
-
-       if (nmemb == 0)
-               return (0);
-
-       /*
-        * XXX
-        * Stupid subtraction for the Cray.
-        */
-       iflag = 0;
-       if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
-               iflag = 1;
-
-       if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
-               return (-1);
-
-       list1 = base;
-       setup(list1, list2, nmemb, size, cmp, context);
-       last = list2 + nmemb * size;
-       i = big = 0;
-       while (*EVAL(list2) != last) {
-           l2 = list1;
-           p1 = EVAL(list1);
-           for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
-               p2 = *EVAL(p2);
-               f1 = l2;
-               f2 = l1 = list1 + (p2 - list2);
-               if (p2 != last)
-                       p2 = *EVAL(p2);
-               l2 = list1 + (p2 - list2);
-               while (f1 < l1 && f2 < l2) {
-                       if ((*cmp)(f1, f2, context) <= 0) {
-                               q = f2;
-                               b = f1, t = l1;
-                               sense = -1;
-                       } else {
-                               q = f1;
-                               b = f2, t = l2;
-                               sense = 0;
-                       }
-                       if (!big) {     /* here i = 0 */
-                               while ((b += size) < t && cmp(q, b, context) >sense)
-                                       if (++i == 6) {
-                                               big = 1;
-                                               goto EXPONENTIAL;
-                                       }
-                       } else {
-EXPONENTIAL:                   for (i = size; ; i <<= 1)
-                                       if ((p = (b + i)) >= t) {
-                                               if ((p = t - size) > b &&
-                                                   (*cmp)(q, p, context) <= sense)
-                                                       t = p;
-                                               else
-                                                       b = p;
-                                               break;
-                                       } else if ((*cmp)(q, p, context) <= sense) {
-                                               t = p;
-                                               if (i == size)
-                                                       big = 0;
-                                               goto FASTCASE;
-                                       } else
-                                               b = p;
-                               while (t > b+size) {
-                                       i = (((t - b) / size) >> 1) * size;
-                                       if ((*cmp)(q, p = b + i, context) <= sense)
-                                               t = p;
-                                       else
-                                               b = p;
-                               }
-                               goto COPY;
-FASTCASE:                      while (i > size)
-                                       if ((*cmp)(q,
-                                               p = b + (i >>= 1), context) <= sense)
-                                               t = p;
-                                       else
-                                               b = p;
-COPY:                          b = t;
-                       }
-                       i = size;
-                       if (q == f1) {
-                               if (iflag) {
-                                       ICOPY_LIST(f2, tp2, b);
-                                       ICOPY_ELT(f1, tp2, i);
-                               } else {
-                                       CCOPY_LIST(f2, tp2, b);
-                                       CCOPY_ELT(f1, tp2, i);
-                               }
-                       } else {
-                               if (iflag) {
-                                       ICOPY_LIST(f1, tp2, b);
-                                       ICOPY_ELT(f2, tp2, i);
-                               } else {
-                                       CCOPY_LIST(f1, tp2, b);
-                                       CCOPY_ELT(f2, tp2, i);
-                               }
-                       }
-               }
-               if (f2 < l2) {
-                       if (iflag)
-                               ICOPY_LIST(f2, tp2, l2);
-                       else
-                               CCOPY_LIST(f2, tp2, l2);
-               } else if (f1 < l1) {
-                       if (iflag)
-                               ICOPY_LIST(f1, tp2, l1);
-                       else
-                               CCOPY_LIST(f1, tp2, l1);
-               }
-               *p1 = l2;
-           }
-           tp2 = list1;        /* swap list1, list2 */
-           list1 = list2;
-           list2 = tp2;
-           last = list2 + nmemb*size;
-       }
-       if (base == list2) {
-               memmove(list2, list1, nmemb*size);
-               list2 = list1;
-       }
-       free(list2);
-       return (0);
-}
-
-#define        swap(a, b) {                                    \
-               s = b;                                  \
-               i = size;                               \
-               do {                                    \
-                       tmp = *a; *a++ = *s; *s++ = tmp; \
-               } while (--i);                          \
-               a -= size;                              \
-       }
-#define reverse(bot, top) {                            \
-       s = top;                                        \
-       do {                                            \
-               i = size;                               \
-               do {                                    \
-                       tmp = *bot; *bot++ = *s; *s++ = tmp; \
-               } while (--i);                          \
-               s -= size2;                             \
-       } while(bot < s);                               \
-}
-
-/*
- * Optional hybrid natural/pairwise first pass.  Eats up list1 in runs of
- * increasing order, list2 in a corresponding linked list.  Checks for runs
- * when THRESHOLD/2 pairs compare with same sense.  (Only used when NATURAL
- * is defined.  Otherwise simple pairwise merging is used.)
- */
-static void
-setup(u_char *list1, u_char *list2, size_t n, size_t size, CFComparisonResult (*cmp)(const void *, const void *, void *), void *context)
-{
-       long i, length, size2, tmp, sense;
-       u_char *f1, *f2, *s, *l2, *last, *p2;
-
-       size2 = size*2;
-       if (n <= 5) {
-               insertionsort(list1, n, size, cmp, context);
-               *EVAL(list2) = (u_char*) list2 + n*size;
-               return;
-       }
-       /*
-        * Avoid running pointers out of bounds; limit n to evens
-        * for simplicity.
-        */
-       i = 4 + (n & 1);
-       insertionsort(list1 + (n - i) * size, i, size, cmp, context);
-       last = list1 + size * (n - i);
-       *EVAL(list2 + (last - list1)) = list2 + n * size;
-
-#ifdef NATURAL
-       p2 = list2;
-       f1 = list1;
-       sense = (cmp(f1, f1 + size, context) > 0);
-       for (; f1 < last; sense = !sense) {
-               length = 2;
-                                       /* Find pairs with same sense. */
-               for (f2 = f1 + size2; f2 < last; f2 += size2) {
-                       if ((cmp(f2, f2+ size, context) > 0) != sense)
-                               break;
-                       length += 2;
-               }
-               if (length < THRESHOLD) {               /* Pairwise merge */
-                       do {
-                               p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
-                               if (sense > 0)
-                                       swap (f1, f1 + size);
-                       } while ((f1 += size2) < f2);
-               } else {                                /* Natural merge */
-                       l2 = f2;
-                       for (f2 = f1 + size2; f2 < l2; f2 += size2) {
-                               if ((cmp(f2-size, f2, context) > 0) != sense) {
-                                       p2 = *EVAL(p2) = f2 - list1 + list2;
-                                       if (sense > 0)
-                                               reverse(f1, f2-size);
-                                       f1 = f2;
-                               }
-                       }
-                       if (sense > 0)
-                               reverse (f1, f2-size);
-                       f1 = f2;
-                       if (f2 < last || cmp(f2 - size, f2, context) > 0)
-                               p2 = *EVAL(p2) = f2 - list1 + list2;
-                       else
-                               p2 = *EVAL(p2) = list2 + n*size;
-               }
-       }
-#else          /* pairwise merge only. */
-       for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
-               p2 = *EVAL(p2) = p2 + size2;
-               if (cmp (f1, f1 + size, context) > 0)
-                       swap(f1, f1 + size);
-       }
-#endif /* NATURAL */
-}
-
-/*
- * This is to avoid out-of-bounds addresses in sorting the
- * last 4 elements.
- */
-static void
-insertionsort(u_char *a, size_t n, size_t size, CFComparisonResult (*cmp)(const void *, const void *, void *), void *context)
-{
-       u_char *ai, *s, *t, *u, tmp;
-       long i;
-
-       for (ai = a+size; --n >= 1; ai += size)
-               for (t = ai; t > a; t -= size) {
-                       u = t - size;
-                       if (cmp(u, t, context) <= 0)
-                               break;
-                       swap(u, t);
-               }
-}
-
-/* Another version, also not so completely different, in order to handle necessary write-barriers in the face of GC */
-
-#undef ASSIGN
-#define ASSIGN __CFObjCStrongAssign
-//#define ASSIGN log_assign
-
-static void setup_wb(u_char *, u_char *, size_t, size_t, CFComparisonResult (*)(), void *);
-static void insertionsort_wb(u_char *, size_t, size_t, CFComparisonResult (*)(), void *);
-
-#undef ICOPY_ELT
-
-#define ICOPY_ELT(src, dst, i)                                 \
-       do                                                      \
-       ASSIGN(*(const void**)src, (const void *)dst), src += ISIZE, dst += ISIZE;      \
-       while (i -= ISIZE)
-
-#undef ICOPY_LIST
-
-#define ICOPY_LIST(src, dst, last) \
-        do \
-        ASSIGN(*(const void **)src, (const void *)dst), src += ISIZE, dst += ISIZE; \
-        while (src < last)
-
-
-/*
- * Arguments are as for qsort.
- */
-static int
-bsd_mergesort_wb(void *base, size_t nmemb, size_t size, CFComparisonResult (*cmp)(const void *, const void *, void *), void *context)
-{
-       long i, sense;
-       long big, iflag;
-       u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
-       u_char *list2, *list1, *p2, *p, *last, **p1;
-
-       if (size < PSIZE / 2) {         /* Pointers must fit into 2 * size. */
-               errno = EINVAL;
-               return (-1);
-       }
-
-       if (nmemb == 0)
-               return (0);
-
-       /*
-        * XXX
-        * Stupid subtraction for the Cray.
-        */
-       iflag = 0;
-       if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
-               iflag = 1;
-
-        if (!iflag)
-            return -1;      // only set up for "integer" swaps, e.g. long integer
-            
-       if ((list2 = CFAllocatorAllocate(NULL, (nmemb * size + PSIZE), __kCFAllocatorGCScannedMemory)) == NULL)
-               return (-1);
-
-       list1 = base;
-       setup_wb(list1, list2, nmemb, size, cmp, context);
-       last = list2 + nmemb * size;
-       i = big = 0;
-       while (*EVAL(list2) != last) {
-           l2 = list1;
-           p1 = EVAL(list1);
-           for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
-               p2 = *EVAL(p2);
-               f1 = l2;
-               f2 = l1 = list1 + (p2 - list2);
-               if (p2 != last)
-                       p2 = *EVAL(p2);
-               l2 = list1 + (p2 - list2);
-               while (f1 < l1 && f2 < l2) {
-                       if ((*cmp)(f1, f2, context) <= 0) {
-                               q = f2;
-                               b = f1, t = l1;
-                               sense = -1;
-                       } else {
-                               q = f1;
-                               b = f2, t = l2;
-                               sense = 0;
-                       }
-                       if (!big) {     /* here i = 0 */
-                               while ((b += size) < t && cmp(q, b, context) >sense)
-                                       if (++i == 6) {
-                                               big = 1;
-                                               goto EXPONENTIAL;
-                                       }
-                       } else {
-EXPONENTIAL:                   for (i = size; ; i <<= 1)
-                                       if ((p = (b + i)) >= t) {
-                                               if ((p = t - size) > b &&
-                                                   (*cmp)(q, p, context) <= sense)
-                                                       t = p;
-                                               else
-                                                       b = p;
-                                               break;
-                                       } else if ((*cmp)(q, p, context) <= sense) {
-                                               t = p;
-                                               if (i == size)
-                                                       big = 0;
-                                               goto FASTCASE;
-                                       } else
-                                               b = p;
-                               while (t > b+size) {
-                                       i = (((t - b) / size) >> 1) * size;
-                                       if ((*cmp)(q, p = b + i, context) <= sense)
-                                               t = p;
-                                       else
-                                               b = p;
-                               }
-                               goto COPY;
-FASTCASE:                      while (i > size)
-                                       if ((*cmp)(q,
-                                               p = b + (i >>= 1), context) <= sense)
-                                               t = p;
-                                       else
-                                               b = p;
-COPY:                          b = t;
-                       }
-                       i = size;
-                       if (q == f1) {
-                               if (iflag) {
-                                       ICOPY_LIST(f2, tp2, b);
-                                       ICOPY_ELT(f1, tp2, i);
-                               } else {
-                                       CCOPY_LIST(f2, tp2, b);
-                                       CCOPY_ELT(f1, tp2, i);
-                               }
-                       } else {
-                               if (iflag) {
-                                       ICOPY_LIST(f1, tp2, b);
-                                       ICOPY_ELT(f2, tp2, i);
-                               } else {
-                                       CCOPY_LIST(f1, tp2, b);
-                                       CCOPY_ELT(f2, tp2, i);
-                               }
-                       }
-               }
-               if (f2 < l2) {
-                       if (iflag)
-                               ICOPY_LIST(f2, tp2, l2);
-                       else
-                               CCOPY_LIST(f2, tp2, l2);
-               } else if (f1 < l1) {
-                       if (iflag)
-                               ICOPY_LIST(f1, tp2, l1);
-                       else
-                               CCOPY_LIST(f1, tp2, l1);
-               }
-               *p1 = l2;
-           }
-           tp2 = list1;        /* swap list1, list2 */
-           list1 = list2;
-           list2 = tp2;
-           last = list2 + nmemb*size;
-       }
-       if (base == list2) {
-               CF_WRITE_BARRIER_MEMMOVE(list2, list1, nmemb*size);
-               list2 = list1;
-       }
-       free(list2);
-       return (0);
-}
-
-
-#define swap_wb(a, b) { \
-        const void *object = *(void **)a; \
-        ASSIGN(*(const void **)b, (const void *)a); \
-        ASSIGN(object, (const void *)b); \
+    if (count < 1 || elementSize < 1) return;
+    CFIndex *indexes = CFSortIndexes(count, 0, ^(CFIndex a, CFIndex b) { return comparator((char *)list + a * elementSize, (char *)list + b * elementSize, context); }); // naturally stable
+    void *store = malloc(count * elementSize);
+    for (CFIndex idx = 0; idx < count; idx++) {
+        if (sizeof(uintptr_t) == elementSize) {
+            uintptr_t *a = (uintptr_t *)list + indexes[idx];
+            uintptr_t *b = (uintptr_t *)store + idx;
+            *b = *a;
+        } else {
+            memmove((char *)store + idx * elementSize, (char *)list + indexes[idx] * elementSize, elementSize);
+        }
     }
-
-#define reverse_wb(bot, top) {                         \
-       s = top;                                        \
-       do {                                            \
-                swap_wb(bot, s);                           \
-                bot += size;                           \
-               s -= size;                              \
-       } while(bot < s);                               \
-}
-
-/*
- * Optional hybrid natural/pairwise first pass.  Eats up list1 in runs of
- * increasing order, list2 in a corresponding linked list.  Checks for runs
- * when THRESHOLD/2 pairs compare with same sense.  (Only used when NATURAL
- * is defined.  Otherwise simple pairwise merging is used.)
- */
-static void
-setup_wb(u_char *list1, u_char *list2, size_t n, size_t size, CFComparisonResult (*cmp)(const void *, const void *, void *), void *context)
-{
-       long i, length, size2, tmp, sense;
-       u_char *f1, *f2, *s, *l2, *last, *p2;
-
-       size2 = size*2;
-       if (n <= 5) {
-               insertionsort_wb(list1, n, size, cmp, context);
-               *EVAL(list2) = (u_char*) list2 + n*size;
-               return;
-       }
-       /*
-        * Avoid running pointers out of bounds; limit n to evens
-        * for simplicity.
-        */
-       i = 4 + (n & 1);
-       insertionsort_wb(list1 + (n - i) * size, i, size, cmp, context);
-       last = list1 + size * (n - i);
-       *EVAL(list2 + (last - list1)) = list2 + n * size;
-
-#ifdef NATURAL
-       p2 = list2;
-       f1 = list1;
-       sense = (cmp(f1, f1 + size, context) > 0);
-       for (; f1 < last; sense = !sense) {
-               length = 2;
-                                       /* Find pairs with same sense. */
-               for (f2 = f1 + size2; f2 < last; f2 += size2) {
-                       if ((cmp(f2, f2+ size, context) > 0) != sense)
-                               break;
-                       length += 2;
-               }
-               if (length < THRESHOLD) {               /* Pairwise merge */
-                       do {
-                               p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
-                               if (sense > 0)
-                                       swap (f1, f1 + size);
-                       } while ((f1 += size2) < f2);
-               } else {                                /* Natural merge */
-                       l2 = f2;
-                       for (f2 = f1 + size2; f2 < l2; f2 += size2) {
-                               if ((cmp(f2-size, f2, context) > 0) != sense) {
-                                       p2 = *EVAL(p2) = f2 - list1 + list2;
-                                       if (sense > 0) {
-                                               reverse_wb(f1, f2-size);
-                                        }
-                                       f1 = f2;
-                               }
-                       }
-                       if (sense > 0) {
-                               reverse_wb (f1, f2-size);
-                        }
-                       f1 = f2;
-                       if (f2 < last || cmp(f2 - size, f2, context) > 0) {
-                               p2 = *EVAL(p2) = f2 - list1 + list2;
-                        }
-                       else {
-                               p2 = *EVAL(p2) = list2 + n*size;
-                        }
-               }
-       }
-#else          /* pairwise merge only. */
-#error unchanged
-       for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
-               p2 = *EVAL(p2) = p2 + size2;
-               if (cmp (f1, f1 + size, context) > 0)
-                       swap_wb(f1, f1 + size);
-       }
-#endif /* NATURAL */
-}
-
-/*
- * This is to avoid out-of-bounds addresses in sorting the
- * last 4 elements.
- */
-static void
-insertionsort_wb(u_char *a, size_t n, size_t size, CFComparisonResult (*cmp)(const void *, const void *, void *), void *context)
-{
-       u_char *ai, *s, *t, *u, tmp;
-       long i;
-
-       for (ai = a+size; --n >= 1; ai += size)
-               for (t = ai; t > a; t -= size) {
-                       u = t - size;
-                       if (cmp(u, t, context) <= 0)
-                               break;
-                       swap(u, t);
-               }
+    // no swapping or modification of the original list has occurred until this point
+    objc_memmove_collectable(list, store, count * elementSize);
+    free(store);
+    free(indexes);
 }
 
+/* Comparator is passed the address of the values. */
 void CFMergeSortArray(void *list, CFIndex count, CFIndex elementSize, CFComparatorFunction comparator, void *context) {
-    if (CF_USING_COLLECTABLE_MEMORY && (auto_zone_get_layout_type(__CFCollectableZone, list) & AUTO_UNSCANNED) == 0)
-        bsd_mergesort_wb(list, count, elementSize, comparator, context);
-    else
-        bsd_mergesort(list, count, elementSize, comparator, context);
-} 
-
-#undef NATURAL
-#undef THRESHOLD
-#undef ISIZE
-#undef PSIZE
-#undef ICOPY_LIST
-#undef ICOPY_ELT
-#undef CCOPY_LIST
-#undef CCOPY_ELT
-#undef EVAL
-#undef swap
-#undef reverse
-
-/* ===================================================================== */
+    if (count < 1 || elementSize < 1) return;
+    CFIndex *indexes = CFSortIndexes(count, kCFSortStable, ^(CFIndex a, CFIndex b) { return comparator((char *)list + a * elementSize, (char *)list + b * elementSize, context); }); // naturally stable
+    void *store = malloc(count * elementSize);
+    for (CFIndex idx = 0; idx < count; idx++) {
+        if (sizeof(uintptr_t) == elementSize) {
+            uintptr_t *a = (uintptr_t *)list + indexes[idx];
+            uintptr_t *b = (uintptr_t *)store + idx;
+            *b = *a;
+        } else {
+            memmove((char *)store + idx * elementSize, (char *)list + indexes[idx] * elementSize, elementSize);
+        }
+    }
+    // no swapping or modification of the original list has occurred until this point
+    objc_memmove_collectable(list, store, count * elementSize);
+    free(store);
+    free(indexes);
+}
 
-#undef EINVAL
 
index ca96f9ad352fc8cd2693acc6b0691581e976007e..9257059105d74a2e63e688a82cb1cfa80153a6b2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStorage.c
-       Copyright 1999-2007, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Ali Ozer
 */
 
@@ -55,7 +55,7 @@ CFStorage is thread-safe for multiple readers, but not thread safe for simultane
 #endif
 #endif
 
-#define COPYMEM(src,dst,n) CF_WRITE_BARRIER_MEMMOVE((dst), (src), (n))
+#define COPYMEM(src,dst,n) objc_memmove_collectable((dst), (src), (n))
 #define PAGE_LIMIT ((CFIndex)PAGE_SIZE / 2)
 
 CF_INLINE int32_t roundToPage(int32_t num) {
@@ -113,7 +113,7 @@ struct __CFStorage {
 */
 static void __CFStorageAllocLeafNodeMemoryAux(CFAllocatorRef allocator, CFStorageRef storage, CFStorageNode *node, CFIndex cap) {
     __CFSpinLock(&(storage->cacheReaderMemoryAllocationLock));
-    CF_WRITE_BARRIER_ASSIGN(allocator, node->info.leaf.memory, _CFAllocatorReallocateGC(allocator, node->info.leaf.memory, cap, storage->nodeHint));   // This will free...
+    __CFAssignWithWriteBarrier((void **)&node->info.leaf.memory, _CFAllocatorReallocateGC(allocator, node->info.leaf.memory, cap, storage->nodeHint)); // This will free...
     if (__CFOASafe) __CFSetLastAllocationEventName(node->info.leaf.memory, "CFStorage (node bytes)");
     node->info.leaf.capacityInBytes = cap;
     __CFSpinUnlock(&(storage->cacheReaderMemoryAllocationLock));
@@ -273,8 +273,9 @@ CF_INLINE void *__CFStorageGetValueAtIndex(CFStorageRef storage, CFIndex idx, CF
     return result;
 }
 
+// returns refcount==1 node under GC
 static CFStorageNode *__CFStorageCreateNode(CFAllocatorRef allocator, bool isLeaf, CFIndex numBytes) {
-    CFStorageNode *newNode = (CFStorageNode *)_CFAllocatorAllocateGC(allocator, sizeof(CFStorageNode), __kCFAllocatorGCScannedMemory);
+    CFStorageNode *newNode = (CFStorageNode *)CFAllocatorAllocate(allocator, sizeof(CFStorageNode), __kCFAllocatorGCScannedMemory);
     if (__CFOASafe) __CFSetLastAllocationEventName(newNode, "CFStorage (node)");
     newNode->isLeaf = isLeaf;
     newNode->numBytes = numBytes;
@@ -335,7 +336,7 @@ static void __CFStorageDelete(CFAllocatorRef allocator, CFStorageRef storage, CF
                 int cnt;
                 _CFAllocatorDeallocateGC(allocator, node->info.notLeaf.child[childNum]);
                 for (cnt = childNum; cnt < 2; cnt++) {
-                    CF_WRITE_BARRIER_ASSIGN(allocator, node->info.notLeaf.child[cnt], node->info.notLeaf.child[cnt+1]);
+                    __CFAssignWithWriteBarrier((void **)&node->info.notLeaf.child[cnt], node->info.notLeaf.child[cnt+1]);
                 }
                 node->info.notLeaf.child[2] = NULL;
             }
@@ -387,11 +388,13 @@ static void __CFStorageDelete(CFAllocatorRef allocator, CFStorageRef storage, CF
                 if (sCnt) {
                     if (!node->info.notLeaf.child[cCnt]) {
                         CFStorageNode *newNode = __CFStorageCreateNode(allocator, false, 0);
-                        CF_WRITE_BARRIER_ASSIGN(allocator, node->info.notLeaf.child[cCnt], newNode);
+                        __CFAssignWithWriteBarrier((void **)&node->info.notLeaf.child[cCnt], newNode);
+                        Boolean GC = CF_IS_COLLECTABLE_ALLOCATOR(allocator);
+                        if (GC) auto_zone_release(auto_zone(), newNode);
                     }
                     for (cnt = 0; cnt < sCnt; cnt++) {
                         node->info.notLeaf.child[cCnt]->numBytes += gChildren[gCnt]->numBytes;
-                        CF_WRITE_BARRIER_ASSIGN(allocator, node->info.notLeaf.child[cCnt]->info.notLeaf.child[cnt], gChildren[gCnt++]);
+                        __CFAssignWithWriteBarrier((void **)&node->info.notLeaf.child[cCnt]->info.notLeaf.child[cnt], gChildren[gCnt++]);
                     }
                 } else {
                     if (node->info.notLeaf.child[cCnt]) {
@@ -407,6 +410,7 @@ static void __CFStorageDelete(CFAllocatorRef allocator, CFStorageRef storage, CF
 
 /* Returns NULL or additional node to come after this node
    Assumption: size is never > storage->maxLeafCapacity
+   Under GC node has a retain count to keep it alive in unregistered pthreads
 */
 static CFStorageNode *__CFStorageInsert(CFAllocatorRef allocator, CFStorageRef storage, CFStorageNode *node, CFIndex byteNum, CFIndex size, CFIndex absoluteByteNum) {
     if (node->isLeaf) {
@@ -417,7 +421,7 @@ static CFStorageNode *__CFStorageInsert(CFAllocatorRef allocator, CFStorageRef s
                 return newNode;
             } else if (byteNum == 0) { // Inserting at front; also easy, but we need to swap node and newNode
                 CFStorageNode *newNode = __CFStorageCreateNode(allocator, true, 0);
-                CF_WRITE_BARRIER_MEMMOVE(newNode, node, sizeof(CFStorageNode));
+                objc_memmove_collectable(newNode, node, sizeof(CFStorageNode));
                 node->isLeaf = true;
                 node->numBytes = size;
                 node->info.leaf.capacityInBytes = 0;
@@ -463,26 +467,31 @@ static CFStorageNode *__CFStorageInsert(CFAllocatorRef allocator, CFStorageRef s
         newNode = __CFStorageInsert(allocator, storage, node->info.notLeaf.child[childNum], relativeByteNum, size, absoluteByteNum);
         if (newNode) {
             if (node->info.notLeaf.child[2] == NULL) { // There's an empty slot for the new node, cool
-                if (childNum == 0) CF_WRITE_BARRIER_ASSIGN(allocator, node->info.notLeaf.child[2], node->info.notLeaf.child[1]);       // Make room
-                CF_WRITE_BARRIER_ASSIGN(allocator, node->info.notLeaf.child[childNum + 1], newNode);
+                if (childNum == 0) __CFAssignWithWriteBarrier((void **)&node->info.notLeaf.child[2], node->info.notLeaf.child[1]);     // Make room
+                __CFAssignWithWriteBarrier((void **)&node->info.notLeaf.child[childNum + 1], newNode);
+                Boolean GC = CF_IS_COLLECTABLE_ALLOCATOR(allocator);
+                if (GC) auto_zone_release(auto_zone(), newNode);
                 node->numBytes += size;
                 return NULL;
             } else {
                 CFStorageNode *anotherNode = __CFStorageCreateNode(allocator, false, 0);       // Create another node
                 if (childNum == 0) {   // Last two children go to new node
-                    CF_WRITE_BARRIER_ASSIGN(allocator, anotherNode->info.notLeaf.child[0], node->info.notLeaf.child[1]);
-                    CF_WRITE_BARRIER_ASSIGN(allocator, anotherNode->info.notLeaf.child[1], node->info.notLeaf.child[2]);
-                    CF_WRITE_BARRIER_ASSIGN(allocator, node->info.notLeaf.child[1], newNode);
+                    __CFAssignWithWriteBarrier((void **)&anotherNode->info.notLeaf.child[0], node->info.notLeaf.child[1]);
+                    __CFAssignWithWriteBarrier((void **)&anotherNode->info.notLeaf.child[1], node->info.notLeaf.child[2]);
+                    __CFAssignWithWriteBarrier((void **)&node->info.notLeaf.child[1], newNode);
                     node->info.notLeaf.child[2] = NULL;
                 } else if (childNum == 1) {    // Last child goes to new node
-                    CF_WRITE_BARRIER_ASSIGN(allocator, anotherNode->info.notLeaf.child[0], newNode);
-                    CF_WRITE_BARRIER_ASSIGN(allocator, anotherNode->info.notLeaf.child[1], node->info.notLeaf.child[2]);
+                    __CFAssignWithWriteBarrier((void **)&anotherNode->info.notLeaf.child[0], newNode);
+                    __CFAssignWithWriteBarrier((void **)&anotherNode->info.notLeaf.child[1], node->info.notLeaf.child[2]);
                     node->info.notLeaf.child[2] = NULL;
                 } else {       // New node contains the new comers...
-                    CF_WRITE_BARRIER_ASSIGN(allocator, anotherNode->info.notLeaf.child[0], node->info.notLeaf.child[2]);
-                    CF_WRITE_BARRIER_ASSIGN(allocator, anotherNode->info.notLeaf.child[1], newNode);
+                    __CFAssignWithWriteBarrier((void **)&anotherNode->info.notLeaf.child[0], node->info.notLeaf.child[2]);
+                    __CFAssignWithWriteBarrier((void **)&anotherNode->info.notLeaf.child[1], newNode);
                     node->info.notLeaf.child[2] = NULL;
                 }
+                if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+                    auto_zone_release(auto_zone(), newNode);
+                }
                 node->numBytes = node->info.notLeaf.child[0]->numBytes + node->info.notLeaf.child[1]->numBytes;
                 anotherNode->numBytes = anotherNode->info.notLeaf.child[0]->numBytes + anotherNode->info.notLeaf.child[1]->numBytes;
                 return anotherNode;
@@ -658,17 +667,21 @@ void CFStorageInsertValues(CFStorageRef storage, CFRange range) {
         newNode = __CFStorageInsert(allocator, storage, &storage->rootNode, byteNum, insertThisTime, byteNum);
         if (newNode) {
             CFStorageNode *tempRootNode = __CFStorageCreateNode(allocator, false, 0);  // Will copy the (static) rootNode over to this
-            CF_WRITE_BARRIER_MEMMOVE(tempRootNode, &storage->rootNode, sizeof(CFStorageNode));
+            objc_memmove_collectable(tempRootNode, &storage->rootNode, sizeof(CFStorageNode));
             storage->rootNode.isLeaf = false;
-            CF_WRITE_BARRIER_BASE_ASSIGN(allocator, storage, storage->rootNode.info.notLeaf.child[0], tempRootNode);
-            CF_WRITE_BARRIER_BASE_ASSIGN(allocator, storage, storage->rootNode.info.notLeaf.child[1], newNode);
+            __CFAssignWithWriteBarrier((void **)&storage->rootNode.info.notLeaf.child[0], tempRootNode);
+            __CFAssignWithWriteBarrier((void **)&storage->rootNode.info.notLeaf.child[1], newNode);
+            if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+                auto_zone_release(auto_zone(), tempRootNode);
+                auto_zone_release(auto_zone(), newNode);
+            }
             storage->rootNode.info.notLeaf.child[2] = NULL;
             storage->rootNode.numBytes = tempRootNode->numBytes + newNode->numBytes;
 #if 1
            // ???
            __CFStorageSetCache(storage, NULL, 0, 0);
 #else
-            if (storage->cache.cachedNode == &(storage->rootNode)) CF_WRITE_BARRIER_BASE_ASSIGN(allocator, storage, storage->cache.cachedNode, tempRootNode);  // The cache should follow the node
+            if (storage->cache.cachedNode == &(storage->rootNode)) __CFAssignWithWriteBarrier((void **)&storage->cache.cachedNode, tempRootNode);      // The cache should follow the node
 #endif
        }
         numBytesToInsert -= insertThisTime;
@@ -686,7 +699,7 @@ void CFStorageDeleteValues(CFStorageRef storage, CFRange range) {
     __CFStorageDelete(allocator, storage, &storage->rootNode, range, true);
     while (__CFStorageGetNumChildren(&storage->rootNode) == 1) {
         CFStorageNode *child = storage->rootNode.info.notLeaf.child[0];        // The single child
-        CF_WRITE_BARRIER_MEMMOVE(&storage->rootNode, child, sizeof(CFStorageNode));
+        objc_memmove_collectable(&storage->rootNode, child, sizeof(CFStorageNode));
         _CFAllocatorDeallocateGC(allocator, child);
     }
     if (__CFStorageGetNumChildren(&storage->rootNode) == 0 && !storage->rootNode.isLeaf) {
@@ -754,20 +767,20 @@ void CFStorageReplaceValues(CFStorageRef storage, CFRange range, const void *val
 
 /* Used by CFArray.c */
 
-static void __CFStorageNodeSetLayoutType(CFStorageNode *node, auto_zone_t *zone, auto_memory_type_t type) {
+static void __CFStorageNodeSetUnscanned(CFStorageNode *node, auto_zone_t *zone) {
     if (node->isLeaf) {
-        auto_zone_set_layout_type(zone, node->info.leaf.memory, type);
+        auto_zone_set_unscanned(zone, node->info.leaf.memory);
     } else {
         CFStorageNode **children = node->info.notLeaf.child;
-        if (children[0]) __CFStorageNodeSetLayoutType(children[0], zone, type);
-        if (children[1]) __CFStorageNodeSetLayoutType(children[1], zone, type);
-        if (children[2]) __CFStorageNodeSetLayoutType(children[2], zone, type);
+        if (children[0]) __CFStorageNodeSetUnscanned(children[0], zone);
+        if (children[1]) __CFStorageNodeSetUnscanned(children[1], zone);
+        if (children[2]) __CFStorageNodeSetUnscanned(children[2], zone);
     }
 }
 
 __private_extern__ void _CFStorageSetWeak(CFStorageRef storage) {
     storage->nodeHint = 0;
-    __CFStorageNodeSetLayoutType(&storage->rootNode, __CFCollectableZone, CF_GET_GC_MEMORY_TYPE(storage->nodeHint));
+    __CFStorageNodeSetUnscanned(&storage->rootNode, (auto_zone_t *)auto_zone());
 }
 
 #undef COPYMEM
index 91a369450a7ac40fcf5b44cc08e45792ae10258b..082861426eb4ce5a702f2610716a155b74282eff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStorage.h
-       Copyright (c) 1999-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
 */
 /*!
         @header CFStorage
index c77f57e0377b637b2281218a902364a4e29aad24..75e8d1f5c89e054c6a976fe65e2cacf3e12d36bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStream.c
-       Copyright 2000-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc. All rights reserved.
        Responsibility: Becky Willrich
 */
 
@@ -506,16 +506,29 @@ static void _signalEventSync(struct _CFStream* stream, CFOptionFlags whatToSigna
     CFOptionFlags eventMask;
 
     __CFBitSet(stream->flags, CALLING_CLIENT);
-    
+
+    void* info = NULL;
+    void (*release) (void*) = NULL;
+
+    if (stream->client->cbContext.retain == NULL)
+       info = stream->client->cbContext.info;
+    else {
+       info = stream->client->cbContext.retain(stream->client->cbContext.info);
+       release = stream->client->cbContext.release;
+    }
+
     for (eventMask = 1; eventMask <= whatToSignal; eventMask = eventMask << 1) {
        if ((eventMask & whatToSignal) && (stream->client->when & eventMask)) {
-           stream->client->cb(stream, eventMask, stream->client->cbContext.info);
+           stream->client->cb(stream, eventMask, info);
            
            /* What happens if the callback sets the client to NULL?  We're in a loop here... Hmm. */
            /* After writing that comment, I see: <rdar://problem/6793636> CFReadStreamSetClient(..., NULL) unsafely releases info pointer immediately */
        }
     }
-    
+
+    if (release)
+       (*release) (info);
+
     __CFBitClear(stream->flags, CALLING_CLIENT);
 }
 
@@ -531,7 +544,7 @@ static void _cfstream_solo_signalEventSync(void* info)
     } else {
        struct _CFStream* stream = (struct _CFStream*) info;
        CFOptionFlags whatToSignal = stream->client->whatToSignal;
-        stream->client->whatToSignal = 0;
+       stream->client->whatToSignal = 0;
        
        /* Since the array version holds a retain, we do it here as well, as opposed to taking a second retain in the client callback */
        CFRetain(stream);
@@ -543,53 +556,53 @@ static void _cfstream_solo_signalEventSync(void* info)
 static void _cfstream_shared_signalEventSync(void* info)
 {
     CFTypeID typeID = CFGetTypeID((CFTypeRef) info);
-        
+    
     if (typeID != CFArrayGetTypeID()) {
        CFLog(__kCFLogAssertion, CFSTR("Expected an array for %p"), info);
 #if defined(DEBUG)
        abort();
 #endif
     } else {
-        CFMutableArrayRef list = (CFMutableArrayRef)info;
-        CFIndex c, i;
+       CFMutableArrayRef list = (CFMutableArrayRef) info;
+       CFIndex c, i;
        CFOptionFlags whatToSignal = 0;
        struct _CFStream* stream = NULL;
-
-        __CFSpinLock(&sSourceLock);
-
+       
+       __CFSpinLock(&sSourceLock);
+       
        /* Looks like, we grab the first stream that wants an event... */
        /* Note that I grab an extra retain when I pull out the stream here... */
-        c = CFArrayGetCount(list);
-        for (i = 0; i < c; i++) {
-            struct _CFStream* s = (struct _CFStream*)CFArrayGetValueAtIndex(list, i);
+       c = CFArrayGetCount(list);
+       for (i = 0; i < c; i++) {
+           struct _CFStream* s = (struct _CFStream*)CFArrayGetValueAtIndex(list, i);
            
-            if (s->client->whatToSignal) {
-                stream = s;
+           if (s->client->whatToSignal) {
+               stream = s;
                CFRetain(stream);
-                whatToSignal = stream->client->whatToSignal;
-                s->client->whatToSignal = 0;
-                break;
-            }
-        }
-        
+               whatToSignal = stream->client->whatToSignal;
+               s->client->whatToSignal = 0;
+               break;
+           }
+       }
+       
        /* And then we also signal any other streams in this array so that we get them next go? */
        for (; i < c;  i++) {
-            struct _CFStream* s = (struct _CFStream*)CFArrayGetValueAtIndex(list, i);
-            if (s->client->whatToSignal) {
-                CFRunLoopSourceSignal(s->client->rlSource);
-                break;
-            }
-        }
-
-        __CFSpinUnlock(&sSourceLock);
-
+           struct _CFStream* s = (struct _CFStream*)CFArrayGetValueAtIndex(list, i);
+           if (s->client->whatToSignal) {
+               CFRunLoopSourceSignal(s->client->rlSource);
+               break;
+           }
+       }
+       
+       __CFSpinUnlock(&sSourceLock);
+       
        /* We're sitting here now, possibly with a stream that needs to be processed by the common routine */
        if (stream) {
            _signalEventSync(stream, whatToSignal);
-
+           
            /* Lose our extra retain */
            CFRelease(stream);
-        }
+       }
     }
 }
 
@@ -817,6 +830,9 @@ __private_extern__ Boolean _CFStreamOpen(struct _CFStream *stream) {
             }
             _CFStreamScheduleEvent(stream, kCFStreamEventOpenCompleted);
         } else {
+#if DEPLOYMENT_TARGET_WINDOWS
+            _CFStreamClose(stream);
+#endif
             _CFStreamSetStatusCode(stream, kCFStreamStatusError);
             _CFStreamScheduleEvent(stream, kCFStreamEventErrorOccurred);
         }
@@ -1243,7 +1259,7 @@ __private_extern__ void _CFStreamScheduleWithRunLoop(struct _CFStream *stream, C
     }
     else if (__CFBitIsSet(stream->flags, SHARED_SOURCE)) {
         /* We were sharing, but now we'll get our own source */
-        
+       
         CFArrayRef runLoopAndSourceKey;
         CFMutableArrayRef listOfStreamsSharingASource;
         CFIndex c, i;
@@ -1570,3 +1586,37 @@ CF_EXPORT CFIndex _CFStreamInstanceSize(void) {
     return sizeof(struct _CFStream);
 }
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_WINDOWS
+void __CFStreamCleanup(void) {
+    __CFSpinLock(&sSourceLock);
+    if (sSharedSources) {
+        CFIndex count = CFDictionaryGetCount(sSharedSources);
+        if (count == 0) {
+            // Only release if empty.  If it's still holding streams (which would be a client
+            // bug leak), freeing this dict would free the streams, which then need to access the
+            // dict to remove themselves, which leads to a deadlock.
+            CFRelease(sSharedSources);
+            sSharedSources = NULL;
+        } else {
+            const void ** keys = (const void **)malloc(sizeof(const void *) * count);
+#if defined(DEBUG)
+            int i;
+#endif
+            CFDictionaryGetKeysAndValues(sSharedSources, keys, NULL);
+             fprintf(stderr, "*** CFNetwork is shutting down, but %ld streams are still scheduled.\n", count);
+#if defined(DEBUG)
+            for (i = 0; i < count;i ++) {
+                if ((CFGetTypeID(keys[i]) == __kCFReadStreamTypeID) || (CFGetTypeID(keys[i]) == __kCFWriteStreamTypeID)) {
+                    CFShow(keys[i]);
+                }
+            }
+#endif
+        }
+    }
+    __CFSpinUnlock(&sSourceLock);
+}
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
index 3f294566fcb24c2ad1ef77fbe3bb26d44c3ac964..092ca21fe0ff21ffe7a7326443dd1fd375fa8822 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStream.h
-       Copyright (c) 2000-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTREAM__)
index b36fe110bebd99d1d7bb93f9d80d8f01f993adca..20ff34ea5df2bafcb1139338aa0b4d7671711f6a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStreamAbstract.h
-       Copyright (c) 2000-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTREAMABSTRACT__)
index ec9266177887ea144cfb2d10231c5447bc5d387f..279bf3dd095e63ae6998d7b3aa9bbe2d3f804924 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
index 79f2c6558eacb044fb2bd3aed1615603ebdd0afb..4a8ccf128dc0b6709e9286c2c40306c87a895ed2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStreamPriv.h
-       Copyright (c) 2000-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTREAMPRIV__)
@@ -171,11 +171,11 @@ CFWriteStreamRef _CFWriteStreamCreateFromFileDescriptor(CFAllocatorRef alloc, in
 #define SECURITY_SSLv32 (3)
 #define SECURITY_TLS    (4)    
 
-#if defined (__MACH__)
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
 // This symbol is exported from CFNetwork (see CFSocketStream.i).  Only __MACH__ systems will
 // get this symbol from CoreFoundation.
 extern const int kCFStreamErrorDomainSSL;
-#endif //__MACH__
+#endif
 
 /*
  * Additional SPI for CFNetwork for select side read buffering
@@ -186,11 +186,13 @@ Boolean __CFSocketGetBytesAvailable(CFSocketRef s, CFIndex* ctBytesAvailable);
 CF_EXPORT
 CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error);
 
-CF_EXPORT
-void __CFSocketSetReadBufferLength(CFSocketRef s, CFIndex length);
+/*
+ * This define can be removed once 6030579 is removed
+ */
+#define CFNETWORK_6030579      1
 
 CF_EXPORT
-void __CFSocketSetReadBufferTimeout(CFSocketRef s, CFTimeInterval timeout);
+void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, CFIndex length);
 
 CF_EXTERN_C_END
 
index a9b5c501c7b93413908b1d719dd3ba17f2237f1b..ce1f36fb23d51c900cf0e1f3249e246e0da6ddd9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFString.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Ali Ozer
         
 !!! For performance reasons, it's important that all functions marked CF_INLINE in this file are inlined.
 #include <CoreFoundation/CFBase.h>
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFDictionary.h>
-#include "CFStringEncodingConverterExt.h"
-#include "CFUniChar.h"
-#include "CFUnicodeDecomposition.h"
-#include "CFUnicodePrecomposition.h"
-#include "CFPriv.h"
+#include <CoreFoundation/CFStringEncodingConverterExt.h>
+#include <CoreFoundation/CFUniChar.h>
+#include <CoreFoundation/CFUnicodeDecomposition.h>
+#include <CoreFoundation/CFUnicodePrecomposition.h>
+#include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
+#include "CFLocaleInternal.h"
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 #include <unistd.h>
 #endif
+#if DEPLOYMENT_TARGET_WINDOWS
+#define strncasecmp_l(a, b, c, d) _strnicmp(a, b, c)
+#endif
 
 #if defined(__GNUC__)
 #define LONG_DOUBLE_SUPPORT 1
@@ -58,8 +62,7 @@
 #define INSTRUMENT_SHARED_STRINGS 0
 #endif
 
-
-__private_extern__ CFStringRef __kCFLocaleCollatorID;
+__private_extern__ const CFStringRef __kCFLocaleCollatorID;
 
 #if INSTRUMENT_SHARED_STRINGS
 #include <sys/stat.h> /* for umask() */
@@ -77,7 +80,7 @@ static void __CFRecordStringAllocationEvent(const char *encoding, const char *by
        if (! name) name = "UNKNOWN";
        umask(0);
        char path[1024];
-       sprintf(path, "/tmp/CFSharedStringInstrumentation_%s_%d.txt", name, getpid());
+       snprintf(path, sizeof(path), "/tmp/CFSharedStringInstrumentation_%s_%d.txt", name, getpid());
        fd = open(path, O_WRONLY | O_APPEND | O_CREAT, 0666);
        if (fd <= 0) {
            int error = errno;
@@ -88,7 +91,7 @@ static void __CFRecordStringAllocationEvent(const char *encoding, const char *by
     if (fd > 0) {
        char *buffer = NULL;
        char formatString[256];
-       sprintf(formatString, "%%-8d\t%%-16s\t%%.%lds\n", byteCount);
+       snprintf(formatString, sizeof(formatString), "%%-8d\t%%-16s\t%%.%lds\n", byteCount);
        int resultCount = asprintf(&buffer, formatString, getpid(), encoding, bytes);
        if (buffer && resultCount > 0) write(fd, buffer, resultCount);
        else puts("Couldn't record allocation event");
@@ -102,7 +105,7 @@ static void __CFRecordStringAllocationEvent(const char *encoding, const char *by
 
 typedef Boolean (*UNI_CHAR_FUNC)(UInt32 flags, UInt8 ch, UniChar *unicodeChar);
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 extern size_t malloc_good_size(size_t size);
 #endif
 extern void __CFStrConvertBytesToUnicode(const uint8_t *bytes, UniChar *buffer, CFIndex numChars);
@@ -333,7 +336,7 @@ Boolean __CFStringIsEightBit(CFStringRef str) {
 */
 CF_INLINE void __CFStrSetContentPtr(CFStringRef str, const void *p) {
     // XXX_PCB catch all writes for mutable string case.
-    CF_WRITE_BARRIER_BASE_ASSIGN(__CFGetAllocator(str), str, ((CFMutableStringRef)str)->variants.notInlineImmutable1.buffer, (void *)p);
+    __CFAssignWithWriteBarrier((void **)&((CFMutableStringRef)str)->variants.notInlineImmutable1.buffer, (void *)p);
 }
 CF_INLINE void __CFStrSetInfoBits(CFStringRef str, UInt32 v)           {__CFBitfieldSetValue(((CFMutableStringRef)str)->base._cfinfo[CF_INFO_BITS], 6, 0, v);}
 
@@ -385,7 +388,7 @@ static void __CFStrDeallocateMutableContents(CFMutableStringRef str, void *buffe
     CFAllocatorRef alloc = (__CFStrHasContentsAllocator(str)) ? __CFStrContentsAllocator(str) : __CFGetAllocator(str);
     if (CF_IS_COLLECTABLE_ALLOCATOR(alloc)) {
         // GC:  for finalization safety, let collector reclaim the buffer in the next GC cycle.
-        auto_zone_release(__CFCollectableZone, buffer);
+        auto_zone_release(auto_zone(), buffer);
     } else {
         CFAllocatorDeallocate(alloc, buffer);
     }
@@ -411,24 +414,22 @@ static CFStringEncoding __CFDefaultSystemEncoding = kCFStringEncodingInvalidId;
 static CFStringEncoding __CFDefaultFileSystemEncoding = kCFStringEncodingInvalidId;
 CFStringEncoding __CFDefaultEightBitStringEncoding = kCFStringEncodingInvalidId;
 
-CFStringEncoding CFStringGetSystemEncoding(void) {
 
-    if (__CFDefaultSystemEncoding == kCFStringEncodingInvalidId) {
-        const CFStringEncodingConverter *converter = NULL;
-#if DEPLOYMENT_TARGET_MACOSX
-            __CFDefaultSystemEncoding = kCFStringEncodingMacRoman; // MacRoman is built-in so always available
-#elif defined(__WIN32__)
-            __CFDefaultSystemEncoding = kCFStringEncodingWindowsLatin1; // WinLatin1 is built-in so always available
-#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
-            __CFDefaultSystemEncoding = kCFStringEncodingISOLatin1; // a reasonable default
-#else // Solaris && HP-UX ?
-            __CFDefaultSystemEncoding = kCFStringEncodingISOLatin1; // a reasonable default
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#define __defaultEncoding kCFStringEncodingMacRoman
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define __defaultEncoding kCFStringEncodingWindowsLatin1
+#else
+#warning This value must match __CFGetConverter condition in CFStringEncodingConverter.c
+#define __defaultEncoding kCFStringEncodingISOLatin1
 #endif
-            converter = CFStringEncodingGetConverter(__CFDefaultSystemEncoding);
 
-               __CFSetCharToUniCharFunc(converter->encodingClass == kCFStringEncodingConverterCheapEightBit ? (UNI_CHAR_FUNC)converter->toUnicode : NULL);
+CFStringEncoding CFStringGetSystemEncoding(void) {
+    if (__CFDefaultSystemEncoding == kCFStringEncodingInvalidId) {
+        __CFDefaultSystemEncoding = __defaultEncoding; 
+        const CFStringEncodingConverter *converter = CFStringEncodingGetConverter(__CFDefaultSystemEncoding);
+        __CFSetCharToUniCharFunc(converter->encodingClass == kCFStringEncodingConverterCheapEightBit ? (UNI_CHAR_FUNC)converter->toUnicode : NULL);
     }
-
     return __CFDefaultSystemEncoding;
 }
 
@@ -441,7 +442,7 @@ CF_INLINE CFStringEncoding __CFStringGetSystemEncoding(void) {
 
 CFStringEncoding CFStringFileSystemEncoding(void) {
     if (__CFDefaultFileSystemEncoding == kCFStringEncodingInvalidId) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
         __CFDefaultFileSystemEncoding = kCFStringEncodingUTF8;
 #else
         __CFDefaultFileSystemEncoding = CFStringGetSystemEncoding();
@@ -452,21 +453,26 @@ CFStringEncoding CFStringFileSystemEncoding(void) {
 }
 
 /* ??? Is returning length when no other answer is available the right thing?
+   !!! All of the (length > (LONG_MAX / N)) type checks are to avoid wrap-around and eventual malloc overflow in the client
 */
 CFIndex CFStringGetMaximumSizeForEncoding(CFIndex length, CFStringEncoding encoding) {
     if (encoding == kCFStringEncodingUTF8) {
-        return _CFExecutableLinkedOnOrAfter(CFSystemVersionPanther) ? (length * 3) : (length * 6); // 1 Unichar could expand to 3 bytes; we return 6 for older apps for compatibility
+        if (_CFExecutableLinkedOnOrAfter(CFSystemVersionPanther)) {     // 1 Unichar can expand to 3 bytes; we return 6 for older apps for compatibility
+            return (length > (LONG_MAX / 3)) ? kCFNotFound : (length * 3);
+        } else {
+            return (length > (LONG_MAX / 6)) ? kCFNotFound : (length * 6);
+        }
     } else if ((encoding == kCFStringEncodingUTF32) || (encoding == kCFStringEncodingUTF32BE) || (encoding == kCFStringEncodingUTF32LE)) { // UTF-32
-        return length * sizeof(UTF32Char);
+        return (length > (LONG_MAX / sizeof(UTF32Char))) ? kCFNotFound : (length * sizeof(UTF32Char));
     } else {
         encoding &= 0xFFF; // Mask off non-base part
     }
     switch (encoding) {
         case kCFStringEncodingUnicode:
-            return length * sizeof(UniChar);
+            return (length > (LONG_MAX / sizeof(UniChar))) ? kCFNotFound : (length * sizeof(UniChar));
 
         case kCFStringEncodingNonLossyASCII:
-            return length * 6; // 1 Unichar could expand to 6 bytes
+            return (length > (LONG_MAX / 6)) ? kCFNotFound : (length * 6);      // 1 Unichar can expand to 6 bytes
 
         case kCFStringEncodingMacRoman:
         case kCFStringEncodingWindowsLatin1:
@@ -529,7 +535,9 @@ CF_INLINE Boolean __CFBytesInASCII(const uint8_t *bytes, CFIndex len) {
 /* Returns whether the provided 8-bit string in the specified encoding can be stored in an 8-bit CFString. 
 */
 CF_INLINE Boolean __CFCanUseEightBitCFStringForBytes(const uint8_t *bytes, CFIndex len, CFStringEncoding encoding) {
-    if (encoding == __CFStringGetEightBitStringEncoding()) return true;
+    // If the encoding is the same as the 8-bit CFString encoding, we can just use the bytes as-is.
+    // One exception is ASCII, which unfortunately needs to mean ISOLatin1 for compatibility reasons <rdar://problem/5458321>.
+    if (encoding == __CFStringGetEightBitStringEncoding() && encoding != kCFStringEncodingASCII) return true;
     if (__CFStringEncodingIsSupersetOfASCII(encoding) && __CFBytesInASCII(bytes, len)) return true;
     return false;
 }
@@ -553,7 +561,7 @@ CF_INLINE Boolean __CFCanUseLengthByte(CFIndex len) {
 #define __CFAssertIfFixedLengthIsOK(cf, reqLen) CFAssert2(!__CFStrIsFixed(cf) || (reqLen <= __CFStrDesiredCapacity(cf)), __kCFLogAssertion, "%s(): length %d too large", __PRETTY_FUNCTION__, reqLen)
 
 
-/* Basic algorithm is to shrink memory when capacity is SHRINKFACTOR times the required capacity or to allocate memory when the capacity is less than GROWFACTOR times the required capacity.
+/* Basic algorithm is to shrink memory when capacity is SHRINKFACTOR times the required capacity or to allocate memory when the capacity is less than GROWFACTOR times the required capacity.  This function will return -1 if the new capacity is just too big (> LONG_MAX).
 Additional complications are applied in the following order:
 - desiredCapacity, which is the minimum (except initially things can be at zero)
 - rounding up to factor of 8
@@ -568,27 +576,28 @@ Additional complications are applied in the following order:
 #define GROWFACTOR(c) (((c) >= (ULONG_MAX / 3UL)) ? __CFMax(LONG_MAX - 4095, (c)) : (((unsigned long)c * 3 + 1) / 2))
 #endif
 
-CF_INLINE CFIndex __CFStrNewCapacity(CFMutableStringRef str, CFIndex reqCapacity, CFIndex capacity, Boolean leaveExtraRoom, CFIndex charSize) {
+CF_INLINE CFIndex __CFStrNewCapacity(CFMutableStringRef str, unsigned long reqCapacity, CFIndex capacity, Boolean leaveExtraRoom, CFIndex charSize) {
     if (capacity != 0 || reqCapacity != 0) {   /* If initially zero, and space not needed, leave it at that... */
         if ((capacity < reqCapacity) ||                /* We definitely need the room... */
             (!__CFStrCapacityProvidedExternally(str) &&        /* Assuming we control the capacity... */
                ((reqCapacity < SHRINKFACTOR(capacity)) ||              /* ...we have too much room! */
                  (!leaveExtraRoom && (reqCapacity < capacity))))) {    /* ...we need to eliminate the extra space... */
-            CFIndex newCapacity = leaveExtraRoom ? GROWFACTOR(reqCapacity) : reqCapacity;      /* Grow by 3/2 if extra room is desired */
+           if (reqCapacity > LONG_MAX) return -1;  /* Too big any way you cut it */
+            unsigned long newCapacity = leaveExtraRoom ? GROWFACTOR(reqCapacity) : reqCapacity;        /* Grow by 3/2 if extra room is desired */
            CFIndex desiredCapacity = __CFStrDesiredCapacity(str) * charSize;
             if (newCapacity < desiredCapacity) {       /* If less than desired, bump up to desired */
                 newCapacity = desiredCapacity;
             } else if (__CFStrIsFixed(str)) {          /* Otherwise, if fixed, no need to go above the desired (fixed) capacity */
                 newCapacity = __CFMax(desiredCapacity, reqCapacity);   /* !!! So, fixed is not really fixed, but "tight" */
             }
-           if (__CFStrHasContentsAllocator(str)) {     /* Also apply any preferred size from the allocator; should we do something for  */
+           if (__CFStrHasContentsAllocator(str)) {     /* Also apply any preferred size from the allocator  */
                 newCapacity = CFAllocatorGetPreferredSizeForSize(__CFStrContentsAllocator(str), newCapacity, 0);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
             } else {
                 newCapacity = malloc_good_size(newCapacity);
 #endif
             }
-            return newCapacity; // If packing: __CFStrUnpackNumber(__CFStrPackNumber(newCapacity));
+            return (newCapacity > LONG_MAX) ? -1 : (CFIndex)newCapacity; // If packing: __CFStrUnpackNumber(__CFStrPackNumber(newCapacity));
         }
     }
     return capacity;
@@ -744,8 +753,7 @@ static void copyBlocks(
 */
 static void __CFStringHandleOutOfMemory(CFTypeRef obj) {
     CFStringRef msg = CFSTR("Out of memory. We suggest restarting the application. If you have an unsaved document, create a backup copy in Finder, then try to save.");
-    CFBadErrorCallBack cb = _CFGetOutOfMemoryErrorCallBack();
-    if (NULL == cb || !cb(obj, CFSTR("NS/CFString"), msg)) {
+    {
        CFLog(kCFLogLevelCritical, CFSTR("%@"), msg);
     }
 }
@@ -755,7 +763,7 @@ static void __CFStringHandleOutOfMemory(CFTypeRef obj) {
 static void __CFStringChangeSizeMultiple(CFMutableStringRef str, const CFRange *deleteRanges, CFIndex numDeleteRanges, CFIndex insertLength, Boolean makeUnicode) {
     const uint8_t *curContents = (uint8_t *)__CFStrContents(str);
     CFIndex curLength = curContents ? __CFStrLength2(str, curContents) : 0;
-    CFIndex newLength;
+    unsigned long newLength;   // We use unsigned to better keep track of overflow
     
     // Compute new length of the string
     if (numDeleteRanges == 1) {
@@ -803,19 +811,19 @@ static void __CFStringChangeSizeMultiple(CFMutableStringRef str, const CFRange *
         Boolean useLengthAndNullBytes = !newIsUnicode /* && (newLength > 0) - implicit */;
         CFIndex numExtraBytes = useLengthAndNullBytes ? 2 : 0; /* 2 extra bytes to keep the length byte & null... */
         CFIndex curCapacity = __CFStrCapacity(str);
+       if (newLength > (LONG_MAX - numExtraBytes) / newCharSize) __CFStringHandleOutOfMemory(str);     // Does not return
         CFIndex newCapacity = __CFStrNewCapacity(str, newLength * newCharSize + numExtraBytes, curCapacity, true, newCharSize);
+       if (newCapacity == -1) __CFStringHandleOutOfMemory(str);        // Does not return
         Boolean allocNewBuffer = (newCapacity != curCapacity) || (curLength > 0 && !oldIsUnicode && newIsUnicode);     /* We alloc new buffer if oldIsUnicode != newIsUnicode because the contents have to be copied */
        uint8_t *newContents;
        if (allocNewBuffer) {
            newContents = (uint8_t *)__CFStrAllocateMutableContents(str, newCapacity);
            if (!newContents) {     // Try allocating without extra room
                newCapacity = __CFStrNewCapacity(str, newLength * newCharSize + numExtraBytes, curCapacity, false, newCharSize);
+               // Since we checked for this above, it shouldn't be the case here, but just in case
+               if (newCapacity == -1) __CFStringHandleOutOfMemory(str);    // Does not return
                newContents = (uint8_t *)__CFStrAllocateMutableContents(str, newCapacity);
-               if (!newContents) {
-                   __CFStringHandleOutOfMemory(str);
-                   // Ideally control doesn't come here at all since we expect the above call to raise an exception.
-                   // If control comes here, there isn't much we can do.
-               }
+               if (!newContents) __CFStringHandleOutOfMemory(str);         // Does not return
            }
        } else {
            newContents = (uint8_t *)curContents;
@@ -1186,7 +1194,7 @@ __private_extern__ CFStringRef __CFStringCreateImmutableFunnel3(
     else if (encoding == kCFStringEncodingUTF8) recordedEncoding = "UTF8";
     else if (encoding == kCFStringEncodingMacRoman) recordedEncoding = "MacRoman";
     else {
-       sprintf(encodingBuffer, "0x%lX", (unsigned long)encoding);
+       snprintf(encodingBuffer, sizeof(encodingBuffer), "0x%lX", (unsigned long)encoding);
        recordedEncoding = encodingBuffer;
     }
 #endif
@@ -1326,8 +1334,9 @@ __private_extern__ CFStringRef __CFStringCreateImmutableFunnel3(
     }
 
     // Now determine the necessary size
-    
+#if INSTRUMENT_SHARED_STRINGS || USE_STRING_ROM
     Boolean stringSupportsROM = stringSupportsEightBitCFRepresentation;
+#endif
 
 #if INSTRUMENT_SHARED_STRINGS
     if (stringSupportsROM) {
@@ -1344,7 +1353,7 @@ __private_extern__ CFStringRef __CFStringCreateImmutableFunnel3(
     if (stringSupportsROM) {
         // Disable the string ROM if necessary
        static char sDisableStringROM = -1;
-       if (sDisableStringROM == -1) sDisableStringROM = !! getenv("CFStringDisableROM");
+       if (sDisableStringROM == -1) sDisableStringROM = !! __CFgetenv("CFStringDisableROM");
 
        if (sDisableStringROM == 0) romResult = _CFSearchStringROM(bytes + !! hasLengthByte, numBytes - !! hasLengthByte);
     }
@@ -1695,7 +1704,7 @@ static Boolean __CFStrIsConstantString(CFStringRef str) {
 #endif
 
 
-#if 0
+#if DEPLOYMENT_TARGET_WINDOWS
 void __CFStringCleanup (void) {
     /* in case library is unloaded, release store for the constant string table */
     if (constantStringTable != NULL) {
@@ -1706,6 +1715,7 @@ void __CFStringCleanup (void) {
 #else 
         CFRelease(constantStringTable);
 #endif
+        constantStringTable = NULL;
     }
 }
 #endif
@@ -1966,6 +1976,19 @@ const char * CFStringGetCStringPtr(CFStringRef str, CFStringEncoding encoding) {
     if (__CFStrHasNullByte(str)) {
         // Note: this is called a lot, 27000 times to open a small xcode project with one file open.
         // Of these uses about 1500 are for cStrings/utf8strings.
+#if 0
+        // Only sometimes when the stars are aligned will this call return a gc pointer
+        // under GC we can only really return a pointer to the start of a GC buffer for cString use
+        // (Is there a simpler way to ask if contents isGC?)
+        CFAllocatorRef alloc = (__CFStrHasContentsAllocator(str)) ? __CFStrContentsAllocator(str) : __CFGetAllocator(str);
+        if (CF_IS_COLLECTABLE_ALLOCATOR(alloc)) {
+            if (__CFStrSkipAnyLengthByte(str) != 0 || !__CFStrIsMutable(str)) {
+                static int counter = 0;
+                printf("CFString %dth unsafe safe string %s\n", ++counter, __CFStrContents(str) + __CFStrSkipAnyLengthByte(str));
+                return NULL;
+            }
+        }
+#endif
        return (const char *)__CFStrContents(str) + __CFStrSkipAnyLengthByte(str);
     } else {
        return NULL;
@@ -2063,6 +2086,9 @@ Boolean CFStringGetCString(CFStringRef str, char *buffer, CFIndex bufferSize, CF
     }
 }
 
+extern Boolean __CFLocaleGetNullLocale(struct __CFLocale *locale);
+extern void __CFLocaleSetNullLocale(struct __CFLocale *locale);
+
 static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale) {
     CFStringRef collatorID;
     const char *langID = NULL;
@@ -2070,6 +2096,8 @@ static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale) {
     static const char *lastLangID = NULL;
     static CFSpinLock_t lock = CFSpinLockInit;
 
+    if (__CFLocaleGetNullLocale((struct __CFLocale *)locale)) return NULL;
+
     __CFSpinLock(&lock);
     if ((NULL != lastLocale) && (lastLocale == locale)) {
         __CFSpinUnlock(&lock);
@@ -2077,7 +2105,7 @@ static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale) {
     }
     __CFSpinUnlock(&lock);
 
-    collatorID = CFLocaleGetValue(locale, __kCFLocaleCollatorID);
+    collatorID = (CFStringRef)CFLocaleGetValue(locale, __kCFLocaleCollatorID);
 
     // This is somewhat depending on CFLocale implementation always creating CFString for locale identifer ???
     if (__CFStrLength(collatorID) > 1) {
@@ -2104,6 +2132,9 @@ static const char *_CFStrGetLanguageIdentifierForLocale(CFLocaleRef locale) {
         }
     }
 
+    if (langID == NULL) __CFLocaleSetNullLocale((struct __CFLocale *)locale);
+
     __CFSpinLock(&lock);
     lastLocale = locale;
     lastLangID = langID;
@@ -2177,14 +2208,14 @@ static CFIndex __CFStringFoldCharacterClusterAtIndex(UTF32Char character, CFStri
             }
 
             // decompose
-            if (flags & (kCFCompareDiacriticsInsensitiveCompatibilityMask|kCFCompareNonliteral)) {
+            if (flags & (kCFCompareDiacriticInsensitive|kCFCompareNonliteral)) {
                 if (CFUniCharIsMemberOfBitmap(character, ((0 == planeNo) ? decompBMP : CFUniCharGetBitmapPtrForPlane(kCFUniCharCanonicalDecomposableCharacterSet, planeNo)))) {
                     UTF32Char original = character;
 
                     filledLength = CFUniCharDecomposeCharacter(character, outCharacters, maxBufferLength);
                     character = *outCharacters;
 
-                    if ((flags & kCFCompareDiacriticsInsensitiveCompatibilityMask) && (character < 0x0510)) {
+                    if ((flags & kCFCompareDiacriticInsensitive) && (character < 0x0510)) {
                         filledLength = 1; // reset if Roman, Greek, Cyrillic
                     } else if (0 == (flags & kCFCompareNonliteral)) {
                         character = original;
@@ -2196,7 +2227,7 @@ static CFIndex __CFStringFoldCharacterClusterAtIndex(UTF32Char character, CFStri
             // fold case
             if (flags & kCFCompareCaseInsensitive) {
                 const uint8_t *nonBaseBitmap;
-                bool filterNonBase = (((flags & kCFCompareDiacriticsInsensitiveCompatibilityMask) && (character < 0x0510)) ? true : false);
+                bool filterNonBase = (((flags & kCFCompareDiacriticInsensitive) && (character < 0x0510)) ? true : false);
                 static const uint8_t *lowerBMP = NULL;
                 static const uint8_t *caseFoldBMP = NULL;
                 
@@ -2261,10 +2292,10 @@ static CFIndex __CFStringFoldCharacterClusterAtIndex(UTF32Char character, CFStri
         }
 
         // collect following combining marks
-        if (flags & (kCFCompareDiacriticsInsensitiveCompatibilityMask|kCFCompareNonliteral)) {
+        if (flags & (kCFCompareDiacriticInsensitive|kCFCompareNonliteral)) {
             const uint8_t *nonBaseBitmap;
             const uint8_t *decompBitmap;
-            bool doFill = (((flags & kCFCompareDiacriticsInsensitiveCompatibilityMask) && (character < 0x0510)) ? false : true);
+            bool doFill = (((flags & kCFCompareDiacriticInsensitive) && (character < 0x0510)) ? false : true);
 
             if (0 == filledLength) {
                 *outCharacters = character; // filledLength will be updated below on demand
@@ -2284,7 +2315,7 @@ static CFIndex __CFStringFoldCharacterClusterAtIndex(UTF32Char character, CFStri
                     if (CFUniCharIsMemberOfBitmap(nonBaseCharacter, nonBaseBitmap)) {
                         filledLength = 1; // For the base character
                         
-                        if ((0 == (flags & kCFCompareDiacriticsInsensitiveCompatibilityMask)) || (nonBaseCharacter > 0x050F)) {
+                        if ((0 == (flags & kCFCompareDiacriticInsensitive)) || (nonBaseCharacter > 0x050F)) {
                             if (CFUniCharIsMemberOfBitmap(nonBaseCharacter, decompBitmap)) {
                                 filledLength += CFUniCharDecomposeCharacter(nonBaseCharacter, &(outCharacters[filledLength]), maxBufferLength - filledLength);
                             } else {
@@ -2347,9 +2378,27 @@ static CFIndex __CFStringFoldCharacterClusterAtIndex(UTF32Char character, CFStri
     return filledLength;
 }
 
-#define kCFStringStackBufferLength (64)
+static bool __CFStringFillCharacterSetInlineBuffer(CFCharacterSetInlineBuffer *buffer, CFStringCompareFlags compareOptions) {
+    if (0 != (compareOptions & kCFCompareIgnoreNonAlphanumeric)) {
+       static CFCharacterSetRef nonAlnumChars = NULL;
+
+       if (NULL == nonAlnumChars) {
+           CFMutableCharacterSetRef cset = CFCharacterSetCreateMutableCopy(NULL, CFCharacterSetGetPredefined(kCFCharacterSetAlphaNumeric));
+           CFCharacterSetInvert(cset);
+           if (!OSAtomicCompareAndSwapPtrBarrier(NULL, cset, (void **)&nonAlnumChars)) CFRelease(cset);
+       }
+
+       CFCharacterSetInitInlineBuffer(nonAlnumChars, buffer);
+
+       return true;
+    }
+
+    return false;
+}
+
+#define kCFStringStackBufferLength (__kCFStringInlineBufferLength)
 
-CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStringRef string2, CFRange rangeToCompare, CFOptionFlags compareOptions, CFLocaleRef locale) {
+CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStringRef string2, CFRange rangeToCompare, CFStringCompareFlags compareOptions, CFLocaleRef locale) {
     /* No objc dispatch needed here since CFStringInlineBuffer works with both CFString and NSString */
     UTF32Char strBuf1[kCFStringStackBufferLength];
     UTF32Char strBuf2[kCFStringStackBufferLength];
@@ -2357,19 +2406,21 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
     UTF32Char str1Char, str2Char;
     CFIndex str1UsedLen, str2UsedLen;
     CFIndex str1Index = 0, str2Index = 0, strBuf1Index = 0, strBuf2Index = 0, strBuf1Len = 0, strBuf2Len = 0;
+    CFIndex str1LocalizedIndex = 0, str2LocalizedIndex = 0;
+    CFIndex forcedIndex1 = 0, forcedIndex2 = 0;
     CFIndex str2Len = CFStringGetLength(string2);
     bool caseInsensitive = ((compareOptions & kCFCompareCaseInsensitive) ? true : false);
-    bool diacriticsInsensitive = ((compareOptions & kCFCompareDiacriticsInsensitiveCompatibilityMask) ? true : false);
-    bool equalityOptions = ((compareOptions & (kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticsInsensitiveCompatibilityMask|kCFCompareWidthInsensitive)) ? true : false);
+    bool diacriticsInsensitive = ((compareOptions & kCFCompareDiacriticInsensitive) ? true : false);
+    bool equalityOptions = ((compareOptions & (kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive|kCFCompareWidthInsensitive)) ? true : false);
     bool numerically = ((compareOptions & kCFCompareNumerically) ? true : false);
+    bool forceOrdering = ((compareOptions & kCFCompareForcedOrdering) ? true : false);
     const uint8_t *graphemeBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, 0);
     const uint8_t *langCode;
     CFComparisonResult compareResult = kCFCompareEqualTo;
     UTF16Char otherChar;
     Boolean freeLocale = false;
-
-    #define _CFCompareStringsWithLocale(A, B, C, D, E, F) (0)
-    locale = NULL;
+    CFCharacterSetInlineBuffer *ignoredChars = NULL;
+    CFCharacterSetInlineBuffer csetBuffer;
 
     if ((compareOptions & kCFCompareLocalized) && (NULL == locale)) {
         locale = CFLocaleCopyCurrent();
@@ -2378,7 +2429,12 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
 
     langCode = ((NULL == locale) ? NULL : (const uint8_t *)_CFStrGetLanguageIdentifierForLocale(locale));
 
-    if ((NULL == locale) && !numerically) { // could do binary comp (be careful when adding new flags)
+    if (__CFStringFillCharacterSetInlineBuffer(&csetBuffer, compareOptions)) {
+       ignoredChars = &csetBuffer;
+       equalityOptions = true;
+    }
+
+    if ((NULL == locale) && (NULL == ignoredChars) && !numerically) { // could do binary comp (be careful when adding new flags)
         CFStringEncoding eightBitEncoding = __CFStringGetEightBitStringEncoding();
         const uint8_t *str1Bytes = (const uint8_t *)CFStringGetCStringPtr(string, eightBitEncoding);
         const uint8_t *str2Bytes = (const uint8_t *)CFStringGetCStringPtr(string2, eightBitEncoding);
@@ -2387,7 +2443,7 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
         if ((NULL != str1Bytes) && (NULL != str2Bytes)) {
             compareOptions &= ~kCFCompareNonliteral; // remove non-literal
 
-            if (kCFStringEncodingASCII == eightBitEncoding) {
+            if ((kCFStringEncodingASCII == eightBitEncoding) && (false == forceOrdering)) {
                 if (caseInsensitive) {
                     int cmpResult = strncasecmp_l((const char *)str1Bytes + rangeToCompare.location, (const char *)str2Bytes, __CFMin(rangeToCompare.length, str2Len), NULL);
                     
@@ -2406,6 +2462,7 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
 
                     if (str1Char != str2Char) {
                         if ((str1Char < 0x80) && (str2Char < 0x80)) {
+                           if (forceOrdering && (kCFCompareEqualTo == compareResult) && (str1Char != str2Char)) compareResult = ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan);
                             if ((str1Char >= 'A') && (str1Char <= 'Z')) str1Char += ('a' - 'A');
                             if ((str2Char >= 'A') && (str2Char <= 'Z')) str2Char += ('a' - 'A');
 
@@ -2423,7 +2480,7 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
                 if (str1Index == limitLength) {
                     int cmpResult = rangeToCompare.length - str2Len;
                     
-                    return ((0 == cmpResult) ? kCFCompareEqualTo : ((cmpResult < 0) ? kCFCompareLessThan : kCFCompareGreaterThan));
+                    return ((0 == cmpResult) ? compareResult : ((cmpResult < 0) ? kCFCompareLessThan : kCFCompareGreaterThan));
                 }
             }
         } else if (!equalityOptions && (NULL == str1Bytes) && (NULL == str2Bytes)) {
@@ -2457,25 +2514,41 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
     CFStringInitInlineBuffer(string, &inlineBuf1, rangeToCompare);
     CFStringInitInlineBuffer(string2, &inlineBuf2, CFRangeMake(0, str2Len));
 
+    if (NULL != locale) {
+       str1LocalizedIndex = str1Index;
+       str2LocalizedIndex = str2Index;
+
+       // We temporarily disable kCFCompareDiacriticInsensitive for SL <rdar://problem/6767096>. Should be revisited in NMOS <rdar://problem/7003830>
+       if (forceOrdering) {
+           diacriticsInsensitive = false;
+           compareOptions &= ~kCFCompareDiacriticInsensitive;
+       }
+    }
     while ((str1Index < rangeToCompare.length) && (str2Index < str2Len)) {
         if (strBuf1Len == 0) {
             str1Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index);
-            if (caseInsensitive && (str1Char >= 'A') && (str1Char <= 'Z') && ((NULL == langCode) || (str1Char != 'I'))) str1Char += ('a' - 'A');
+            if (caseInsensitive && (str1Char >= 'A') && (str1Char <= 'Z') && ((NULL == langCode) || (str1Char != 'I')) && ((false == forceOrdering) || (kCFCompareEqualTo != compareResult))) str1Char += ('a' - 'A');
             str1UsedLen = 1;
         } else {
             str1Char = strBuf1[strBuf1Index++];
         }
         if (strBuf2Len == 0) {
             str2Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf2, str2Index);
-            if (caseInsensitive && (str2Char >= 'A') && (str2Char <= 'Z') && ((NULL == langCode) || (str2Char != 'I'))) str2Char += ('a' - 'A');
+            if (caseInsensitive && (str2Char >= 'A') && (str2Char <= 'Z') && ((NULL == langCode) || (str2Char != 'I')) && ((false == forceOrdering) || (kCFCompareEqualTo != compareResult))) str2Char += ('a' - 'A');
             str2UsedLen = 1;
         } else {
             str2Char = strBuf2[strBuf2Index++];
         }
-        
+
         if (numerically && ((0 == strBuf1Len) && (str1Char <= '9') && (str1Char >= '0')) && ((0 == strBuf2Len) && (str2Char <= '9') && (str2Char >= '0'))) { // If both are not ASCII digits, then don't do numerical comparison here
             uint64_t intValue1 = 0, intValue2 = 0;     // !!! Doesn't work if numbers are > max uint64_t
 
+            if (forceOrdering && (kCFCompareEqualTo == compareResult) && (str1Char != str2Char)) {
+               compareResult = ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan);
+               forcedIndex1 = str1Index;
+               forcedIndex2 = str2Index;
+           }
+
             do {
                 intValue1 = (intValue1 * 10) + (str1Char - '0');
                 str1Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, ++str1Index);
@@ -2503,22 +2576,26 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
 
         if (str1Char != str2Char) {
             if (!equalityOptions) {
-               CFComparisonResult res = ((NULL == locale) ? ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan) : _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(strBuf1Index, rangeToCompare.length - strBuf1Index), &inlineBuf2, CFRangeMake(strBuf2Index, str2Len - strBuf2Index), compareOptions, locale));
+               compareResult = ((NULL == locale) ? ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan) : _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(str1Index, rangeToCompare.length - str1Index), &inlineBuf2, CFRangeMake(str2Index, str2Len - str2Index), compareOptions, locale));
                 if (freeLocale && locale) {
                     CFRelease(locale);
                 }
-               return res;
+               return compareResult;
            }
 
-            if ((compareOptions & kCFCompareForcedOrdering) && (kCFCompareEqualTo == compareResult)) compareResult = ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan);
+            if (forceOrdering && (kCFCompareEqualTo == compareResult)) {
+               compareResult = ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan);
+               forcedIndex1 = str1LocalizedIndex;
+               forcedIndex2 = str2LocalizedIndex;
+           }
 
-            if ((str1Char < 0x80) && (str2Char < 0x80)) {
+            if ((str1Char < 0x80) && (str2Char < 0x80) && (NULL == ignoredChars)) {
                 if (NULL != locale) {
-                   CFComparisonResult res = _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(strBuf1Index, rangeToCompare.length - strBuf1Index), &inlineBuf2, CFRangeMake(strBuf2Index, str2Len - strBuf2Index), compareOptions, locale);
+                   compareResult = _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(str1Index, rangeToCompare.length - str1Index), &inlineBuf2, CFRangeMake(str2Index, str2Len - str2Index), compareOptions, locale);
                    if (freeLocale && locale) {
                        CFRelease(locale);
                    }
-                   return res;
+                   return compareResult;
                 } else if (!caseInsensitive) {
                    if (freeLocale && locale) {
                        CFRelease(locale);
@@ -2537,6 +2614,21 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
                 str2UsedLen = 2;
             }
             
+           if (NULL != ignoredChars) {
+               if (CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str1Char)) {
+                   if ((strBuf1Len > 0) && (strBuf1Index == strBuf1Len)) strBuf1Len = 0;
+                   if (strBuf1Len == 0) str1Index += str1UsedLen;
+                   if (strBuf2Len > 0) --strBuf2Index;
+                   continue;
+               }
+               if (CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str2Char)) {
+                   if ((strBuf2Len > 0) && (strBuf2Index == strBuf2Len)) strBuf2Len = 0;
+                   if (strBuf2Len == 0) str2Index += str2UsedLen;
+                   if (strBuf1Len > 0) -- strBuf1Index;
+                   continue;
+               }           
+           }
+           
             if (diacriticsInsensitive && (str1Index > 0)) {
                 bool str1Skip = false;
                 bool str2Skip = false;
@@ -2566,11 +2658,11 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
                 }
                 
                 if ((0 == strBuf1Len) && (0 < strBuf2Len)) {
-                   CFComparisonResult res =  ((NULL == locale) ? ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan) : _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(strBuf1Index, rangeToCompare.length - strBuf1Index), &inlineBuf2, CFRangeMake(strBuf2Index, str2Len - strBuf2Index), compareOptions, locale));
+                   compareResult =  ((NULL == locale) ? ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan) : _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(str1LocalizedIndex, rangeToCompare.length - str1LocalizedIndex), &inlineBuf2, CFRangeMake(str2LocalizedIndex, str2Len - str2LocalizedIndex), compareOptions, locale));
                    if (freeLocale && locale) {
                        CFRelease(locale);
                    }
-                   return res;
+                   return compareResult;
                }
                 
                 if ((0 == strBuf2Len) && ((0 == strBuf1Len) || (str1Char != str2Char))) {
@@ -2580,11 +2672,11 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
                         strBuf2Index = 1;
                     }
                     if ((0 == strBuf2Len) || (str1Char != str2Char)) {
-                       CFComparisonResult res = ((NULL == locale) ? ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan) : _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(strBuf1Index, rangeToCompare.length - strBuf1Index), &inlineBuf2, CFRangeMake(strBuf2Index, str2Len - strBuf2Index), compareOptions, locale));
+                       compareResult = ((NULL == locale) ? ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan) : _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(str1LocalizedIndex, rangeToCompare.length - str1LocalizedIndex), &inlineBuf2, CFRangeMake(str2LocalizedIndex, str2Len - str2LocalizedIndex), compareOptions, locale));
                        if (freeLocale && locale) {
                            CFRelease(locale);
                        }
-                       return res;
+                       return compareResult;
                    }
                 }
             }
@@ -2595,7 +2687,7 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
                     ++strBuf1Index; ++strBuf2Index;
                 }
                 if ((strBuf1Index < strBuf1Len) && (strBuf2Index < strBuf2Len)) {
-                   CFComparisonResult res = ((NULL == locale) ? ((str1Char < str2Char) ? kCFCompareLessThan : kCFCompareGreaterThan) : _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(strBuf1Index, rangeToCompare.length - strBuf1Index), &inlineBuf2, CFRangeMake(strBuf2Index, str2Len - strBuf2Index), compareOptions, locale));
+                   CFComparisonResult res = ((NULL == locale) ? ((strBuf1[strBuf1Index] < strBuf2[strBuf2Index]) ? kCFCompareLessThan : kCFCompareGreaterThan) : _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(str1LocalizedIndex, rangeToCompare.length - str1LocalizedIndex), &inlineBuf2, CFRangeMake(str2LocalizedIndex, str2Len - str2LocalizedIndex), compareOptions, locale));
                    if (freeLocale && locale) {
                        CFRelease(locale);
                    }
@@ -2609,31 +2701,37 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
         
         if (strBuf1Len == 0) str1Index += str1UsedLen;
         if (strBuf2Len == 0) str2Index += str2UsedLen;
+       if ((strBuf1Len == 0) && (strBuf2Len == 0)) {
+           str1LocalizedIndex = str1Index;
+           str2LocalizedIndex = str2Index;
+       }
     }
 
-    if (diacriticsInsensitive) {
+    if (diacriticsInsensitive || (NULL != ignoredChars)) {
         while (str1Index < rangeToCompare.length) {
             str1Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index);
-            if (str1Char < 0x80) break; // found ASCII
+            if ((str1Char < 0x80) && (NULL == ignoredChars)) break; // found ASCII
 
             if (CFUniCharIsSurrogateHighCharacter(str1Char) && CFUniCharIsSurrogateLowCharacter((otherChar = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index + 1)))) str1Char = CFUniCharGetLongCharacterForSurrogatePair(str1Char, otherChar);
 
-            if (!CFUniCharIsMemberOfBitmap(str1Char, ((str1Char < 0x10000) ? graphemeBMP : CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, (str1Char >> 16))))) break;
+            if ((!diacriticsInsensitive || !CFUniCharIsMemberOfBitmap(str1Char, ((str1Char < 0x10000) ? graphemeBMP : CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, (str1Char >> 16))))) && ((NULL == ignoredChars) || !CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str1Char))) break;
 
             str1Index += ((str1Char < 0x10000) ? 1 : 2);
         }
 
         while (str2Index < str2Len) {
             str2Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf2, str2Index);
-            if (str2Char < 0x80) break; // found ASCII
+            if ((str2Char < 0x80) && (NULL == ignoredChars)) break; // found ASCII
                 
             if (CFUniCharIsSurrogateHighCharacter(str2Char) && CFUniCharIsSurrogateLowCharacter((otherChar = CFStringGetCharacterFromInlineBuffer(&inlineBuf2, str2Index + 1)))) str2Char = CFUniCharGetLongCharacterForSurrogatePair(str2Char, otherChar);
 
-            if (!CFUniCharIsMemberOfBitmap(str2Char, ((str2Char < 0x10000) ? graphemeBMP : CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, (str2Char >> 16))))) break;
+            if ((!diacriticsInsensitive || !CFUniCharIsMemberOfBitmap(str2Char, ((str2Char < 0x10000) ? graphemeBMP : CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, (str2Char >> 16))))) && ((NULL == ignoredChars) || !CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str2Char))) break;
 
             str2Index += ((str2Char < 0x10000) ? 1 : 2);
         }
     }
+    // Need to recalc localized result here for forced ordering
+    if ((NULL != locale) && (kCFCompareEqualTo != compareResult) && (str1Index == rangeToCompare.length) && (str2Index == str2Len)) compareResult = _CFCompareStringsWithLocale(&inlineBuf1, CFRangeMake(forcedIndex1, rangeToCompare.length - forcedIndex1), &inlineBuf2, CFRangeMake(forcedIndex2, str2Len - forcedIndex2), compareOptions, locale);
 
     if (freeLocale && locale) {
        CFRelease(locale);
@@ -2643,23 +2741,30 @@ CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef string, CFStr
 }
 
 
-CFComparisonResult CFStringCompareWithOptions(CFStringRef string, CFStringRef string2, CFRange rangeToCompare, CFOptionFlags compareOptions) { return CFStringCompareWithOptionsAndLocale(string, string2, rangeToCompare, compareOptions, NULL); }
+CFComparisonResult CFStringCompareWithOptions(CFStringRef string, CFStringRef string2, CFRange rangeToCompare, CFStringCompareFlags compareOptions) { return CFStringCompareWithOptionsAndLocale(string, string2, rangeToCompare, compareOptions, NULL); }
 
 CFComparisonResult CFStringCompare(CFStringRef string, CFStringRef str2, CFOptionFlags options) {
     return CFStringCompareWithOptions(string, str2, CFRangeMake(0, CFStringGetLength(string)), options);
 }
 
-Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringToFind, CFRange rangeToSearch, CFOptionFlags compareOptions, CFLocaleRef locale, CFRange *result)  {
+Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags compareOptions, CFLocaleRef locale, CFRange *result)  {
     /* No objc dispatch needed here since CFStringInlineBuffer works with both CFString and NSString */
     CFIndex findStrLen = CFStringGetLength(stringToFind);
     Boolean didFind = false;
-    bool lengthVariants = ((compareOptions & (kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticsInsensitiveCompatibilityMask)) ? true : false);
+    bool lengthVariants = ((compareOptions & (kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive)) ? true : false);
+    CFCharacterSetInlineBuffer *ignoredChars = NULL;
+    CFCharacterSetInlineBuffer csetBuffer;
+
+    if (__CFStringFillCharacterSetInlineBuffer(&csetBuffer, compareOptions)) {
+       ignoredChars = &csetBuffer;
+       lengthVariants = true;
+    }
 
     if ((findStrLen > 0) && (rangeToSearch.length > 0) && ((findStrLen <= rangeToSearch.length) || lengthVariants)) {
         UTF32Char strBuf1[kCFStringStackBufferLength];
         UTF32Char strBuf2[kCFStringStackBufferLength];
         CFStringInlineBuffer inlineBuf1, inlineBuf2;
-        UTF32Char str1Char, str2Char;
+        UTF32Char str1Char = 0, str2Char = 0;
         CFStringEncoding eightBitEncoding = __CFStringGetEightBitStringEncoding();
         const uint8_t *str1Bytes = (const uint8_t *)CFStringGetCStringPtr(string, eightBitEncoding);
         const uint8_t *str2Bytes = (const uint8_t *)CFStringGetCStringPtr(stringToFind, eightBitEncoding);
@@ -2668,8 +2773,11 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
         CFIndex fromLoc, toLoc;
         CFIndex str1Index, str2Index;
         CFIndex strBuf1Len, strBuf2Len;
+       CFIndex maxStr1Index = (rangeToSearch.location + rangeToSearch.length);
         bool equalityOptions = ((lengthVariants || (compareOptions & kCFCompareWidthInsensitive)) ? true : false);
         bool caseInsensitive = ((compareOptions & kCFCompareCaseInsensitive) ? true : false);
+       bool forwardAnchor = ((kCFCompareAnchored == (compareOptions & (kCFCompareBackwards|kCFCompareAnchored))) ? true : false);
+       bool backwardAnchor = (((kCFCompareBackwards|kCFCompareAnchored) == (compareOptions & (kCFCompareBackwards|kCFCompareAnchored))) ? true : false);
         int8_t delta;
 
         if (NULL == locale) {
@@ -2696,7 +2804,6 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
         delta = ((fromLoc <= toLoc) ? 1 : -1);
 
         if ((NULL != str1Bytes) && (NULL != str2Bytes)) {
-            CFIndex maxStr1Index = (rangeToSearch.location + rangeToSearch.length);
             uint8_t str1Byte, str2Byte;
 
             while (1) {
@@ -2721,6 +2828,12 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                                     strBuf1Len = 1;
                                 }
                             }
+
+                           if ((NULL != ignoredChars) && (forwardAnchor || (str1Index != fromLoc)) && CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, ((str1Byte < 0x80) ? str1Byte : str1Char))) {
+                               ++str1Index;
+                               continue;
+                           }
+
                             if ((str2Byte < 0x80) && ((NULL == langCode) || ('I' != str2Byte))) {
                                 if (caseInsensitive && (str2Byte >= 'A') && (str2Byte <= 'Z')) str2Byte += ('a' - 'A');
                                 *strBuf2 = str2Byte;
@@ -2734,6 +2847,11 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                                 }
                             }
 
+                           if ((NULL != ignoredChars) && CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, ((str2Byte < 0x80) ? str2Byte : str2Char))) {
+                               ++str2Index;
+                               continue;
+                           }
+
                             if ((1 == strBuf1Len) && (1 == strBuf2Len)) { // normal case
                                 if (*strBuf1 != *strBuf2) break;
                             } else {
@@ -2745,7 +2863,7 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                                 if (strBuf1Len < strBuf2Len) {
                                     delta = strBuf2Len - strBuf1Len;
 
-                                    if ((str1Index + strBuf1Len + delta) > (rangeToSearch.location + rangeToSearch.length)) break;
+                                    if ((str1Index + strBuf1Len + delta) > maxStr1Index) break;
 
                                     characters = &(strBuf2[strBuf1Len]);
                                     charactersLimit = characters + delta;
@@ -2779,8 +2897,26 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                     ++str1Index; ++str2Index;
                 }
 
+               if ((NULL != ignoredChars) && (str1Index == maxStr1Index) && (str2Index < findStrLen)) { // Process the stringToFind tail
+                   while (str2Index < findStrLen) {
+                       str2Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf2, str2Index);
+
+                       if (!CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str2Char)) break;
+                       ++str2Index;
+                   }
+               }
+
                 if (str2Index == findStrLen) {
-                    if (((kCFCompareBackwards|kCFCompareAnchored) != (compareOptions & (kCFCompareBackwards|kCFCompareAnchored))) || (str1Index == (rangeToSearch.location + rangeToSearch.length))) {
+                   if ((NULL != ignoredChars) && backwardAnchor && (str1Index < maxStr1Index)) { // Process the anchor tail
+                       while (str1Index < maxStr1Index) {
+                           str1Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index);
+                           
+                           if (!CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str1Char)) break;
+                           ++str1Index;
+                       }
+                   }
+
+                    if (!backwardAnchor || (str1Index == maxStr1Index)) {
                         didFind = true;
                         if (NULL != result) *result = CFRangeMake(fromLoc, str1Index - fromLoc);
                     }
@@ -2793,7 +2929,7 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
         } else if (equalityOptions) {
             UTF16Char otherChar;
             CFIndex str1UsedLen, str2UsedLen, strBuf1Index = 0, strBuf2Index = 0;
-            bool diacriticsInsensitive = ((compareOptions & kCFCompareDiacriticsInsensitiveCompatibilityMask) ? true : false);
+            bool diacriticsInsensitive = ((compareOptions & kCFCompareDiacriticInsensitive) ? true : false);
             const uint8_t *graphemeBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharGraphemeExtendCharacterSet, 0);
             const uint8_t *combClassBMP = (const uint8_t *)CFUniCharGetUnicodePropertyDataForPlane(kCFUniCharCombiningProperty, 0);
 
@@ -2820,7 +2956,7 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                     }
 
                     if (str1Char != str2Char) {
-                        if ((str1Char < 0x80) && (str2Char < 0x80) && ((NULL == langCode) || !caseInsensitive)) break;
+                        if ((str1Char < 0x80) && (str2Char < 0x80) && (NULL == ignoredChars) && ((NULL == langCode) || !caseInsensitive)) break;
 
                         if (CFUniCharIsSurrogateHighCharacter(str1Char) && CFUniCharIsSurrogateLowCharacter((otherChar = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index + 1)))) {
                             str1Char = CFUniCharGetLongCharacterForSurrogatePair(str1Char, otherChar);
@@ -2832,6 +2968,21 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                             str2UsedLen = 2;
                         }
 
+                       if (NULL != ignoredChars) {
+                           if ((forwardAnchor || (str1Index != fromLoc)) && (str1Index < maxStr1Index) && CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str1Char)) {
+                               if ((strBuf1Len > 0) && (strBuf1Index == strBuf1Len)) strBuf1Len = 0;
+                               if (strBuf1Len == 0) str1Index += str1UsedLen;
+                               if (strBuf2Len > 0) --strBuf2Index;
+                               continue;
+                           }
+                           if (CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str2Char)) {
+                               if ((strBuf2Len > 0) && (strBuf2Index == strBuf2Len)) strBuf2Len = 0;
+                               if (strBuf2Len == 0) str2Index += str2UsedLen;
+                               if (strBuf1Len > 0) -- strBuf1Index;
+                               continue;
+                           }       
+                       }
+                       
                         if (diacriticsInsensitive && (str1Index > fromLoc)) {
                             bool str1Skip = false;
                             bool str2Skip = false;
@@ -2885,13 +3036,24 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                     if (strBuf2Len == 0) str2Index += str2UsedLen;
                 }
 
+               if ((NULL != ignoredChars) && (str1Index == maxStr1Index) && (str2Index < findStrLen)) { // Process the stringToFind tail
+                   while (str2Index < findStrLen) {
+                       str2Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf2, str2Index);
+                        if (CFUniCharIsSurrogateHighCharacter(str2Char) && CFUniCharIsSurrogateLowCharacter((otherChar = CFStringGetCharacterFromInlineBuffer(&inlineBuf2, str2Index + 1)))) {
+                            str2Char = CFUniCharGetLongCharacterForSurrogatePair(str2Char, otherChar);
+                        }
+                       if (!CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str2Char)) break;
+                       str2Index += ((str2Char < 0x10000) ? 1 : 2);
+                   }
+               }
+
                 if (str2Index == findStrLen) {
                     bool match = true;
 
                     if (strBuf1Len > 0) {
                         match = false;
 
-                        if ((compareOptions & kCFCompareDiacriticsInsensitiveCompatibilityMask) && (strBuf1[0] < 0x0510)) {
+                        if ((compareOptions & kCFCompareDiacriticInsensitive) && (strBuf1[0] < 0x0510)) {
                             while (strBuf1Index < strBuf1Len) {
                                 if (!CFUniCharIsMemberOfBitmap(strBuf1[strBuf1Index], ((strBuf1[strBuf1Index] < 0x10000) ? graphemeBMP : CFUniCharGetBitmapPtrForPlane(kCFUniCharCanonicalDecomposableCharacterSet, (strBuf1[strBuf1Index] >> 16))))) break;
                                 ++strBuf1Index;
@@ -2904,7 +3066,7 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                         }
                     }
 
-                    if (match && (compareOptions & (kCFCompareDiacriticsInsensitiveCompatibilityMask|kCFCompareNonliteral)) && (str1Index < (rangeToSearch.location + rangeToSearch.length))) {
+                    if (match && (compareOptions & (kCFCompareDiacriticInsensitive|kCFCompareNonliteral)) && (str1Index < maxStr1Index)) {
                         const uint8_t *nonBaseBitmap;
 
                         str1Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index);
@@ -2926,9 +3088,7 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                                     } while (CFUniCharIsMemberOfBitmap(str1Char, graphemeBMP), (rangeToSearch.location < index));
 
                                     if (str1Char < 0x0510) {
-                                        CFIndex maxIndex = (rangeToSearch.location + rangeToSearch.length);
-
-                                        while (++str1Index < maxIndex) if (!CFUniCharIsMemberOfBitmap(CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index), graphemeBMP)) break;
+                                        while (++str1Index < maxStr1Index) if (!CFUniCharIsMemberOfBitmap(CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index), graphemeBMP)) break;
                                     }
                                 }
                             } else {
@@ -2947,7 +3107,18 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
                     }
 
                     if (match) {
-                        if (((kCFCompareBackwards|kCFCompareAnchored) != (compareOptions & (kCFCompareBackwards|kCFCompareAnchored))) || (str1Index == (rangeToSearch.location + rangeToSearch.length))) {
+                       if ((NULL != ignoredChars) && backwardAnchor && (str1Index < maxStr1Index)) { // Process the anchor tail
+                           while (str1Index < maxStr1Index) {
+                               str1Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index);
+                               if (CFUniCharIsSurrogateHighCharacter(str1Char) && CFUniCharIsSurrogateLowCharacter((otherChar = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, str1Index + 1)))) {
+                                   str1Char = CFUniCharGetLongCharacterForSurrogatePair(str1Char, otherChar);
+                               }
+                               if (!CFCharacterSetInlineBufferIsLongCharacterMember(ignoredChars, str1Char)) break;
+                               str1Index += ((str1Char < 0x10000) ? 1 : 2);
+                           }
+                       }
+
+                        if (!backwardAnchor || (str1Index == maxStr1Index)) {
                             didFind = true;
                             if (NULL != result) *result = CFRangeMake(fromLoc, str1Index - fromLoc);
                         }
@@ -2984,7 +3155,8 @@ Boolean CFStringFindWithOptionsAndLocale(CFStringRef string, CFStringRef stringT
     return didFind;
 }
 
-Boolean CFStringFindWithOptions(CFStringRef string, CFStringRef stringToFind, CFRange rangeToSearch, CFOptionFlags compareOptions, CFRange *result) { return CFStringFindWithOptionsAndLocale(string, stringToFind, rangeToSearch, compareOptions, NULL, result); }
+
+Boolean CFStringFindWithOptions(CFStringRef string, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags compareOptions, CFRange *result) { return CFStringFindWithOptionsAndLocale(string, stringToFind, rangeToSearch, compareOptions, NULL, result); }
 
 // Functions to deal with special arrays of CFRange, CFDataRef, created by CFStringCreateArrayWithFindResults()
 
@@ -3009,7 +3181,7 @@ static Boolean    __rangeEqual(const void *ptr1, const void *ptr2) {
 }
 
 
-CFArrayRef CFStringCreateArrayWithFindResults(CFAllocatorRef alloc, CFStringRef string, CFStringRef stringToFind, CFRange rangeToSearch, CFOptionFlags compareOptions) {
+CFArrayRef CFStringCreateArrayWithFindResults(CFAllocatorRef alloc, CFStringRef string, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags compareOptions) {
     CFRange foundRange;
     Boolean backwards = ((compareOptions & kCFCompareBackwards) != 0);
     UInt32 endIndex = rangeToSearch.location + rangeToSearch.length;
@@ -3063,7 +3235,7 @@ CFArrayRef CFStringCreateArrayWithFindResults(CFAllocatorRef alloc, CFStringRef
 }
 
 
-CFRange CFStringFind(CFStringRef string, CFStringRef stringToFind, CFOptionFlags compareOptions) {
+CFRange CFStringFind(CFStringRef string, CFStringRef stringToFind, CFStringCompareFlags compareOptions) {
     CFRange foundRange;
 
     if (CFStringFindWithOptions(string, stringToFind, CFRangeMake(0, CFStringGetLength(string)), compareOptions, &foundRange)) {
@@ -3381,155 +3553,9 @@ CFRange CFStringGetRangeOfCharacterClusterAtIndex(CFStringRef string, CFIndex ch
     return range;
 }
 
-#if 1 /* Using the new implementation. Leaving the old implementation if'ed out for testing purposes for now */
 CFRange CFStringGetRangeOfComposedCharactersAtIndex(CFStringRef theString, CFIndex theIndex) {
     return CFStringGetRangeOfCharacterClusterAtIndex(theString, theIndex, kCFStringComposedCharacterCluster);
 }
-#else
-/*!
-       @function CFStringGetRangeOfComposedCharactersAtIndex
-       Returns the range of the composed character sequence at the specified index.
-       @param theString The CFString which is to be searched.  If this
-                               parameter is not a valid CFString, the behavior is
-                       undefined.
-       @param theIndex The index of the character contained in the
-                       composed character sequence.  If the index is
-                       outside the index space of the string (0 to N-1 inclusive,
-                       where N is the length of the string), the behavior is
-                       undefined.
-       @result The range of the composed character sequence.
-*/
-#define ExtHighHalfZoneLow 0xD800
-#define ExtHighHalfZoneHigh 0xDBFF
-#define ExtLowHalfZoneLow 0xDC00
-#define ExtLowHalfZoneHigh 0xDFFF
-#define JunseongStart 0x1160
-#define JonseongEnd 0x11F9
-CF_INLINE Boolean IsHighCode(UniChar X) { return (X >= ExtHighHalfZoneLow && X <= ExtHighHalfZoneHigh); }
-CF_INLINE Boolean IsLowCode(UniChar X) { return (X >= ExtLowHalfZoneLow && X <= ExtLowHalfZoneHigh); }
-#define IsHangulConjoiningJamo(X) (X >= JunseongStart && X <= JonseongEnd)
-#define IsHalfwidthKanaVoicedMark(X) ((X == 0xFF9E) || (X == 0xFF9F))
-CF_INLINE Boolean IsNonBaseChar(UniChar X, CFCharacterSetRef nonBaseSet) { return (CFCharacterSetIsCharacterMember(nonBaseSet, X) || IsHangulConjoiningJamo(X) || IsHalfwidthKanaVoicedMark(X) || (X & 0x1FFFF0) == 0xF870); } // combining char, hangul jamo, or Apple corporate variant tag
-#define ZWJ    0x200D
-#define ZWNJ   0x200C
-#define COMBINING_GRAPHEME_JOINER (0x034F)
-
-static CFCharacterSetRef nonBaseChars = NULL;
-static CFCharacterSetRef letterChars = NULL;
-static const void *__CFCombiningClassBMP = NULL;
-
-CF_INLINE bool IsVirama(UTF32Char character) {
-    return ((character == COMBINING_GRAPHEME_JOINER) ? true : ((character < 0x10000) && (CFUniCharGetCombiningPropertyForCharacter(character, __CFCombiningClassBMP) == 9) ? true : false));
-}
-
-CFRange CFStringGetRangeOfComposedCharactersAtIndex(CFStringRef theString, CFIndex theIndex) {
-    CFIndex left, current, save;
-    CFIndex len = CFStringGetLength(theString);
-    CFStringInlineBuffer stringBuffer;
-    static volatile Boolean _isInited = false;
-
-    if (theIndex >= len) return CFRangeMake(kCFNotFound, 0);
-
-    if (!_isInited) {
-        nonBaseChars = CFCharacterSetGetPredefined(kCFCharacterSetNonBase);
-        letterChars = CFCharacterSetGetPredefined(kCFCharacterSetLetter);
-        __CFCombiningClassBMP = CFUniCharGetUnicodePropertyDataForPlane(kCFUniCharCombiningProperty, 0);
-        _isInited = true;
-    }
-
-    save = current = theIndex;
-
-    CFStringInitInlineBuffer(theString, &stringBuffer, CFRangeMake(0, len));
-
-    /*
-     * First check for transcoding hints
-     */
-    {
-        CFRange theRange = (current > MAX_TRANSCODING_LENGTH  ? CFRangeMake(current - MAX_TRANSCODING_LENGTH, MAX_TRANSCODING_LENGTH + 1) : CFRangeMake(0, current + 1));
-
-        // Should check the next loc ?
-        if (current + 1 < len) ++theRange.length;
-
-        if (theRange.length > 1) {
-            UniChar characterBuffer[MAX_TRANSCODING_LENGTH + 2]; // Transcoding hint length + current loc + next loc
-
-            if (stringBuffer.directBuffer) {
-                memmove(characterBuffer, stringBuffer.directBuffer + theRange.location, theRange.length * sizeof(UniChar));
-            } else {
-                CFStringGetCharacters(theString, theRange, characterBuffer);
-            }
-
-            while (current >= theRange.location) {
-                if ((characterBuffer[current - theRange.location] & 0x1FFFF0) == 0xF860) {
-                    theRange = CFRangeMake(current, __CFTranscodingHintLength[characterBuffer[current - theRange.location] - 0xF860] + 1);
-                    if ((theRange.location + theRange.length) <= theIndex) break;
-                    if ((theRange.location + theRange.length) >= len) theRange.length = len - theRange.location;
-                    return theRange;
-                }
-                if (current == 0) break;
-                --current;
-            }
-            current = theIndex; // Reset current
-        }
-    }
-
-//#warning Aki 5/29/01 This does not support non-base chars in non-BMP planes (i.e. musical symbol combining stem in Unicode 3.1)
-    /*
-     * if we start NOT on a base, first move back to a base as appropriate.
-     */
-
-  roundAgain:
-
-    while ((current > 0) && IsNonBaseChar(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current), nonBaseChars)) --current;
-
-    if (current >= 1 && current < len && CFCharacterSetIsCharacterMember(letterChars, CFStringGetCharacterFromInlineBuffer(&stringBuffer, current)) && IsVirama(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current - 1))) {
-       --current;
-       goto roundAgain;
-    } else if ((current >= 2) && (CFStringGetCharacterFromInlineBuffer(&stringBuffer, current - 1) == ZWJ) && IsVirama(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current - 2))) {
-        current -= 2;
-       goto roundAgain;
-    }
-
-    /*
-     * Set the left position, then jump back to the saved original position.
-     */
-
-    if (current >= 1 && IsLowCode(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current)) && IsHighCode(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current - 1))) --current;
-    left = current;
-    current = save;
-
-    /*
-     * Now, presume we are on a base; move forward & look for the next base.
-     * Handle jumping over H/L codes.
-     */
-    if (IsHighCode(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current)) && (current + 1) < len && IsLowCode(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current + 1))) ++current;
-    ++current;
-
-  round2Again:
-
-    if (current < len)  {
-        while (IsNonBaseChar(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current), nonBaseChars)) {
-           ++current;
-           if (current >= len) break;
-       }
-       if ((current < len) && CFCharacterSetIsCharacterMember(letterChars, CFStringGetCharacterFromInlineBuffer(&stringBuffer, current))) {
-           if (IsVirama(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current - 1))) {
-               ++current; goto round2Again;
-           } else if ((current >= 2) && (CFStringGetCharacterFromInlineBuffer(&stringBuffer, current - 1) == ZWJ) && IsVirama(CFStringGetCharacterFromInlineBuffer(&stringBuffer, current - 2))) {
-               ++current; goto round2Again;
-           }
-       }
-    }
-    /*
-     * Now, "current" is a base, and "left" is a base.
-     * The junk between had better contain "save"!
-     */
-    if ((! (left <= save)) || (! (save <= current))) {
-       CFLog(kCFLogLevelWarning, CFSTR("CFString: CFStringGetRangeOfComposedCharactersAtIndex:%d returned invalid\n"), save);
-    }
-    return CFRangeMake(left, current - left);
-}
-#endif
 
 /*!
        @function CFStringFindCharacterFromSet
@@ -3561,7 +3587,7 @@ CFRange CFStringGetRangeOfComposedCharactersAtIndex(CFStringRef theString, CFInd
 #define SURROGATE_START 0xD800
 #define SURROGATE_END 0xDFFF
 
-CF_EXPORT Boolean CFStringFindCharacterFromSet(CFStringRef theString, CFCharacterSetRef theSet, CFRange rangeToSearch, CFOptionFlags searchOptions, CFRange *result) {
+CF_EXPORT Boolean CFStringFindCharacterFromSet(CFStringRef theString, CFCharacterSetRef theSet, CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFRange *result) {
     CFStringInlineBuffer stringBuffer;
     CFCharacterSetInlineBuffer csetBuffer;
     UniChar ch;
@@ -3867,7 +3893,7 @@ CFDataRef CFStringCreateExternalRepresentation(CFAllocatorRef alloc, CFStringRef
     if (((encoding & 0x0FFF) == kCFStringEncodingUnicode) && ((encoding == kCFStringEncodingUnicode) || ((encoding > kCFStringEncodingUTF8) && (encoding <= kCFStringEncodingUTF32LE)))) {
         guessedByteLength = (length + 1) * ((((encoding >> 26)  & 2) == 0) ? sizeof(UTF16Char) : sizeof(UTF32Char)); // UTF32 format has the bit set
     } else if (((guessedByteLength = CFStringGetMaximumSizeForEncoding(length, encoding)) > length) && !CF_IS_OBJC(__kCFStringTypeID, string)) { // Multi byte encoding
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
         if (__CFStrIsUnicode(string)) {
             CFIndex aLength = CFStringEncodingByteLengthForCharacters(encoding, kCFStringEncodingPrependBOM, __CFStrContents(string), __CFStrLength(string));
             if (aLength > 0) guessedByteLength = aLength;
@@ -3881,7 +3907,7 @@ CFDataRef CFStringCreateExternalRepresentation(CFAllocatorRef alloc, CFStringRef
         if (guessedByteLength == length && __CFStrIsEightBit(string) && __CFStringEncodingIsSupersetOfASCII(encoding)) { // It's all ASCII !!
             return CFDataCreate(alloc, ((uint8_t *)__CFStrContents(string) + __CFStrSkipAnyLengthByte(string)), __CFStrLength(string));
         }
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
         }
 #endif
     }
@@ -4114,7 +4140,7 @@ void CFStringAppendFormat(CFMutableStringRef str, CFDictionaryRef formatOptions,
 }
 
 
-CFIndex CFStringFindAndReplace(CFMutableStringRef string, CFStringRef stringToFind, CFStringRef replacementString, CFRange rangeToSearch, CFOptionFlags compareOptions) {
+CFIndex CFStringFindAndReplace(CFMutableStringRef string, CFStringRef stringToFind, CFStringRef replacementString, CFRange rangeToSearch, CFStringCompareFlags compareOptions) {
     CFRange foundRange;
     Boolean backwards = ((compareOptions & kCFCompareBackwards) != 0);
     UInt32 endIndex = rangeToSearch.location + rangeToSearch.length;
@@ -5301,7 +5327,7 @@ void CFStringAppendFormatAndArguments(CFMutableStringRef outputString, CFDiction
     _CFStringAppendFormatAndArgumentsAux(outputString, NULL, formatOptions, formatString, args);
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define SNPRINTF(TYPE, WHAT) {                         \
     TYPE value = (TYPE) WHAT;                          \
     if (-1 != specs[curSpec].widthArgNum) {            \
@@ -5322,18 +5348,18 @@ void CFStringAppendFormatAndArguments(CFMutableStringRef outputString, CFDiction
     TYPE value = (TYPE) WHAT;                          \
     if (-1 != specs[curSpec].widthArgNum) {            \
        if (-1 != specs[curSpec].precArgNum) {          \
-           snprintf(buffer, 255, formatBuffer, width, precision, value); \
+           sprintf(buffer, formatBuffer, width, precision, value); \
        } else {                                        \
-           snprintf(buffer, 255, formatBuffer, width, value); \
+           sprintf(buffer, formatBuffer, width, value); \
        }                                               \
     } else {                                           \
        if (-1 != specs[curSpec].precArgNum) {          \
-           snprintf(buffer, 255, formatBuffer, precision, value); \
+           sprintf(buffer, formatBuffer, precision, value); \
         } else {                                       \
-           snprintf(buffer, 255, formatBuffer, value); \
+           sprintf(buffer, formatBuffer, value);       \
        }                                               \
     }}
-#endif //__MACH__
+#endif
 
 void _CFStringAppendFormatAndArgumentsAux(CFMutableStringRef outputString, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, CFStringRef formatString, va_list args) {
     SInt32 numSpecs, sizeSpecs, sizeArgNum, formatIdx, curSpec, argNum;
@@ -5608,7 +5634,7 @@ void _CFStringAppendFormatAndArgumentsAux(CFMutableStringRef outputString, CFStr
                        }
                        // See if we need to localize the decimal point
                         if (formatOptions) {   // We have localization info
-                           CFStringRef decimalSeparator = (CFGetTypeID(formatOptions) == CFLocaleGetTypeID()) ? (CFStringRef)CFLocaleGetValue((CFLocaleRef)formatOptions, kCFLocaleDecimalSeparator) : (CFStringRef)CFDictionaryGetValue(formatOptions, CFSTR("NSDecimalSeparator"));
+                           CFStringRef decimalSeparator = (CFGetTypeID(formatOptions) == CFLocaleGetTypeID()) ? (CFStringRef)CFLocaleGetValue((CFLocaleRef)formatOptions, kCFLocaleDecimalSeparatorKey) : (CFStringRef)CFDictionaryGetValue(formatOptions, CFSTR("NSDecimalSeparator"));
                             if (decimalSeparator != NULL) {    // We have a decimal separator in there
                                 CFIndex decimalPointLoc = 0;
                                 while (buffer[decimalPointLoc] != 0 && buffer[decimalPointLoc] != '.') decimalPointLoc++;
@@ -5628,7 +5654,7 @@ void _CFStringAppendFormatAndArgumentsAux(CFMutableStringRef outputString, CFStr
                                if (dynamicBuffer) {
                                        CFAllocatorDeallocate(kCFAllocatorSystemDefault, dynamicBuffer);
                                }
-#endif         
+#endif
                        }
                 break;
        case CFFormatLiteralType:
index 7fdd126c04853979bec95b8bef6a0d4d867795a4..89abd364551103d030882b8573ac23f2217d1b63 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFString.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTRING__)
@@ -40,10 +40,12 @@ CF_EXTERN_C_BEGIN
 /*
 Please note: CFStrings are conceptually an array of Unicode characters.
 However, in general, how a CFString stores this array is an implementation
-detail. For instance, CFString might choose to use an array of 8-bit characters;
-to store its contents; or it might use multiple blocks of memory; or whatever.
-Furthermore, the implementation might change depending on the default
-system encoding, the user's language, the OS, or even a given release.
+detail. For instance, CFString might choose to use an array of 8-bit characters
+to store its contents, or it might use multiple blocks of memory, or whatever.
+This is especially true since CFString is toll-free bridged with NSString, enabling
+any NSString instance to be used as a CFString. Furthermore, the implementation
+may change depending on the default system encoding, the user's language, 
+or even a release or update of the OS.
 
 What this means is that you should use the following advanced functions with care:
 
@@ -62,20 +64,19 @@ exception mentioned further below.)
 In your usages of these functions, if you get a NULL return, use the non-Ptr version
 of the functions as shown in this example:
 
-  Str255 buffer;
-  StringPtr ptr = CFStringGetPascalStringPtr(str, encoding);
+  char buffer[BUFSIZE];
+  const char *ptr = CFStringGetCStringPtr(str, encoding);
   if (ptr == NULL) {
-      if (CFStringGetPascalString(str, buffer, 256, encoding)) ptr = buffer;
+      if (CFStringGetCString(str, buffer, BUFSIZE, encoding)) ptr = buffer;
   }
 
-Note that CFStringGetPascalString() or CFStringGetCString() calls might still fail --- but
+Note that CFStringGetCString() or CFStringGetPascalString() calls might still fail --- but
 that will happen in two circumstances only: The conversion from the UniChar contents of CFString
 to the specified encoding fails, or the buffer is too small. If they fail, that means
 the conversion was not possible.
 
-If you need a copy of the buffer in the above example, you might consider simply
-calling CFStringGetPascalString() in all cases --- CFStringGetPascalStringPtr()
-is simply an optimization.
+If you need a copy of the buffer in the above example, you might consider simply calling
+CFStringGetCString() in all cases --- CFStringGetCStringPtr() is simply an optimization.
 
 In addition, the following functions, which create immutable CFStrings from developer
 supplied buffers without copying the buffers, might have to actually copy
@@ -125,7 +126,7 @@ enum {
     kCFStringEncodingUnicode = 0x0100, /* kTextEncodingUnicodeDefault  + kTextEncodingDefaultFormat (aka kUnicode16BitFormat) */
     kCFStringEncodingUTF8 = 0x08000100, /* kTextEncodingUnicodeDefault + kUnicodeUTF8Format */
     kCFStringEncodingNonLossyASCII = 0x0BFF /* 7bit Unicode variants used by Cocoa & Java */
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+#if MAC_OS_X_VERSION_10_4 <= MAC_OS_X_VERSION_MAX_ALLOWED
     ,
     kCFStringEncodingUTF16 = 0x0100, /* kTextEncodingUnicodeDefault + kUnicodeUTF16Format (alias of kCFStringEncodingUnicode) */
     kCFStringEncodingUTF16BE = 0x10000100, /* kTextEncodingUnicodeDefault + kUnicodeUTF16BEFormat */
@@ -134,15 +135,17 @@ enum {
     kCFStringEncodingUTF32 = 0x0c000100, /* kTextEncodingUnicodeDefault + kUnicodeUTF32Format */
     kCFStringEncodingUTF32BE = 0x18000100, /* kTextEncodingUnicodeDefault + kUnicodeUTF32BEFormat */
     kCFStringEncodingUTF32LE = 0x1c000100 /* kTextEncodingUnicodeDefault + kUnicodeUTF32LEFormat */
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 */
+#endif /* MAC_OS_X_VERSION_10_4 <= MAC_OS_X_VERSION_MAX_ALLOWED */
 };
 typedef CFStringEncoding CFStringBuiltInEncodings;
 
+
 /* CFString type ID */
 CF_EXPORT
 CFTypeID CFStringGetTypeID(void);
 
-/* Macro to allow creation of compile-time constant strings; the argument should be a constant string.
+/* CFSTR() allows creation of compile-time constant CFStringRefs; the argument 
+should be a constant C-string.
 
 CFSTR(), not being a "Copy" or "Create" function, does not return a new
 reference for you. So, you should not release the return value. This is
@@ -154,17 +157,32 @@ properly nested fashion, just like any other CF type. That is, if you pass
 a CFSTR() return value to a function such as SetMenuItemWithCFString(), the
 function can retain it, then later, when it's done with it, it can release it.
 
-At this point non-7 bit characters (that is, characters > 127) in CFSTR() are not 
-supported and using them will lead to unpredictable results. This includes escaped
-(\nnn) characters whose values are > 127. Even if it works for you in testing, 
-it might not work for a user with a different language preference.
+Non-7 bit characters (that is, above 127) in CFSTR() are supported, although care must
+be taken in dealing with files containing them. If you can trust your editor and tools
+to deal with non-ASCII characters in the source code, then you can use them directly 
+in CFSTR(); otherwise, you can represent such characters with their escaped octal 
+equivalents in the encoding the compiler will use to interpret them (for instance, 
+O-umlaut is \303\226 in UTF-8). UTF-8 is the recommended encoding here, 
+since it is the default choice with Mac OS X developer tools.
 */
+#if TARGET_OS_WIN32
+#undef __CONSTANT_CFSTRINGS__
+#endif
+
 #ifdef __CONSTANT_CFSTRINGS__
 #define CFSTR(cStr)  ((CFStringRef) __builtin___CFStringMakeConstantString ("" cStr ""))
 #else
 #define CFSTR(cStr)  __CFStringMakeConstantString("" cStr "")
 #endif
 
+#if defined(__GNUC__) && (__GNUC__*10+__GNUC_MINOR__ >= 42) && !defined(__INTEL_COMPILER) && (TARGET_OS_MAC || TARGET_OS_EMBEDDED)
+#define CF_FORMAT_FUNCTION(F,A) __attribute__((format(CFString, F, A)))
+#define CF_FORMAT_ARGUMENT(A) __attribute__((format_arg(A)))
+#else
+#define CF_FORMAT_FUNCTION(F,A)
+#define CF_FORMAT_ARGUMENT(A)
+#endif
+
 /*** Immutable string creation functions ***/
 
 /* Functions to create basic immutable strings. The provided allocator is used for all memory activity in these functions.
@@ -208,7 +226,7 @@ CFStringRef CFStringCreateWithPascalStringNoCopy(CFAllocatorRef alloc, ConstStr2
 CF_EXPORT
 CFStringRef CFStringCreateWithCStringNoCopy(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding, CFAllocatorRef contentsDeallocator);
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+#if MAC_OS_X_VERSION_10_4 <= MAC_OS_X_VERSION_MAX_ALLOWED
 /* The following takes an explicit length, and allows you to specify whether the data is an external format --- that is, whether to pay attention to the BOM character (if any) and do byte swapping if necessary
 */
 CF_EXPORT
@@ -229,10 +247,10 @@ CFStringRef CFStringCreateCopy(CFAllocatorRef alloc, CFStringRef theString);
 /* These functions create a CFString from the provided printf-like format string and arguments.
 */
 CF_EXPORT
-CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...);
+CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...) CF_FORMAT_FUNCTION(3,4);
 
 CF_EXPORT
-CFStringRef CFStringCreateWithFormatAndArguments(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, va_list arguments);
+CFStringRef CFStringCreateWithFormatAndArguments(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, va_list arguments) CF_FORMAT_FUNCTION(3,0);
 
 /* Functions to create mutable strings. "maxLength", if not 0, is a hard bound on the length of the string. If 0, there is no limit on the length.
 */
@@ -301,25 +319,29 @@ CF_EXPORT
 const UniChar *CFStringGetCharactersPtr(CFStringRef theString);                                        /* May return NULL at any time; be prepared for NULL */
 
 /* The primitive conversion routine; allows you to convert a string piece at a time
-   into a fixed size buffer. Returns number of characters converted. 
+       into a fixed size buffer. Returns number of characters converted. 
    Characters that cannot be converted to the specified encoding are represented
-   with the byte specified by lossByte; if lossByte is 0, then lossy conversion
-   is not allowed and conversion stops, returning partial results.
+       with the byte specified by lossByte; if lossByte is 0, then lossy conversion
+       is not allowed and conversion stops, returning partial results.
    Pass buffer==NULL if you don't care about the converted string (but just the convertability,
-   or number of bytes required). 
+       or number of bytes required). 
    maxBufLength indicates the maximum number of bytes to generate. It is ignored when buffer==NULL.
    Does not zero-terminate. If you want to create Pascal or C string, allow one extra byte at start or end. 
    Setting isExternalRepresentation causes any extra bytes that would allow 
-   the data to be made persistent to be included; for instance, the Unicode BOM.
+       the data to be made persistent to be included; for instance, the Unicode BOM. Note that
+       CFString prepends UTF encoded data with the Unicode BOM <http://www.unicode.org/faq/utf_bom.html> 
+       when generating external representation if the target encoding allows. It's important to note that
+       only UTF-8, UTF-16, and UTF-32 define the handling of the byte order mark character, and the "LE"
+       and "BE" variants of UTF-16 and UTF-32 don't.
 */
 CF_EXPORT
 CFIndex CFStringGetBytes(CFStringRef theString, CFRange range, CFStringEncoding encoding, UInt8 lossByte, Boolean isExternalRepresentation, UInt8 *buffer, CFIndex maxBufLen, CFIndex *usedBufLen);
 
 /* Convenience functions String <-> Data. These generate "external" formats, that is, formats that
-   can be written out to disk. For instance, if the encoding is Unicode, CFStringCreateFromExternalRepresentation()
-   pays attention to the BOM character (if any) and does byte swapping if necessary.
-   Similarly CFStringCreateExternalRepresentation() will always include a BOM character if the encoding is
-   Unicode. See above for description of lossByte.
+   can be written out to disk. For instance, if the encoding is Unicode,
+   CFStringCreateFromExternalRepresentation() pays attention to the BOM character (if any) 
+   and does byte swapping if necessary. Similarly CFStringCreateExternalRepresentation() will  
+   include a BOM character if appropriate. See CFStringGetBytes() for more on this and lossByte.
 */
 CF_EXPORT
 CFStringRef CFStringCreateFromExternalRepresentation(CFAllocatorRef alloc, CFDataRef data, CFStringEncoding encoding); /* May return NULL on conversion error */
@@ -364,8 +386,7 @@ CFStringRef CFStringCreateWithFileSystemRepresentation(CFAllocatorRef alloc, con
 
 /*** Comparison functions. ***/
 
-/* Find and compare flags; these are OR'ed together as compareOptions or searchOptions in the various functions. 
-   This typedef doesn't appear in the functions; instead the argument is CFOptionFlags. 
+/* Find and compare flags; these are OR'ed together and provided as CFStringCompareFlags in the various functions. 
 */
 enum { 
     kCFCompareCaseInsensitive = 1,     
@@ -374,12 +395,12 @@ enum {
     kCFCompareNonliteral = 16,         /* If specified, loose equivalence is performed (o-umlaut == o, umlaut) */
     kCFCompareLocalized = 32,          /* User's default locale is used for the comparisons */
     kCFCompareNumerically = 64         /* Numeric comparison is used; that is, Foo2.txt < Foo7.txt < Foo25.txt */
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
     ,
     kCFCompareDiacriticInsensitive = 128, /* If specified, ignores diacritics (o-umlaut == o) */
     kCFCompareWidthInsensitive = 256, /* If specified, ignores width differences ('a' == UFF41) */
     kCFCompareForcedOrdering = 512 /* If specified, comparisons are forced to return either kCFCompareLessThan or kCFCompareGreaterThan if the strings are equivalent but not strictly equal, for stability when sorting (e.g. "aaa" > "AAA" with kCFCompareCaseInsensitive specified) */
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 */
+#endif /* MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED */
 };
 typedef CFOptionFlags CFStringCompareFlags;
 
@@ -388,41 +409,37 @@ locale == NULL indicates canonical locale (the return value from CFLocaleGetSyst
 kCFCompareNumerically, added in 10.2, does not work if kCFCompareLocalized is specified on systems before 10.3
 kCFCompareBackwards and kCFCompareAnchored are not applicable.
 */
-#if !defined (__WIN32__)
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
 CF_EXPORT
-CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef theString1, CFStringRef theString2, CFRange rangeToCompare, CFOptionFlags compareOptions, CFLocaleRef locale) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 */
-#endif //__WIN32__
+CFComparisonResult CFStringCompareWithOptionsAndLocale(CFStringRef theString1, CFStringRef theString2, CFRange rangeToCompare, CFStringCompareFlags compareOptions, CFLocaleRef locale) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
+#endif /* MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED */
 
 /* Comparison convenience. Uses the current user locale (the return value from CFLocaleCopyCurrent()) if kCFCompareLocalized.
 */
 CF_EXPORT
-CFComparisonResult CFStringCompareWithOptions(CFStringRef theString1, CFStringRef theString2, CFRange rangeToCompare, CFOptionFlags compareOptions);
+CFComparisonResult CFStringCompareWithOptions(CFStringRef theString1, CFStringRef theString2, CFRange rangeToCompare, CFStringCompareFlags compareOptions);
 
 /* Comparison convenience suitable for passing as sorting functions.
    kCFCompareNumerically, added in 10.2, does not work if kCFCompareLocalized is specified on systems before 10.3
    kCFCompareBackwards and kCFCompareAnchored are not applicable.
 */
 CF_EXPORT
-CFComparisonResult CFStringCompare(CFStringRef theString1, CFStringRef theString2, CFOptionFlags compareOptions);
+CFComparisonResult CFStringCompare(CFStringRef theString1, CFStringRef theString2, CFStringCompareFlags compareOptions);
 
 /* CFStringFindWithOptionsAndLocale() returns the found range in the CFRange * argument; you can pass NULL for simple discovery check.
  locale == NULL indicates canonical locale (the return value from CFLocaleGetSystem()).
  If stringToFind is the empty string (zero length), nothing is found.
  Ignores the kCFCompareNumerically option.
 */
-#if !defined (__WIN32__)
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
 CF_EXPORT
-Boolean CFStringFindWithOptionsAndLocale(CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFOptionFlags searchOptions, CFLocaleRef locale, CFRange *result) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 */
-#endif //__WIN32__
+Boolean CFStringFindWithOptionsAndLocale(CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFLocaleRef locale, CFRange *result) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
+#endif /* MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED */
 
 /* Find convenience. Uses the current user locale (the return value from CFLocaleCopyCurrent()) if kCFCompareLocalized.
 */
 CF_EXPORT
-Boolean CFStringFindWithOptions(CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFOptionFlags searchOptions, CFRange *result);
+Boolean CFStringFindWithOptions(CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFRange *result);
 
 /* CFStringCreateArrayWithFindResults() returns an array of CFRange pointers, or NULL if there are no matches.
    Overlapping instances are not found; so looking for "AA" in "AAA" finds just one range.
@@ -433,12 +450,12 @@ Boolean CFStringFindWithOptions(CFStringRef theString, CFStringRef stringToFind,
    Ignores the kCFCompareNumerically option.
 */
 CF_EXPORT
-CFArrayRef CFStringCreateArrayWithFindResults(CFAllocatorRef alloc, CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFOptionFlags compareOptions);
+CFArrayRef CFStringCreateArrayWithFindResults(CFAllocatorRef alloc, CFStringRef theString, CFStringRef stringToFind, CFRange rangeToSearch, CFStringCompareFlags compareOptions);
 
 /* Find conveniences; see comments above concerning empty string and options.
 */
 CF_EXPORT
-CFRange CFStringFind(CFStringRef theString, CFStringRef stringToFind, CFOptionFlags compareOptions);
+CFRange CFStringFind(CFStringRef theString, CFStringRef stringToFind, CFStringCompareFlags compareOptions);
 
 CF_EXPORT
 Boolean CFStringHasPrefix(CFStringRef theString, CFStringRef prefix);
@@ -491,7 +508,7 @@ CF_EXPORT CFRange CFStringGetRangeOfComposedCharactersAtIndex(CFStringRef theStr
        @result true, if at least a character which is a member of the character
                        set is found and result is filled, otherwise, false.
 */
-CF_EXPORT Boolean CFStringFindCharacterFromSet(CFStringRef theString, CFCharacterSetRef theSet, CFRange rangeToSearch, CFOptionFlags searchOptions, CFRange *result);
+CF_EXPORT Boolean CFStringFindCharacterFromSet(CFStringRef theString, CFCharacterSetRef theSet, CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFRange *result);
 #endif
 
 /* Find range of bounds of the line(s) that span the indicated range (startIndex, numChars),
@@ -549,10 +566,10 @@ CF_EXPORT
 void CFStringAppendCString(CFMutableStringRef theString, const char *cStr, CFStringEncoding encoding);
 
 CF_EXPORT
-void CFStringAppendFormat(CFMutableStringRef theString, CFDictionaryRef formatOptions, CFStringRef format, ...);
+void CFStringAppendFormat(CFMutableStringRef theString, CFDictionaryRef formatOptions, CFStringRef format, ...) CF_FORMAT_FUNCTION(3,4);
 
 CF_EXPORT
-void CFStringAppendFormatAndArguments(CFMutableStringRef theString, CFDictionaryRef formatOptions, CFStringRef format, va_list arguments);
+void CFStringAppendFormatAndArguments(CFMutableStringRef theString, CFDictionaryRef formatOptions, CFStringRef format, va_list arguments) CF_FORMAT_FUNCTION(3,0);
 
 CF_EXPORT
 void CFStringInsert(CFMutableStringRef str, CFIndex idx, CFStringRef insertedStr);
@@ -576,7 +593,7 @@ void CFStringReplaceAll(CFMutableStringRef theString, CFStringRef replacement);
    Returns number of replacements performed.
 */
 CF_EXPORT
-CFIndex CFStringFindAndReplace(CFMutableStringRef theString, CFStringRef stringToFind, CFStringRef replacementString, CFRange rangeToSearch, CFOptionFlags compareOptions);
+CFIndex CFStringFindAndReplace(CFMutableStringRef theString, CFStringRef stringToFind, CFStringRef replacementString, CFRange rangeToSearch, CFStringCompareFlags compareOptions);
 
 #endif
 
@@ -659,7 +676,7 @@ typedef CFIndex CFStringNormalizationForm;
 CF_EXPORT void CFStringNormalize(CFMutableStringRef theString, CFStringNormalizationForm theForm);
 #endif
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
 /*!
        @function CFStringFold
        Folds the string into the form specified by the flags.
@@ -686,12 +703,13 @@ CF_EXPORT void CFStringNormalize(CFMutableStringRef theString, CFStringNormaliza
 
 CF_EXPORT
 void CFStringFold(CFMutableStringRef theString, CFOptionFlags theFlags, CFLocaleRef theLocale) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 */
+#endif /* MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED */
 
 /* Perform string transliteration.  The transformation represented by transform is applied to the given range of string, modifying it in place. Only the specified range will be modified, but the transform may look at portions of the string outside that range for context. NULL range pointer causes the whole string to be transformed. On return, range is modified to reflect the new range corresponding to the original range. reverse indicates that the inverse transform should be used instead, if it exists. If the transform is successful, true is returned; if unsuccessful, false. Reasons for the transform being unsuccessful include an invalid transform identifier, or attempting to reverse an irreversible transform.
 
 You can pass one of the predefined transforms below, or any valid ICU transform ID as defined in the ICU User Guide. Note that we do not support arbitrary set of ICU transform rules.
 */
+CF_EXPORT
 Boolean CFStringTransform(CFMutableStringRef string, CFRange *range, CFStringRef transform, Boolean reverse) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
 
 /* Transform identifiers for CFStringTransform()
@@ -819,11 +837,38 @@ CF_INLINE UniChar CFStringGetCharacterFromInlineBuffer(CFStringInlineBuffer *buf
 
 
 
+/* UTF-16 surrogate support
+ */
+CF_INLINE Boolean CFStringIsSurrogateHighCharacter(UniChar character) {
+    return ((character >= 0xD800UL) && (character <= 0xDBFFUL) ? true : false);
+}
+
+CF_INLINE Boolean CFStringIsSurrogateLowCharacter(UniChar character) {
+    return ((character >= 0xDC00UL) && (character <= 0xDFFFUL) ? true : false);
+}
+
+CF_INLINE UTF32Char CFStringGetLongCharacterForSurrogatePair(UniChar surrogateHigh, UniChar surrogateLow) {
+    return ((surrogateHigh - 0xD800UL) << 10) + (surrogateLow - 0xDC00UL) + 0x0010000UL;
+}
 
+// Maps a UTF-32 character to a pair of UTF-16 surrogate characters. The buffer pointed by surrogates has to have space for at least 2 UTF-16 characters. Returns true if mapped to a surrogate pair.
+CF_INLINE Boolean CFStringGetSurrogatePairForLongCharacter(UTF32Char character, UniChar *surrogates) {
+    if ((character > 0xFFFFUL) && (character < 0x110000UL)) { // Non-BMP character
+        character -= 0x10000;
+        if (NULL != surrogates) {
+            surrogates[0] = (UniChar)((character >> 10) + 0xD800UL);
+            surrogates[1] = (UniChar)((character & 0x3FF) + 0xDC00UL);
+        }
+        return true;
+    } else {
+        if (NULL != surrogates) *surrogates = (UniChar)character;
+        return false;
+    }
+}
 
 /* Rest of the stuff in this file is private and should not be used directly
 */
-/* For debugging only
+/* For debugging only; output goes to stderr
    Use CFShow() to printf the description of any CFType;
    Use CFShowStr() to printf detailed info about a CFString
 */
@@ -840,4 +885,3 @@ CFStringRef  __CFStringMakeConstantString(const char *cStr);        /* Private; do not
 CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFSTRING__ */
-
index ad5c28a810bd4a0b9ba046e39e63e719c297ecad..0adfe26064efe4df8d4473e6daf73230c7ef0a3a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringDefaultEncoding.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTRINGDEFAULTENCODING__)
 #define __COREFOUNDATION_CFSTRINGDEFAULTENCODING__ 1
 
-/* This file defines static inline functions used both by CarbonCore & CF. */
-
 #include <CoreFoundation/CFBase.h>
 
-#if defined(__MACH__)
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
 #include <stdlib.h>
 #include <fcntl.h>
 #include <pwd.h>
 CF_EXTERN_C_BEGIN
 
 #define __kCFUserEncodingEnvVariableName ("__CF_USER_TEXT_ENCODING")
-#define __kCFMaxDefaultEncodingFileLength (24)
+#define __kCFMaxDefaultEncodingFileLength (64)
 #define __kCFUserEncodingFileName ("/.CFUserTextEncoding")
 
-/* This function is used to obtain users' default script/region code.
-   The function first looks at environment variable __kCFUserEncodingEnvVariableName, then, reads the configuration file in user's home directory.
-*/
-CF_INLINE void __CFStringGetUserDefaultEncoding(UInt32 *oScriptValue, UInt32 *oRegionValue) {
-    char *stringValue;
-    char buffer[__kCFMaxDefaultEncodingFileLength];
-    int uid = getuid();
-
-    if ((stringValue = getenv(__kCFUserEncodingEnvVariableName)) != NULL) {
-        if ((uid == strtol_l(stringValue, &stringValue, 0, NULL)) && (':' == *stringValue)) {
-            ++stringValue;
-        } else {
-            stringValue = NULL;
-        }
-    }
-
-    if ((stringValue == NULL) && ((uid > 0) || getenv("HOME"))) {
-        struct passwd *passwdp;
-
-        if ((passwdp = getpwuid((uid_t)uid))) {
-            char filename[MAXPATHLEN + 1];
-
-           const char *path = NULL;
-           if (!issetugid()) {
-               path = getenv("CFFIXED_USER_HOME");
-           }
-           if (!path) {
-               path = passwdp->pw_dir;
-           }
-
-            strlcpy(filename, path, sizeof(filename));
-            strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
-
-           int no_hang_fd = open("/dev/autofs_nowait", 0);
-            int fd = open(filename, O_RDONLY, 0);
-            if (fd == -1) {
-                // Cannot open the file. Let's fallback to smRoman/verUS
-                snprintf(filename, sizeof(filename), "0x%X:0:0", uid);
-                setenv(__kCFUserEncodingEnvVariableName, filename, 1);
-            } else {
-                int readSize;
-
-               // cjk: We do not turn on F_NOCACHE on the fd here, because
-               // many processes read this file on startup, and caching the
-               // is probably a good thing, for the system as a whole.
-                readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
-                buffer[(readSize < 0 ? 0 : readSize)] = '\0';
-                close(fd);
-                stringValue = buffer;
-
-                // Well, we already have a buffer, let's reuse it
-                snprintf(filename, sizeof(filename), "0x%X:%s", uid, buffer);
-                setenv(__kCFUserEncodingEnvVariableName, filename, 1);
-            }
-           close(no_hang_fd);
-        }
-    }
-
-    if (stringValue) {
-        *oScriptValue = strtol_l(stringValue, &stringValue, 0, NULL);
-        if (*stringValue == ':') {
-            if (oRegionValue) *oRegionValue = strtol_l(++stringValue, NULL, 0, NULL);
-            return;
-        }
-    }
-
-    // Falling back
-    *oScriptValue = 0; // smRoman
-    if (oRegionValue) *oRegionValue = 0; // verUS
-}
-
-CF_INLINE uint32_t __CFStringGetInstallationRegion() {
-    char *stringValue = NULL;
-    char buffer[__kCFMaxDefaultEncodingFileLength];
-    struct passwd *passwdp;
-    
-    if ((passwdp = getpwuid((uid_t)0))) {
-        char filename[MAXPATHLEN + 1];
-        
-       const char *path = NULL;
-       if (!issetugid()) {
-           path = getenv("CFFIXED_USER_HOME");
-       }
-       if (!path) {
-           path = passwdp->pw_dir;
-       }
+CF_EXPORT void _CFStringGetUserDefaultEncoding(UInt32 *oScriptValue, UInt32 *oRegionValue);
+CF_EXPORT void _CFStringGetInstallationEncodingAndRegion(uint32_t *encoding, uint32_t *region);
+CF_EXPORT Boolean _CFStringSaveUserDefaultEncoding(UInt32 iScriptValue, UInt32 iRegionValue);
 
-        strlcpy(filename, path, sizeof(filename));
-        strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
-        
-        int no_hang_fd = open("/dev/autofs_nowait", 0);
-       int fd = open(filename, O_RDONLY, 0);
-       if (fd == -1) {
-            int readSize;
-            
-            // cjk: We do not turn on F_NOCACHE on the fd here, because
-            // many processes read this file on startup, and caching the
-            // is probably a good thing, for the system as a whole.
-            readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
-            buffer[(readSize < 0 ? 0 : readSize)] = '\0';
-            close(fd);
-            stringValue = buffer;
-        }
-       close(no_hang_fd);
-    }
-    
-    if (stringValue) {
-        (void)strtol_l(stringValue, &stringValue, 0, NULL);
-        if (*stringValue == ':') return strtol_l(++stringValue, NULL, 0, NULL);
-    }
-
-    return 0; // verUS
-}
-
-CF_INLINE void __CFStringGetInstallationEncodingAndRegion(uint32_t *encoding, uint32_t *region) {
-    char *stringValue = NULL;
-    char buffer[__kCFMaxDefaultEncodingFileLength];
-    struct passwd *passwdp;
-
-    *encoding = 0; *region = 0;
-
-    if ((passwdp = getpwuid((uid_t)0))) {
-        char filename[MAXPATHLEN + 1];
-
-       const char *path = NULL;
-       if (!issetugid()) {
-           path = getenv("CFFIXED_USER_HOME");
-       }
-       if (!path) {
-           path = passwdp->pw_dir;
-       }
-
-        strlcpy(filename, path, sizeof(filename));
-        strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
-        
-       int no_hang_fd = open("/dev/autofs_nowait", 0);
-       int fd = open(filename, O_RDONLY, 0);
-       if (fd == -1) {
-            int readSize;
-            
-            readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
-            buffer[(readSize < 0 ? 0 : readSize)] = '\0';
-            close(fd);
-            stringValue = buffer;
-        }
-       close(no_hang_fd);
-    }
-    
-    if (stringValue) {
-        *encoding = strtol_l(stringValue, &stringValue, 0, NULL);
-        if (*stringValue == ':') *region = strtol_l(++stringValue, NULL, 0, NULL);
-    }
-}
-
-CF_INLINE void __CFStringSaveUserDefaultEncoding(UInt32 iScriptValue, UInt32 iRegionValue) {
-    struct passwd *passwdp;
-
-    if ((passwdp = getpwuid(getuid()))) {
-        char filename[MAXPATHLEN + 1];
-
-       const char *path = NULL;
-       if (!issetugid()) {
-           path = getenv("CFFIXED_USER_HOME");
-       }
-       if (!path) {
-           path = passwdp->pw_dir;
-       }
-
-        strlcpy(filename, path, sizeof(filename));
-        strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
-
-       int no_hang_fd = open("/dev/autofs_nowait", 0);
-        (void)unlink(filename);                // In case, file exists
-       int fd = open(filename, O_WRONLY|O_CREAT, 0400);
-       if (fd == -1) {
-            char buffer[__kCFMaxDefaultEncodingFileLength];
-            unsigned int writeSize;
-
-            writeSize = snprintf(buffer, __kCFMaxDefaultEncodingFileLength, "0x%X:0x%X", (unsigned int)iScriptValue, (unsigned int)iRegionValue);
-            (void)write(fd, buffer, (writeSize > __kCFMaxDefaultEncodingFileLength ? __kCFMaxDefaultEncodingFileLength : writeSize));
-            close(fd);
-        }
-       close(no_hang_fd);
-    }
-}
+CF_INLINE void __CFStringGetUserDefaultEncoding(UInt32 *oScriptValue, UInt32 *oRegionValue) { _CFStringGetUserDefaultEncoding(oScriptValue, oRegionValue); }
+CF_INLINE void __CFStringGetInstallationEncodingAndRegion(uint32_t *encoding, uint32_t *region) { _CFStringGetInstallationEncodingAndRegion(encoding, region); }
+CF_INLINE void __CFStringSaveUserDefaultEncoding(UInt32 iScriptValue, UInt32 iRegionValue) { _CFStringSaveUserDefaultEncoding(iScriptValue, iRegionValue); }
 
 CF_EXTERN_C_END
 
@@ -239,3 +59,4 @@ CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFSTRINGDEFAULTENCODING__ */
 
+
index 3e9276852726637ba8777885c8acbde6fc613462..52b24765c5c74646592650c278cf6d3e42e85d52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringEncodingConverter.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Aki Inoue
 */
 
 #include "CFInternal.h"
 #include <CoreFoundation/CFArray.h>
 #include <CoreFoundation/CFDictionary.h>
-#include "CFUniChar.h"
-#include "CFPriv.h"
+#include "CFICUConverters.h"
+#include <CoreFoundation/CFUniChar.h>
+#include <CoreFoundation/CFPriv.h>
 #include "CFUnicodeDecomposition.h"
 #include "CFStringEncodingConverterExt.h"
 #include "CFStringEncodingConverterPriv.h"
 #include <stdlib.h>
-#if !defined(__WIN32__)
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <pthread.h>
 #endif
 
+typedef CFIndex (*_CFToBytesProc)(const void *converter, uint32_t flags, const UniChar *characters, CFIndex numChars, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen);
+typedef CFIndex (*_CFToUnicodeProc)(const void *converter, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen);
+
+typedef struct {
+    const CFStringEncodingConverter *definition;
+    _CFToBytesProc toBytes;
+    _CFToUnicodeProc toUnicode;
+    _CFToUnicodeProc toCanonicalUnicode;
+    CFStringEncodingToBytesFallbackProc toBytesFallback;
+    CFStringEncodingToUnicodeFallbackProc toUnicodeFallback;
+} _CFEncodingConverter;
 
 /* Macros
 */
-#define TO_BYTE(conv,flags,chars,numChars,bytes,max,used) (conv->_toBytes ? conv->toBytes(conv,flags,chars,numChars,bytes,max,used) : ((CFStringEncodingToBytesProc)conv->toBytes)(flags,chars,numChars,bytes,max,used))
-#define TO_UNICODE(conv,flags,bytes,numBytes,chars,max,used) (conv->_toUnicode ?  (flags & (kCFStringEncodingUseCanonical|kCFStringEncodingUseHFSPlusCanonical) ? conv->toCanonicalUnicode(conv,flags,bytes,numBytes,chars,max,used) : conv->toUnicode(conv,flags,bytes,numBytes,chars,max,used)) : ((CFStringEncodingToUnicodeProc)conv->toUnicode)(flags,bytes,numBytes,chars,max,used))
+#define TO_BYTE(conv,flags,chars,numChars,bytes,max,used) (conv->toBytes ? conv->toBytes(conv,flags,chars,numChars,bytes,max,used) : ((CFStringEncodingToBytesProc)conv->definition->toBytes)(flags,chars,numChars,bytes,max,used))
+#define TO_UNICODE(conv,flags,bytes,numBytes,chars,max,used) (conv->toUnicode ?  (flags & (kCFStringEncodingUseCanonical|kCFStringEncodingUseHFSPlusCanonical) ? conv->toCanonicalUnicode(conv,flags,bytes,numBytes,chars,max,used) : conv->toUnicode(conv,flags,bytes,numBytes,chars,max,used)) : ((CFStringEncodingToUnicodeProc)conv->definition->toUnicode)(flags,bytes,numBytes,chars,max,used))
 
 #define ASCIINewLine 0x0a
 #define kSurrogateHighStart 0xD800
@@ -50,6 +62,8 @@
 #define kSurrogateLowStart 0xDC00
 #define kSurrogateLowEnd 0xDFFF
 
+static const uint8_t __CFMaximumConvertedLength = 20;
+
 /* Mapping 128..255 to lossy ASCII
 */
 static const struct {
@@ -230,7 +244,7 @@ static CFIndex __CFToBytesCheapEightBitWrapper(const void *converter, uint32_t f
     uint8_t byte;
 
     while (processedCharLen < length) {
-        if (!((CFStringEncodingCheapEightBitToBytesProc)((const _CFEncodingConverter*)converter)->_toBytes)(flags, characters[processedCharLen], &byte)) break;
+        if (!((CFStringEncodingCheapEightBitToBytesProc)((const _CFEncodingConverter*)converter)->definition->toBytes)(flags, characters[processedCharLen], &byte)) break;
 
         if (maxByteLen) bytes[processedCharLen] = byte;
         processedCharLen++;
@@ -246,7 +260,7 @@ static CFIndex __CFToUnicodeCheapEightBitWrapper(const void *converter, uint32_t
     UniChar character;
 
     while (processedByteLen < length) {
-        if (!((CFStringEncodingCheapEightBitToUnicodeProc)((const _CFEncodingConverter*)converter)->_toUnicode)(flags, bytes[processedByteLen], &character)) break;
+        if (!((CFStringEncodingCheapEightBitToUnicodeProc)((const _CFEncodingConverter*)converter)->definition->toUnicode)(flags, bytes[processedByteLen], &character)) break;
 
         if (maxCharLen) characters[processedByteLen] = character;
         processedByteLen++;
@@ -265,7 +279,7 @@ static CFIndex __CFToCanonicalUnicodeCheapEightBitWrapper(const void *converter,
     bool isHFSPlus = (flags & kCFStringEncodingUseHFSPlusCanonical ? true : false);
 
     while ((processedByteLen < numBytes) && (!maxCharLen || (theUsedCharLen < maxCharLen))) {
-        if (!((CFStringEncodingCheapEightBitToUnicodeProc)((const _CFEncodingConverter*)converter)->_toUnicode)(flags, bytes[processedByteLen], &character)) break;
+        if (!((CFStringEncodingCheapEightBitToUnicodeProc)((const _CFEncodingConverter*)converter)->definition->toUnicode)(flags, bytes[processedByteLen], &character)) break;
 
         if (CFUniCharIsDecomposableCharacter(character, isHFSPlus)) {
             CFIndex idx;
@@ -307,7 +321,7 @@ static CFIndex __CFToBytesStandardEightBitWrapper(const void *converter, uint32_
     *usedByteLen = 0;
 
     while (numChars && (!maxByteLen || (*usedByteLen < maxByteLen))) {
-        if (!(usedLen = ((CFStringEncodingStandardEightBitToBytesProc)((const _CFEncodingConverter*)converter)->_toBytes)(flags, characters, numChars, &byte))) break;
+        if (!(usedLen = ((CFStringEncodingStandardEightBitToBytesProc)((const _CFEncodingConverter*)converter)->definition->toBytes)(flags, characters, numChars, &byte))) break;
 
         if (maxByteLen) bytes[*usedByteLen] = byte;
         (*usedByteLen)++;
@@ -321,17 +335,13 @@ static CFIndex __CFToBytesStandardEightBitWrapper(const void *converter, uint32_
 
 static CFIndex __CFToUnicodeStandardEightBitWrapper(const void *converter, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) {
     CFIndex processedByteLen = 0;
-#if 0 || 0
-    UniChar charBuffer[20]; // Dynamic stack allocation is GNU specific
-#else
-    UniChar charBuffer[((const _CFEncodingConverter*)converter)->maxLen];
-#endif
+    UniChar charBuffer[__CFMaximumConvertedLength];
     CFIndex usedLen;
 
     *usedCharLen = 0;
 
     while ((processedByteLen < numBytes) && (!maxCharLen || (*usedCharLen < maxCharLen))) {
-        if (!(usedLen = ((CFStringEncodingCheapEightBitToUnicodeProc)((const _CFEncodingConverter*)converter)->_toUnicode)(flags, bytes[processedByteLen], charBuffer))) break;
+        if (!(usedLen = ((CFStringEncodingCheapEightBitToUnicodeProc)((const _CFEncodingConverter*)converter)->definition->toUnicode)(flags, bytes[processedByteLen], charBuffer))) break;
 
         if (maxCharLen) {
             CFIndex idx;
@@ -351,11 +361,7 @@ static CFIndex __CFToUnicodeStandardEightBitWrapper(const void *converter, uint3
 
 static CFIndex __CFToCanonicalUnicodeStandardEightBitWrapper(const void *converter, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen) {
     CFIndex processedByteLen = 0;
-#if 0 || 0
-    UniChar charBuffer[20]; // Dynamic stack allocation is GNU specific
-#else
-    UniChar charBuffer[((const _CFEncodingConverter*)converter)->maxLen];
-#endif
+    UniChar charBuffer[__CFMaximumConvertedLength];
     UTF32Char decompBuffer[MAX_DECOMPOSED_LENGTH];
     CFIndex usedLen;
     CFIndex decompedLen;
@@ -364,7 +370,7 @@ static CFIndex __CFToCanonicalUnicodeStandardEightBitWrapper(const void *convert
     CFIndex theUsedCharLen = 0;
 
     while ((processedByteLen < numBytes) && (!maxCharLen || (theUsedCharLen < maxCharLen))) {
-        if (!(usedLen = ((CFStringEncodingCheapEightBitToUnicodeProc)((const _CFEncodingConverter*)converter)->_toUnicode)(flags, bytes[processedByteLen], charBuffer))) break;
+        if (!(usedLen = ((CFStringEncodingCheapEightBitToUnicodeProc)((const _CFEncodingConverter*)converter)->definition->toUnicode)(flags, bytes[processedByteLen], charBuffer))) break;
 
         for (idx = 0;idx < usedLen;idx++) {
             if (CFUniCharIsDecomposableCharacter(charBuffer[idx], isHFSPlus)) {
@@ -400,17 +406,13 @@ static CFIndex __CFToCanonicalUnicodeStandardEightBitWrapper(const void *convert
 
 static CFIndex __CFToBytesCheapMultiByteWrapper(const void *converter, uint32_t flags, const UniChar *characters, CFIndex numChars, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen) {
     CFIndex processedCharLen = 0;
-#if 0 || 0
-    uint8_t byteBuffer[20]; // Dynamic stack allocation is GNU specific
-#else
-    uint8_t byteBuffer[((const _CFEncodingConverter*)converter)->maxLen];
-#endif
+    uint8_t byteBuffer[__CFMaximumConvertedLength];
     CFIndex usedLen;
 
     *usedByteLen = 0;
 
     while ((processedCharLen < numChars) && (!maxByteLen || (*usedByteLen < maxByteLen))) {
-        if (!(usedLen = ((CFStringEncodingCheapMultiByteToBytesProc)((const _CFEncodingConverter*)converter)->_toBytes)(flags, characters[processedCharLen], byteBuffer))) break;
+        if (!(usedLen = ((CFStringEncodingCheapMultiByteToBytesProc)((const _CFEncodingConverter*)converter)->definition->toBytes)(flags, characters[processedCharLen], byteBuffer))) break;
 
         if (maxByteLen) {
             CFIndex idx;
@@ -437,7 +439,7 @@ static CFIndex __CFToUnicodeCheapMultiByteWrapper(const void *converter, uint32_
     *usedCharLen = 0;
 
     while (numBytes && (!maxCharLen || (*usedCharLen < maxCharLen))) {
-        if (!(usedLen = ((CFStringEncodingCheapMultiByteToUnicodeProc)((const _CFEncodingConverter*)converter)->_toUnicode)(flags, bytes, numBytes, &character))) break;
+        if (!(usedLen = ((CFStringEncodingCheapMultiByteToUnicodeProc)((const _CFEncodingConverter*)converter)->definition->toUnicode)(flags, bytes, numBytes, &character))) break;
 
         if (maxCharLen) *(characters++) = character;
         (*usedCharLen)++;
@@ -459,7 +461,7 @@ static CFIndex __CFToCanonicalUnicodeCheapMultiByteWrapper(const void *converter
     bool isHFSPlus = (flags & kCFStringEncodingUseHFSPlusCanonical ? true : false);
 
     while (numBytes && (!maxCharLen || (theUsedCharLen < maxCharLen))) {
-        if (!(usedLen = ((CFStringEncodingCheapMultiByteToUnicodeProc)((const _CFEncodingConverter*)converter)->_toUnicode)(flags, bytes, numBytes, &character))) break;
+        if (!(usedLen = ((CFStringEncodingCheapMultiByteToUnicodeProc)((const _CFEncodingConverter*)converter)->definition->toUnicode)(flags, bytes, numBytes, &character))) break;
 
         if (CFUniCharIsDecomposableCharacter(character, isHFSPlus)) {
             CFIndex idx;
@@ -497,79 +499,14 @@ static CFIndex __CFToCanonicalUnicodeCheapMultiByteWrapper(const void *converter
 
 /* static functions
 */
-static _CFConverterEntry __CFConverterEntryASCII = {
-    kCFStringEncodingASCII, NULL,
-    "Western (ASCII)", {"us-ascii", "ascii", "iso-646-us", NULL}, NULL, NULL, NULL, NULL,
-    kCFStringEncodingMacRoman // We use string encoding's script range here
-};
-
-static _CFConverterEntry __CFConverterEntryISOLatin1 = {
-    kCFStringEncodingISOLatin1, NULL,
-    "Western (ISO Latin 1)", {"iso-8859-1", "latin1","iso-latin-1", NULL}, NULL, NULL, NULL, NULL,
-    kCFStringEncodingMacRoman // We use string encoding's script range here
-};
-
-static _CFConverterEntry __CFConverterEntryMacRoman = {
-    kCFStringEncodingMacRoman, NULL,
-    "Western (Mac OS Roman)", {"macintosh", "mac", "x-mac-roman", NULL}, NULL, NULL, NULL, NULL,
-    kCFStringEncodingMacRoman // We use string encoding's script range here
-};
-
-static _CFConverterEntry __CFConverterEntryWinLatin1 = {
-    kCFStringEncodingWindowsLatin1, NULL,
-    "Western (Windows Latin 1)", {"windows-1252", "cp1252", "windows latin1", NULL}, NULL, NULL, NULL, NULL,
-    kCFStringEncodingMacRoman // We use string encoding's script range here
-};
-
-static _CFConverterEntry __CFConverterEntryNextStepLatin = {
-    kCFStringEncodingNextStepLatin, NULL,
-    "Western (NextStep)", {"x-nextstep", NULL, NULL, NULL}, NULL, NULL, NULL, NULL,
-    kCFStringEncodingMacRoman // We use string encoding's script range here
-};
-
-static _CFConverterEntry __CFConverterEntryUTF8 = {
-    kCFStringEncodingUTF8, NULL,
-    "UTF-8", {"utf-8", "unicode-1-1-utf8", NULL, NULL}, NULL, NULL, NULL, NULL,
-    kCFStringEncodingUnicode // We use string encoding's script range here
-};
-
-CF_INLINE _CFConverterEntry *__CFStringEncodingConverterGetEntry(uint32_t encoding) {
-    switch (encoding) {
-        case kCFStringEncodingInvalidId:
-        case kCFStringEncodingASCII:
-            return &__CFConverterEntryASCII;
-
-        case kCFStringEncodingISOLatin1:
-            return &__CFConverterEntryISOLatin1;
-
-        case kCFStringEncodingMacRoman:
-            return &__CFConverterEntryMacRoman;
-
-        case kCFStringEncodingWindowsLatin1:
-            return &__CFConverterEntryWinLatin1;
-
-        case kCFStringEncodingNextStepLatin:
-            return &__CFConverterEntryNextStepLatin;
-
-        case kCFStringEncodingUTF8:
-            return &__CFConverterEntryUTF8;
-
-        default: {
-            return NULL;
-        }
-    }
-}
-
-CF_INLINE _CFEncodingConverter *__CFEncodingConverterFromDefinition(const CFStringEncodingConverter *definition) {
+CF_INLINE _CFEncodingConverter *__CFEncodingConverterFromDefinition(const CFStringEncodingConverter *definition, CFStringEncoding encoding) {
 #define NUM_OF_ENTRIES_CYCLE (10)
-    static CFSpinLock_t _indexLock = CFSpinLockInit;
     static uint32_t _currentIndex = 0;
     static uint32_t _allocatedSize = 0;
     static _CFEncodingConverter *_allocatedEntries = NULL;
     _CFEncodingConverter *converter;
 
 
-    __CFSpinLock(&_indexLock);
     if ((_currentIndex + 1) >= _allocatedSize) {
         _currentIndex = 0;
         _allocatedSize = 0;
@@ -582,117 +519,130 @@ CF_INLINE _CFEncodingConverter *__CFEncodingConverterFromDefinition(const CFStri
     } else {
         converter = &(_allocatedEntries[++_currentIndex]);
     }
-    __CFSpinUnlock(&_indexLock);
+
+    memset(converter, 0, sizeof(_CFEncodingConverter));
+
+    converter->definition = definition;
 
     switch (definition->encodingClass) {
         case kCFStringEncodingConverterStandard:
-            converter->toBytes = (_CFToBytesProc)definition->toBytes;
-            converter->toUnicode = (_CFToUnicodeProc)definition->toUnicode;
-            converter->toCanonicalUnicode = (_CFToUnicodeProc)definition->toUnicode;
-            converter->_toBytes = NULL;
-            converter->_toUnicode = NULL;
-            converter->maxLen = 2;
+            converter->toBytes = NULL;
+            converter->toUnicode = NULL;
+            converter->toCanonicalUnicode = NULL;
             break;
 
         case kCFStringEncodingConverterCheapEightBit:
             converter->toBytes = __CFToBytesCheapEightBitWrapper;
             converter->toUnicode = __CFToUnicodeCheapEightBitWrapper;
             converter->toCanonicalUnicode = __CFToCanonicalUnicodeCheapEightBitWrapper;
-            converter->_toBytes = definition->toBytes;
-            converter->_toUnicode = definition->toUnicode;
-            converter->maxLen = 1;
             break;
 
         case kCFStringEncodingConverterStandardEightBit:
             converter->toBytes = __CFToBytesStandardEightBitWrapper;
             converter->toUnicode = __CFToUnicodeStandardEightBitWrapper;
             converter->toCanonicalUnicode = __CFToCanonicalUnicodeStandardEightBitWrapper;
-            converter->_toBytes = definition->toBytes;
-            converter->_toUnicode = definition->toUnicode;
-            converter->maxLen = definition->maxDecomposedCharLen;
             break;
 
         case kCFStringEncodingConverterCheapMultiByte:
             converter->toBytes = __CFToBytesCheapMultiByteWrapper;
             converter->toUnicode = __CFToUnicodeCheapMultiByteWrapper;
             converter->toCanonicalUnicode = __CFToCanonicalUnicodeCheapMultiByteWrapper;
-            converter->_toBytes = definition->toBytes;
-            converter->_toUnicode = definition->toUnicode;
-            converter->maxLen = definition->maxBytesPerChar;
+            break;
+
+        case kCFStringEncodingConverterICU:
+            converter->toBytes = (_CFToBytesProc)__CFStringEncodingGetICUName(encoding);
             break;
 
         case kCFStringEncodingConverterPlatformSpecific:
-            converter->toBytes = NULL;
-            converter->toUnicode = NULL;
-            converter->toCanonicalUnicode = NULL;
-            converter->_toBytes = NULL;
-            converter->_toUnicode = NULL;
-            converter->maxLen = 0;
-            converter->toBytesLen = NULL;
-            converter->toUnicodeLen = NULL;
-            converter->toBytesFallback = NULL;
-            converter->toUnicodeFallback = NULL;
-            converter->toBytesPrecompose = NULL;
-            converter->isValidCombiningChar = NULL;
-            return converter;
+            break;
             
         default: // Shouln't be here
             return NULL;
     }
 
-    converter->toBytesLen = (definition->toBytesLen ? definition->toBytesLen : (CFStringEncodingToBytesLenProc)(uintptr_t)definition->maxBytesPerChar);
-    converter->toUnicodeLen = (definition->toUnicodeLen ? definition->toUnicodeLen : (CFStringEncodingToUnicodeLenProc)(uintptr_t)definition->maxDecomposedCharLen);
     converter->toBytesFallback = (definition->toBytesFallback ? definition->toBytesFallback : __CFDefaultToBytesFallbackProc);
     converter->toUnicodeFallback = (definition->toUnicodeFallback ? definition->toUnicodeFallback : __CFDefaultToUnicodeFallbackProc);
-    converter->toBytesPrecompose = (definition->toBytesPrecompose ? definition->toBytesPrecompose : NULL);
-    converter->isValidCombiningChar = (definition->isValidCombiningChar ? definition->isValidCombiningChar : NULL);
 
     return converter;
 }
 
-CF_INLINE const CFStringEncodingConverter *__CFStringEncodingConverterGetDefinition(_CFConverterEntry *entry) {
-    if (!entry) return NULL;
-    
-    switch (entry->encoding) {
+CF_INLINE const CFStringEncodingConverter *__CFStringEncodingConverterGetDefinition(CFStringEncoding encoding) {
+    switch (encoding) {
+        case kCFStringEncodingUTF8:
+            return &__CFConverterUTF8;
+
+        case kCFStringEncodingMacRoman:
+            return &__CFConverterMacRoman;
+            
+        case kCFStringEncodingWindowsLatin1:
+            return &__CFConverterWinLatin1;
+
         case kCFStringEncodingASCII:
             return &__CFConverterASCII;
 
         case kCFStringEncodingISOLatin1:
             return &__CFConverterISOLatin1;
 
-        case kCFStringEncodingMacRoman:
-            return &__CFConverterMacRoman;
-
-        case kCFStringEncodingWindowsLatin1:
-            return &__CFConverterWinLatin1;
 
         case kCFStringEncodingNextStepLatin:
             return &__CFConverterNextStepLatin;
 
-        case kCFStringEncodingUTF8:
-            return &__CFConverterUTF8;
 
         default:
-           return NULL;
+            return __CFStringEncodingGetExternalConverter(encoding);
     }
 }
 
 static const _CFEncodingConverter *__CFGetConverter(uint32_t encoding) {
-    _CFConverterEntry *entry = __CFStringEncodingConverterGetEntry(encoding);
+    const _CFEncodingConverter *converter = NULL;
+    const _CFEncodingConverter **commonConverterSlot = NULL;
+    static _CFEncodingConverter *commonConverters[3] = {NULL, NULL, NULL}; // UTF8, MacRoman/WinLatin1, and the default encoding*
+    static CFMutableDictionaryRef mappingTable = NULL;
+    static CFSpinLock_t lock = CFSpinLockInit;
+
+    switch (encoding) {
+       case kCFStringEncodingUTF8: commonConverterSlot = (const _CFEncodingConverter **)&(commonConverters[0]); break;
+
+           /* the swith here should avoid possible bootstrap issues in the default: case below when invoked from CFStringGetSystemEncoding() */
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+       case kCFStringEncodingMacRoman: commonConverterSlot = (const _CFEncodingConverter **)&(commonConverters[1]); break;
+#elif DEPLOYMENT_TARGET_WINDOWS
+       case kCFStringEncodingWindowsLatin1: commonConverterSlot = (const _CFEncodingConverter **)(&(commonConverters[1])); break;
+#else
+#warning This case must match __defaultEncoding value defined in CFString.c
+       case kCFStringEncodingISOLatin1: commonConverterSlot = (const _CFEncodingConverter **)(&(commonConverters[1])); break;
+#endif /* DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED */
+
+       default: if (CFStringGetSystemEncoding() == encoding) commonConverterSlot = (const _CFEncodingConverter **)&(commonConverters[2]); break;
+    }
+
+    __CFSpinLock(&lock);
+    converter = ((NULL == commonConverterSlot) ? ((NULL == mappingTable) ? NULL : (const _CFEncodingConverter *)CFDictionaryGetValue(mappingTable, (const void *)(uintptr_t)encoding)) : *commonConverterSlot);
+    __CFSpinUnlock(&lock);
 
-    if (!entry) return NULL;
+    if (NULL == converter) {
+        const CFStringEncodingConverter *definition = __CFStringEncodingConverterGetDefinition(encoding);
 
-    if (!entry->converter) {
-        const CFStringEncodingConverter *definition = __CFStringEncodingConverterGetDefinition(entry);
+        if (NULL != definition) {
+            __CFSpinLock(&lock);
+            converter = ((NULL == commonConverterSlot) ? ((NULL == mappingTable) ? NULL : (const _CFEncodingConverter *)CFDictionaryGetValue(mappingTable, (const void *)(uintptr_t)encoding)) : *commonConverterSlot);
 
-        if (definition) {
-            entry->converter = __CFEncodingConverterFromDefinition(definition);
-            entry->toBytesFallback = definition->toBytesFallback;
-            entry->toUnicodeFallback = definition->toUnicodeFallback;
+            if (NULL == converter) {
+                converter = __CFEncodingConverterFromDefinition(definition, encoding);
+
+               if (NULL == commonConverterSlot) {
+                   if (NULL == mappingTable) mappingTable = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+
+                   CFDictionarySetValue(mappingTable, (const void *)(uintptr_t)encoding, converter);
+               } else {
+                   *commonConverterSlot = converter;
+               }
+            }
+            __CFSpinUnlock(&lock);
         }
     }
 
-    return (_CFEncodingConverter *)entry->converter;
+    return converter;
 }
 
 /* Public API
@@ -718,7 +668,11 @@ uint32_t CFStringEncodingUnicodeToBytes(uint32_t encoding, uint32_t flags, const
 
         if (convertedCharLen == numChars) {
             return kCFStringEncodingConversionSuccess;
-        } else if (maxByteLen && (maxByteLen == usedLen)) {
+        } else if ((maxByteLen > 0) && ((maxByteLen - usedLen) < 10)) { // could be filled outbuf
+            UTF16Char character = characters[convertedCharLen];
+            
+            if (((character >= kSurrogateLowStart) && (character <= kSurrogateLowEnd)) || ((character >= kSurrogateHighStart) && (character <= kSurrogateHighEnd) && ((1 == (numChars - convertedCharLen)) || (characters[convertedCharLen + 1] < kSurrogateLowStart) || (characters[convertedCharLen + 1] > kSurrogateLowEnd)))) return kCFStringEncodingInvalidInputStream;
+            
             return kCFStringEncodingInsufficientOutputBufferLength;
         } else {
             return kCFStringEncodingInvalidInputStream;
@@ -735,15 +689,19 @@ uint32_t CFStringEncodingUnicodeToBytes(uint32_t encoding, uint32_t flags, const
         if (!converter) return kCFStringEncodingConverterUnavailable;
 
         if (flags & kCFStringEncodingSubstituteCombinings) {
-            if (!(flags & kCFStringEncodingAllowLossyConversion)) isValidCombiningChar = converter->isValidCombiningChar;
+            if (!(flags & kCFStringEncodingAllowLossyConversion)) isValidCombiningChar = converter->definition->isValidCombiningChar;
        } else {
-            isValidCombiningChar = converter->isValidCombiningChar;
+            isValidCombiningChar = converter->definition->isValidCombiningChar;
             if (!(flags & kCFStringEncodingIgnoreCombinings)) {
-                toBytesPrecompose = converter->toBytesPrecompose;
+                toBytesPrecompose = converter->definition->toBytesPrecompose;
                 flags |= kCFStringEncodingComposeCombinings;
             }
         }
 
+        if (kCFStringEncodingConverterICU == converter->definition->encodingClass) return __CFStringEncodingICUToBytes((const char *)converter->toBytes, flags, characters, numChars, usedCharLen, bytes, maxByteLen, usedByteLen);
+
+        /* Platform converter */
+        if (kCFStringEncodingConverterPlatformSpecific == converter->definition->encodingClass) return __CFStringEncodingPlatformUnicodeToBytes(encoding, flags, characters, numChars, usedCharLen, bytes, maxByteLen, usedByteLen);
 
         while ((usedLen < numChars) && (!maxByteLen || (theUsedByteLen < maxByteLen))) {
             if ((usedLen += TO_BYTE(converter, flags, characters + usedLen, numChars - usedLen, bytes + theUsedByteLen, (maxByteLen ? maxByteLen - theUsedByteLen : 0), &localUsedByteLen)) < numChars) {
@@ -755,7 +713,7 @@ uint32_t CFStringEncodingUnicodeToBytes(uint32_t encoding, uint32_t flags, const
 
                         while (isValidCombiningChar(characters[--usedLen]));
                         theUsedByteLen += localUsedByteLen;
-                        if (converter->maxLen > 1) {
+                        if (converter->definition->maxBytesPerChar > 1) {
                             TO_BYTE(converter, flags, characters + usedLen, localUsedLen - usedLen, NULL, 0, &localUsedByteLen);
                             theUsedByteLen -= localUsedByteLen;
                         } else {
@@ -772,7 +730,7 @@ uint32_t CFStringEncodingUnicodeToBytes(uint32_t encoding, uint32_t flags, const
                             uint8_t lossyByte = CFStringEncodingMaskToLossyByte(flags);
 
                             if (lossyByte) {
-                                                               while (isValidCombiningChar(characters[++usedLen]));
+                                while (isValidCombiningChar(characters[++usedLen]));
                                 localUsedByteLen = 1;
                                 if (maxByteLen) *(bytes + theUsedByteLen) = lossyByte;
                             } else {
@@ -857,6 +815,10 @@ uint32_t CFStringEncodingBytesToUnicode(uint32_t encoding, uint32_t flags, const
 
     if (!converter) return kCFStringEncodingConverterUnavailable;
 
+    if (kCFStringEncodingConverterICU == converter->definition->encodingClass) return __CFStringEncodingICUToUnicode((const char *)converter->toBytes, flags, bytes, numBytes, usedByteLen, characters, maxCharLen, usedCharLen);
+
+    /* Platform converter */
+    if (kCFStringEncodingConverterPlatformSpecific == converter->definition->encodingClass) return __CFStringEncodingPlatformBytesToUnicode(encoding, flags, bytes, numBytes, usedByteLen, characters, maxCharLen, usedCharLen);
 
     while ((usedLen < numBytes) && (!maxCharLen || (theUsedCharLen < maxCharLen))) {
         if ((usedLen += TO_UNICODE(converter, flags, bytes + usedLen, numBytes - usedLen, characters + theUsedCharLen, (maxCharLen ? maxCharLen - theUsedCharLen : 0), &localUsedCharLen)) < numBytes) {
@@ -891,35 +853,43 @@ __private_extern__ bool CFStringEncodingIsValidEncoding(uint32_t encoding) {
     return (CFStringEncodingGetConverter(encoding) ? true : false);
 }
 
-__private_extern__ const char *CFStringEncodingName(uint32_t encoding) {
-    _CFConverterEntry *entry = __CFStringEncodingConverterGetEntry(encoding);
-    if (entry) return entry->encodingName;
-    return NULL;
-}
+__private_extern__ CFIndex CFStringEncodingCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) {
+    const _CFEncodingConverter *converter = __CFGetConverter(encoding);
 
-__private_extern__ const char **CFStringEncodingCanonicalCharsetNames(uint32_t encoding) {
-    _CFConverterEntry *entry = __CFStringEncodingConverterGetEntry(encoding);
-    if (entry) return entry->ianaNames;
-    return NULL;
-}
+    if (converter) {
+        if (kCFStringEncodingConverterICU == converter->definition->encodingClass) return __CFStringEncodingICUCharLength((const char *)converter->toBytes, flags, bytes, numBytes);
 
-__private_extern__ uint32_t CFStringEncodingGetScriptCodeForEncoding(CFStringEncoding encoding) {
-    _CFConverterEntry *entry = __CFStringEncodingConverterGetEntry(encoding);
+        if (kCFStringEncodingConverterPlatformSpecific == converter->definition->encodingClass) return __CFStringEncodingPlatformCharLengthForBytes(encoding, flags, bytes, numBytes);
 
-    return (entry ? entry->scriptCode : ((encoding & 0x0FFF) == kCFStringEncodingUnicode ? kCFStringEncodingUnicode : (encoding < 0xFF ? encoding : kCFStringEncodingInvalidId)));
-}
+        if (1 == converter->definition->maxBytesPerChar) return numBytes;
 
-__private_extern__ CFIndex CFStringEncodingCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes) {
-    const _CFEncodingConverter *converter = __CFGetConverter(encoding);
+        if (NULL == converter->definition->toUnicodeLen) {
+            CFIndex usedByteLen = 0;
+            CFIndex totalLength = 0;
+            CFIndex usedCharLen;
 
-    if (converter) {
-        uintptr_t switchVal = (uintptr_t)(converter->toUnicodeLen);
+            while (numBytes > 0) {
+                usedByteLen = TO_UNICODE(converter, flags, bytes, numBytes, NULL, 0, &usedCharLen);
+
+                bytes += usedByteLen;
+                numBytes -= usedByteLen;
+                totalLength += usedCharLen;
+
+                if (numBytes > 0) {
+                    if (0 == (flags & kCFStringEncodingAllowLossyConversion)) return 0;
 
-        if (switchVal < 0xFFFF) {
-            return switchVal * numBytes;
+                    usedByteLen = TO_UNICODE_FALLBACK(converter, bytes, numBytes, NULL, 0, &usedCharLen);
+
+                    bytes += usedByteLen;
+                    numBytes -= usedByteLen;
+                    totalLength += usedCharLen;
+                }
+            }
+
+            return totalLength;
         } else {
-            return converter->toUnicodeLen(flags, bytes, numBytes);
-       }
+            return converter->definition->toUnicodeLen(flags, bytes, numBytes);
+        }
     }
 
     return 0;
@@ -929,32 +899,42 @@ __private_extern__ CFIndex CFStringEncodingByteLengthForCharacters(uint32_t enco
     const _CFEncodingConverter *converter = __CFGetConverter(encoding);
 
     if (converter) {
-        uintptr_t switchVal = (uintptr_t)(converter->toBytesLen);
+        if (kCFStringEncodingConverterICU == converter->definition->encodingClass) return __CFStringEncodingICUByteLength((const char *)converter->toBytes, flags, characters, numChars);
+
+        if (kCFStringEncodingConverterPlatformSpecific == converter->definition->encodingClass) return __CFStringEncodingPlatformByteLengthForCharacters(encoding, flags, characters, numChars);
+
+        if (1 == converter->definition->maxBytesPerChar) return numChars;
+
+        if (NULL == converter->definition->toBytesLen) {
+            CFIndex usedCharLen;
 
-       if (switchVal < 0xFFFF) {
-            return switchVal * numChars;
+            return ((kCFStringEncodingConversionSuccess == CFStringEncodingUnicodeToBytes(encoding, flags, characters, numChars, &usedCharLen, NULL, 0, NULL)) ? usedCharLen : 0);
         } else {
-            return converter->toBytesLen(flags, characters, numChars);
-       }
+            return converter->definition->toBytesLen(flags, characters, numChars);
+        }
     }
 
     return 0;
 }
 
 __private_extern__ void CFStringEncodingRegisterFallbackProcedures(uint32_t encoding, CFStringEncodingToBytesFallbackProc toBytes, CFStringEncodingToUnicodeFallbackProc toUnicode) {
-    _CFConverterEntry *entry = __CFStringEncodingConverterGetEntry(encoding);
+    _CFEncodingConverter *converter = (_CFEncodingConverter *)__CFGetConverter(encoding);
+
+    if (NULL != converter) {
+       const CFStringEncodingConverter *body = CFStringEncodingGetConverter(encoding);
 
-    if (entry && __CFGetConverter(encoding)) {
-        ((_CFEncodingConverter*)entry->converter)->toBytesFallback = (toBytes ? toBytes : entry->toBytesFallback);
-        ((_CFEncodingConverter*)entry->converter)->toUnicodeFallback = (toUnicode ? toUnicode : entry->toUnicodeFallback);
+        converter->toBytesFallback = ((NULL == toBytes) ? ((NULL == body) ? __CFDefaultToBytesFallbackProc : body->toBytesFallback) : toBytes);
+        converter->toUnicodeFallback = ((NULL == toUnicode) ? ((NULL == body) ? __CFDefaultToUnicodeFallbackProc : body->toUnicodeFallback) : toUnicode);
     }
 }
 
 __private_extern__ const CFStringEncodingConverter *CFStringEncodingGetConverter(uint32_t encoding) {
-    return __CFStringEncodingConverterGetDefinition(__CFStringEncodingConverterGetEntry(encoding));
+    const _CFEncodingConverter *converter = __CFGetConverter(encoding);
+
+    return ((NULL == converter) ? NULL : converter->definition);
 }
 
-static const uint32_t __CFBuiltinEncodings[] = {
+static const CFStringEncoding __CFBuiltinEncodings[] = {
     kCFStringEncodingMacRoman,
     kCFStringEncodingWindowsLatin1,
     kCFStringEncodingISOLatin1,
@@ -975,11 +955,61 @@ static const uint32_t __CFBuiltinEncodings[] = {
     kCFStringEncodingInvalidId,
 };
 
+static CFComparisonResult __CFStringEncodingComparator(const void *v1, const void *v2, void *context) {
+    CFComparisonResult val1 = (*(const CFStringEncoding *)v1) & 0xFFFF;
+    CFComparisonResult val2 = (*(const CFStringEncoding *)v2) & 0xFFFF;
 
-__private_extern__ const uint32_t *CFStringEncodingListOfAvailableEncodings(void) {
-    return __CFBuiltinEncodings;
+    return ((val1 == val2) ? ((CFComparisonResult)(*(const CFStringEncoding *)v1) - (CFComparisonResult)(*(const CFStringEncoding *)v2)) : val1 - val2);
 }
 
+static void __CFStringEncodingFliterDupes(CFStringEncoding *encodings, CFIndex numSlots) {
+    CFStringEncoding last = kCFStringEncodingInvalidId;
+    const CFStringEncoding *limitEncodings = encodings + numSlots;
+
+    while (encodings < limitEncodings) {
+        if (last == *encodings) {
+            if ((encodings + 1) < limitEncodings) memmove(encodings, encodings + 1, sizeof(CFStringEncoding) * (limitEncodings - encodings - 1));
+            --limitEncodings;
+        } else {
+            last = *(encodings++);
+        }
+    }
+}
+
+__private_extern__ const CFStringEncoding *CFStringEncodingListOfAvailableEncodings(void) {
+    static const CFStringEncoding *encodings = NULL;
+
+    if (NULL == encodings) {
+        CFStringEncoding *list = (CFStringEncoding *)__CFBuiltinEncodings;
+        CFIndex numICUConverters = 0, numPlatformConverters = 0;
+        CFStringEncoding *icuConverters = __CFStringEncodingCreateICUEncodings(NULL, &numICUConverters);
+        CFStringEncoding *platformConverters = __CFStringEncodingCreateListOfAvailablePlatformConverters(NULL, &numPlatformConverters);
+
+        if ((NULL != icuConverters) || (NULL != platformConverters)) {
+            CFIndex numSlots = (sizeof(__CFBuiltinEncodings) / sizeof(*__CFBuiltinEncodings)) + numICUConverters + numPlatformConverters;
+
+            list = (CFStringEncoding *)CFAllocatorAllocate(NULL, sizeof(CFStringEncoding) * numSlots, 0);
+
+            memcpy(list, __CFBuiltinEncodings, sizeof(__CFBuiltinEncodings));
+
+            if (NULL != icuConverters) {
+                memcpy(list + (sizeof(__CFBuiltinEncodings) / sizeof(*__CFBuiltinEncodings)), icuConverters, sizeof(CFStringEncoding) * numICUConverters);
+                CFAllocatorDeallocate(NULL, icuConverters);
+            }
+
+            if (NULL != platformConverters) {
+                memcpy(list + (sizeof(__CFBuiltinEncodings) / sizeof(*__CFBuiltinEncodings)) + numICUConverters, platformConverters, sizeof(CFStringEncoding) * numPlatformConverters);
+                CFAllocatorDeallocate(NULL, platformConverters);
+            }
+
+            CFQSortArray(list, numSlots, sizeof(CFStringEncoding), (CFComparatorFunction)__CFStringEncodingComparator, NULL);
+            __CFStringEncodingFliterDupes(list, numSlots);
+        }
+        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, list, (void * volatile *)&encodings) && (list != __CFBuiltinEncodings)) CFAllocatorDeallocate(NULL, list);
+    }
+
+    return encodings;
+}
 
 #undef TO_BYTE
 #undef TO_UNICODE
index 22cf1aa5f525840dc1a8edab410a3cf609298ddb..2334029ff50bfa06a184dd775d5c0ea0716f9133 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringEncodingConverter.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERTER__)
@@ -34,19 +34,22 @@ CF_EXTERN_C_BEGIN
 
 /* Values for flags argument for the conversion functions below.  These can be combined, but the three NonSpacing behavior flags are exclusive.
 */
+// kCFStringEncodingBasicDirectionLeftToRight ~ kCFStringEncodingPrependBOM will probably be deprecated and superceded by kCFStringEncodingPartialInput flag
 enum {
-    kCFStringEncodingAllowLossyConversion = 1, // Uses fallback functions to substitutes non mappable chars
-    kCFStringEncodingBasicDirectionLeftToRight = (1 << 1), // Converted with original direction left-to-right.
-    kCFStringEncodingBasicDirectionRightToLeft = (1 << 2), // Converted with original direction right-to-left.
-    kCFStringEncodingSubstituteCombinings = (1 << 3), // Uses fallback function to combining chars.
-    kCFStringEncodingComposeCombinings = (1 << 4), // Checks mappable precomposed equivalents for decomposed sequences.  This is the default behavior.
-    kCFStringEncodingIgnoreCombinings = (1 << 5), // Ignores combining chars.
-    kCFStringEncodingUseCanonical = (1 << 6), // Always use canonical form
-    kCFStringEncodingUseHFSPlusCanonical = (1 << 7), // Always use canonical form but leaves 0x2000 ranges
-    kCFStringEncodingPrependBOM = (1 << 8), // Prepend BOM sequence (i.e. ISO2022KR)
-    kCFStringEncodingDisableCorporateArea = (1 << 9), // Disable the usage of 0xF8xx area for Apple proprietary chars in converting to UniChar, resulting loosely mapping.
-    kCFStringEncodingASCIICompatibleConversion = (1 << 10), // This flag forces strict ASCII compatible converion. i.e. MacJapanese 0x5C maps to Unicode 0x5C.
-    kCFStringEncodingLenientUTF8Conversion = (1 << 11) // 10.1 (Puma) compatible lenient UTF-8 conversion.
+    kCFStringEncodingAllowLossyConversion = (1UL << 0), // Uses fallback functions to substitutes non mappable chars
+    kCFStringEncodingBasicDirectionLeftToRight = (1UL << 1), // Converted with original direction left-to-right.
+    kCFStringEncodingBasicDirectionRightToLeft = (1UL << 2), // Converted with original direction right-to-left.
+    kCFStringEncodingSubstituteCombinings = (1UL << 3), // Uses fallback function to combining chars.
+    kCFStringEncodingComposeCombinings = (1UL << 4), // Checks mappable precomposed equivalents for decomposed sequences.  This is the default behavior.
+    kCFStringEncodingIgnoreCombinings = (1UL << 5), // Ignores combining chars.
+    kCFStringEncodingUseCanonical = (1UL << 6), // Always use canonical form
+    kCFStringEncodingUseHFSPlusCanonical = (1UL << 7), // Always use canonical form but leaves 0x2000 ranges
+    kCFStringEncodingPrependBOM = (1UL << 8), // Prepend BOM sequence (i.e. ISO2022KR)
+    kCFStringEncodingDisableCorporateArea = (1UL << 9), // Disable the usage of 0xF8xx area for Apple proprietary chars in converting to UniChar, resulting loosely mapping.
+    kCFStringEncodingASCIICompatibleConversion = (1UL << 10), // This flag forces strict ASCII compatible converion. i.e. MacJapanese 0x5C maps to Unicode 0x5C.
+    kCFStringEncodingLenientUTF8Conversion = (1UL << 11), // 10.1 (Puma) compatible lenient UTF-8 conversion.
+    kCFStringEncodingPartialInput = (1UL << 12), // input buffer is a part of stream
+    kCFStringEncodingPartialOutput = (1UL << 13) // output buffer streaming
 };
 
 /* Return values for CFStringEncodingUnicodeToBytes & CFStringEncodingBytesToUnicode functions
@@ -63,43 +66,43 @@ enum {
 #define CFStringEncodingLossyByteToMask(lossByte)      ((uint32_t)(lossByte << 24)|kCFStringEncodingAllowLossyConversion)
 #define CFStringEncodingMaskToLossyByte(flags)         ((uint8_t)(flags >> 24))
 
+/* Macros for streaming support
+ */
+#define CFStringEncodingStreamIDMask                    (0x00FF0000)
+#define CFStringEncodingStreamIDFromMask(mask)    ((mask >> 16) & 0xFF)
+#define CFStringEncodingStreamIDToMask(identifier)            ((uint32_t)((identifier & 0xFF) << 16))
+
 /* Converts characters into the specified encoding.  Returns the constants defined above.
 If maxByteLen is 0, bytes is ignored. You can pass lossyByte by passing the value in flags argument.
 i.e. CFStringEncodingUnicodeToBytes(encoding, CFStringEncodingLossyByteToMask(lossByte), ....)
 */
-extern uint32_t CFStringEncodingUnicodeToBytes(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen);
+CF_EXPORT uint32_t CFStringEncodingUnicodeToBytes(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen);
 
 /* Converts bytes in the specified encoding into unicode.  Returns the constants defined above.
 maxCharLen & usdCharLen are in UniChar length, not byte length.
 If maxCharLen is 0, characters is ignored.
 */
-extern uint32_t CFStringEncodingBytesToUnicode(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen);
+CF_EXPORT uint32_t CFStringEncodingBytesToUnicode(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen);
 
 /* Fallback functions used when allowLossy
 */
 typedef CFIndex (*CFStringEncodingToBytesFallbackProc)(const UniChar *characters, CFIndex numChars, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen);
 typedef CFIndex (*CFStringEncodingToUnicodeFallbackProc)(const uint8_t *bytes, CFIndex numBytes, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen);
 
-extern bool CFStringEncodingIsValidEncoding(uint32_t encoding);
+CF_EXPORT bool CFStringEncodingIsValidEncoding(uint32_t encoding);
 
 /* Returns kCFStringEncodingInvalidId terminated encoding list
 */
-extern const uint32_t *CFStringEncodingListOfAvailableEncodings(void);
-
-extern const char *CFStringEncodingName(uint32_t encoding);
-
-/* Returns NULL-terminated list of IANA registered canonical names
-*/
-extern const char **CFStringEncodingCanonicalCharsetNames(uint32_t encoding);
+CF_EXPORT const CFStringEncoding *CFStringEncodingListOfAvailableEncodings(void);
 
 /* Returns required length of destination buffer for conversion.  These functions are faster than specifying 0 to maxByteLen (maxCharLen), but unnecessarily optimal length
 */
-extern CFIndex CFStringEncodingCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes);
-extern CFIndex CFStringEncodingByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars);
+CF_EXPORT CFIndex CFStringEncodingCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes);
+CF_EXPORT CFIndex CFStringEncodingByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars);
 
 /* Can register functions used for lossy conversion.  Reregisters default procs if NULL
 */
-extern void CFStringEncodingRegisterFallbackProcedures(uint32_t encoding, CFStringEncodingToBytesFallbackProc toBytes, CFStringEncodingToUnicodeFallbackProc toUnicode);
+CF_EXPORT void CFStringEncodingRegisterFallbackProcedures(uint32_t encoding, CFStringEncodingToBytesFallbackProc toBytes, CFStringEncodingToUnicodeFallbackProc toUnicode);
 
 CF_EXTERN_C_END
 
index 0df8580dd6895373b0116d8ee70d650210fe64fa..c394cee7eb3029855c9dcc36018950f22127b2e9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringEncodingConverterExt.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERETEREXT__)
@@ -38,7 +38,8 @@ enum {
     kCFStringEncodingConverterCheapEightBit = 1,
     kCFStringEncodingConverterStandardEightBit = 2,
     kCFStringEncodingConverterCheapMultiByte = 3,
-    kCFStringEncodingConverterPlatformSpecific = 4 // Other fields are ignored
+    kCFStringEncodingConverterPlatformSpecific = 4, // Other fields are ignored
+    kCFStringEncodingConverterICU = 5 // Other fields are ignored
 };
 
 /* kCFStringEncodingConverterStandard */
@@ -75,7 +76,6 @@ typedef struct {
     CFStringEncodingIsValidCombiningCharacterProc isValidCombiningChar;
 } CFStringEncodingConverter;
 
-
 extern const CFStringEncodingConverter *CFStringEncodingGetConverter(uint32_t encoding);
 
 enum {
@@ -91,8 +91,6 @@ extern const void *CFStringEncodingGetAddressForSelector(uint32_t selector);
 #define BOOTSTRAPFUNC_NAME     CFStringEncodingBootstrap
 typedef const CFStringEncodingConverter* (*CFStringEncodingBootstrapProc)(uint32_t encoding, const void *getSelector);
 
-extern uint32_t CFStringEncodingGetScriptCodeForEncoding(CFStringEncoding encoding);
-
 /* Latin precomposition */
 /* This function does not precompose recursively nor to U+01E0 and U+01E1.
 */
index c53f830bc32b84e38dc77dbffc986513908af0bb..a8a6ccb83fb640c4286d8d63fd4551259232573c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringEncodingConverterPriv.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERTERPRIV__)
 #include <CoreFoundation/CFBase.h>
 #include "CFStringEncodingConverterExt.h"
 
-#define MAX_IANA_ALIASES (4)
-
-typedef CFIndex (*_CFToBytesProc)(const void *converter, uint32_t flags, const UniChar *characters, CFIndex numChars, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen);
-typedef CFIndex (*_CFToUnicodeProc)(const void *converter, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen);
-
-typedef struct {
-    _CFToBytesProc toBytes;
-    _CFToUnicodeProc toUnicode;
-    _CFToUnicodeProc toCanonicalUnicode;
-    void *_toBytes; // original proc
-    void *_toUnicode; // original proc
-    uint16_t maxLen;
-    uint16_t :16;
-    CFStringEncodingToBytesLenProc toBytesLen;
-    CFStringEncodingToUnicodeLenProc toUnicodeLen;
-    CFStringEncodingToBytesFallbackProc toBytesFallback;
-    CFStringEncodingToUnicodeFallbackProc toUnicodeFallback;
-    CFStringEncodingToBytesPrecomposeProc toBytesPrecompose;
-    CFStringEncodingIsValidCombiningCharacterProc isValidCombiningChar;
-} _CFEncodingConverter;
-
-typedef struct {
-    uint32_t encoding;
-    _CFEncodingConverter *converter;
-    const char *encodingName;
-    const char *ianaNames[MAX_IANA_ALIASES];
-    const char *loadablePath;
-    CFStringEncodingBootstrapProc bootstrap;
-    CFStringEncodingToBytesFallbackProc toBytesFallback;
-    CFStringEncodingToUnicodeFallbackProc toUnicodeFallback;
-    uint32_t scriptCode;
-} _CFConverterEntry;
-
-extern const CFStringEncodingConverter __CFConverterASCII;
-extern const CFStringEncodingConverter __CFConverterISOLatin1;
-extern const CFStringEncodingConverter __CFConverterMacRoman;
-extern const CFStringEncodingConverter __CFConverterWinLatin1;
-extern const CFStringEncodingConverter __CFConverterNextStepLatin;
-extern const CFStringEncodingConverter __CFConverterUTF8;
-
+extern  const CFStringEncodingConverter __CFConverterASCII;
+extern  const CFStringEncodingConverter __CFConverterISOLatin1;
+extern  const CFStringEncodingConverter __CFConverterMacRoman;
+extern  const CFStringEncodingConverter __CFConverterWinLatin1;
+extern  const CFStringEncodingConverter __CFConverterNextStepLatin;
+extern  const CFStringEncodingConverter __CFConverterUTF8;
+
+extern  CFStringEncoding *__CFStringEncodingCreateListOfAvailablePlatformConverters(CFAllocatorRef allocator, CFIndex *numberOfConverters);
+extern  const CFStringEncodingConverter *__CFStringEncodingGetExternalConverter(uint32_t encoding);
+extern  CFIndex __CFStringEncodingPlatformUnicodeToBytes(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars, CFIndex *usedCharLen, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen);
+extern  CFIndex __CFStringEncodingPlatformBytesToUnicode(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, CFIndex *usedByteLen, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen);
+extern  CFIndex __CFStringEncodingPlatformCharLengthForBytes(uint32_t encoding, uint32_t flags, const uint8_t *bytes, CFIndex numBytes);
+extern  CFIndex __CFStringEncodingPlatformByteLengthForCharacters(uint32_t encoding, uint32_t flags, const UniChar *characters, CFIndex numChars);
 
 #endif /* ! __COREFOUNDATION_CFSTRINGENCODINGCONVERTERPRIV__ */
 
diff --git a/CFStringEncodingDatabase.c b/CFStringEncodingDatabase.c
new file mode 100644 (file)
index 0000000..715edd5
--- /dev/null
@@ -0,0 +1,859 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*
+ *  CFStringEncodingDatabase.c
+ *  CoreFoundation
+ *
+ *  Created by Aki Inoue on 07/12/05.
+ *  Copyright 2007-2009, Apple Inc. All rights reserved.
+ *
+ */
+
+#include "CFInternal.h"
+#include <CoreFoundation/CFStringEncodingExt.h>
+#include "CFStringEncodingConverterPriv.h"
+#include "CFStringEncodingDatabase.h"
+#include <stdio.h>
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#define strncasecmp_l(a, b, c, d) _strnicmp(a, b, c)
+#define snprintf _snprintf
+#endif
+
+#define ISO8859CODEPAGE_BASE (28590)
+
+static const uint16_t __CFKnownEncodingList[] = {
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacJapanese,
+    kCFStringEncodingMacChineseTrad,
+    kCFStringEncodingMacKorean,
+    kCFStringEncodingMacArabic,
+    kCFStringEncodingMacHebrew,
+    kCFStringEncodingMacGreek,
+    kCFStringEncodingMacCyrillic,
+    kCFStringEncodingMacDevanagari,
+    kCFStringEncodingMacGurmukhi,
+    kCFStringEncodingMacGujarati,
+    kCFStringEncodingMacOriya,
+    kCFStringEncodingMacBengali,
+    kCFStringEncodingMacTamil,
+    kCFStringEncodingMacTelugu,
+    kCFStringEncodingMacKannada,
+    kCFStringEncodingMacMalayalam,
+    kCFStringEncodingMacSinhalese,
+    kCFStringEncodingMacBurmese,
+    kCFStringEncodingMacKhmer,
+    kCFStringEncodingMacThai,
+    kCFStringEncodingMacLaotian,
+    kCFStringEncodingMacGeorgian,
+    kCFStringEncodingMacArmenian,
+    kCFStringEncodingMacChineseSimp,
+    kCFStringEncodingMacTibetan,
+    kCFStringEncodingMacMongolian,
+    kCFStringEncodingMacEthiopic,
+    kCFStringEncodingMacCentralEurRoman,
+    kCFStringEncodingMacVietnamese,
+    kCFStringEncodingMacSymbol,
+    kCFStringEncodingMacDingbats,
+    kCFStringEncodingMacTurkish,
+    kCFStringEncodingMacCroatian,
+    kCFStringEncodingMacIcelandic,
+    kCFStringEncodingMacRomanian,
+    kCFStringEncodingMacCeltic,
+    kCFStringEncodingMacGaelic,
+    kCFStringEncodingMacFarsi,
+    kCFStringEncodingMacUkrainian,
+    kCFStringEncodingMacInuit,
+    
+    kCFStringEncodingDOSLatinUS,
+    kCFStringEncodingDOSGreek,
+    kCFStringEncodingDOSBalticRim,
+    kCFStringEncodingDOSLatin1,
+    kCFStringEncodingDOSGreek1,
+    kCFStringEncodingDOSLatin2,
+    kCFStringEncodingDOSCyrillic,
+    kCFStringEncodingDOSTurkish,
+    kCFStringEncodingDOSPortuguese,
+    kCFStringEncodingDOSIcelandic,
+    kCFStringEncodingDOSHebrew,
+    kCFStringEncodingDOSCanadianFrench,
+    kCFStringEncodingDOSArabic,
+    kCFStringEncodingDOSNordic,
+    kCFStringEncodingDOSRussian,
+    kCFStringEncodingDOSGreek2,
+    kCFStringEncodingDOSThai,
+    kCFStringEncodingDOSJapanese,
+    kCFStringEncodingDOSChineseSimplif,
+    kCFStringEncodingDOSKorean,
+    kCFStringEncodingDOSChineseTrad,
+    
+    kCFStringEncodingWindowsLatin1,
+    kCFStringEncodingWindowsLatin2,
+    kCFStringEncodingWindowsCyrillic,
+    kCFStringEncodingWindowsGreek,
+    kCFStringEncodingWindowsLatin5,
+    kCFStringEncodingWindowsHebrew,
+    kCFStringEncodingWindowsArabic,
+    kCFStringEncodingWindowsBalticRim,
+    kCFStringEncodingWindowsVietnamese,
+    kCFStringEncodingWindowsKoreanJohab,
+    kCFStringEncodingASCII,
+    
+    kCFStringEncodingShiftJIS_X0213,
+    kCFStringEncodingGB_18030_2000,
+    
+    kCFStringEncodingISO_2022_JP,
+    kCFStringEncodingISO_2022_JP_2,
+    kCFStringEncodingISO_2022_JP_1,
+    kCFStringEncodingISO_2022_JP_3,
+    kCFStringEncodingISO_2022_CN,
+    kCFStringEncodingISO_2022_CN_EXT,
+    kCFStringEncodingISO_2022_KR,
+    kCFStringEncodingEUC_JP,
+    kCFStringEncodingEUC_CN,
+    kCFStringEncodingEUC_TW,
+    kCFStringEncodingEUC_KR,
+    
+    kCFStringEncodingShiftJIS,
+
+    kCFStringEncodingKOI8_R,
+
+    kCFStringEncodingBig5,
+
+    kCFStringEncodingMacRomanLatin1,
+    kCFStringEncodingHZ_GB_2312,
+    kCFStringEncodingBig5_HKSCS_1999,
+    kCFStringEncodingVISCII,
+    kCFStringEncodingKOI8_U,
+    kCFStringEncodingBig5_E,
+    kCFStringEncodingUTF7_IMAP,
+    
+    kCFStringEncodingNextStepLatin,
+    
+    kCFStringEncodingEBCDIC_CP037
+};
+
+// Windows codepage mapping
+static const uint16_t __CFWindowsCPList[] = {
+    10000,
+    10001,
+    10002,
+    10003,
+    10004,
+    10005,
+    10006,
+    10007,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    10021,
+    0,
+    0,
+    0,
+    10008,
+    0,
+    0,
+    0,
+    10029,
+    0,
+    0,
+    0,
+    10081,
+    10082,
+    10079,
+    10010,
+    0,
+    0,
+    0,
+    10017,
+    0,
+    
+    437,
+    737,
+    775,
+    850,
+    851,
+    852,
+    855,
+    857,
+    860,
+    861,
+    862,
+    863,
+    864,
+    865,
+    866,
+    869,
+    874,
+    932,
+    936,
+    949,
+    950,
+    
+    1252,
+    1250,
+    1251,
+    1253,
+    1254,
+    1255,
+    1256,
+    1257,
+    1258,
+    1361,
+
+    20127,
+    
+    0,
+    54936,
+    
+    50221, // we prefere this over 50220/50221 since that's what CF coverter generates
+    0,
+    0,
+    0,
+    50227,
+    0,
+    50225,
+    
+    51932,
+    51936,
+    51950,
+    51949,
+    
+    0,
+
+    20866,
+
+    0,
+
+    0,
+    52936,
+    0,
+    0,
+    21866,
+    0,
+    0,
+    
+    0,
+    
+    37
+};
+
+// Canonical name
+static const char *__CFCanonicalNameList[] = {
+    "macintosh",
+    "japanese",
+    "trad-chinese",
+    "korean",
+    "arabic",
+    "hebrew",
+    "greek",
+    "cyrillic",
+    "devanagari",
+    "gurmukhi",
+    "gujarati",
+    "oriya",
+    "bengali",
+    "tamil",
+    "telugu",
+    "kannada",
+    "malayalam",
+    "sinhalese",
+    "burmese",
+    "khmer",
+    "thai",
+    "laotian",
+    "georgian",
+    "armenian",
+    "simp-chinese",
+    "tibetan",
+    "mongolian",
+    "ethiopic",
+    "centraleurroman",
+    "vietnamese",
+    "symbol",
+    "dingbats",
+    "turkish",
+    "croatian",
+    "icelandic",
+    "romanian",
+    "celtic",
+    "gaelic",
+    "farsi",
+    "ukrainian",
+    "inuit",
+    
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    
+    "us-ascii",
+    
+    NULL,
+    "gb18030",
+    
+    "iso-2022-jp",
+    "iso-2022-jp-2",
+    "iso-2022-jp-1",
+    "iso-2022-jp-3",
+    "iso-2022-cn",
+    "iso-2022-cn-ext",
+    "iso-2022-kr",
+    "euc-jp",
+    "gb2312",
+    "euc-tw",
+    "euc-kr",
+    
+    "shift_jis",
+
+    "koi8-r",
+
+    "big5",
+
+    "roman-latin1",
+    "hz-gb-2312",
+    "big5-hkscs",
+    "viscii",
+    "koi8-u",
+    NULL,
+    "utf7-imap",
+    
+    "x-nextstep",
+    
+    "ibm037",
+};
+
+static inline CFIndex __CFGetEncodingIndex(CFStringEncoding encoding) {
+    const uint16_t *head = __CFKnownEncodingList;
+    const uint16_t *tail = head + ((sizeof(__CFKnownEncodingList) / sizeof(*__CFKnownEncodingList)) - 1);
+    const uint16_t *middle;
+
+    encoding &= 0x0FFF;
+    while (head <= tail) {
+        middle = head + ((tail - head) >> 1);
+
+        if (encoding == *middle) {
+            return middle - __CFKnownEncodingList;
+        } else if (encoding < *middle) {
+            tail = middle - 1;
+        } else {
+            head = middle + 1;
+        }
+    }
+
+    return kCFNotFound;
+}
+
+__private_extern__ uint16_t __CFStringEncodingGetWindowsCodePage(CFStringEncoding encoding) {
+    CFStringEncoding encodingBase = encoding & 0x0F00;
+
+    if (0x0100 == encodingBase) { // UTF
+        switch (encoding) {
+            case kCFStringEncodingUTF7: return 65000;
+            case kCFStringEncodingUTF8: return 65001;
+            case kCFStringEncodingUTF16: return 1200;
+            case kCFStringEncodingUTF16BE: return 1201;
+            case kCFStringEncodingUTF32: return 65005;
+            case kCFStringEncodingUTF32BE: return 65006;
+        }        
+    } else if (0x0200 == encodingBase) { // ISO 8859 range
+        return ISO8859CODEPAGE_BASE + (encoding & 0xFF);
+    } else { // others
+        CFIndex index = __CFGetEncodingIndex(encoding);
+
+        if (kCFNotFound != index) return __CFWindowsCPList[index];
+    }
+
+    return 0;
+}
+
+__private_extern__ CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uint16_t codepage) {
+    switch (codepage) {
+        case 65001: return kCFStringEncodingUTF8;
+        case 1200: return kCFStringEncodingUTF16;
+        case 0: return kCFStringEncodingInvalidId;
+        case 1201: return kCFStringEncodingUTF16BE;
+        case 65005: return kCFStringEncodingUTF32;
+        case 65006: return kCFStringEncodingUTF32BE;
+        case 65000: return kCFStringEncodingUTF7;
+    }
+
+    if ((codepage > ISO8859CODEPAGE_BASE) && (codepage <= (ISO8859CODEPAGE_BASE + 16))) {
+        return (codepage - ISO8859CODEPAGE_BASE) + 0x0200;
+    } else {
+        static CFMutableDictionaryRef mappingTable = NULL;
+        static CFSpinLock_t lock = CFSpinLockInit;
+        uintptr_t value;
+
+        __CFSpinLock(&lock);
+        if (NULL == mappingTable) {
+            CFIndex index, count = sizeof(__CFKnownEncodingList) / sizeof(*__CFKnownEncodingList);
+            
+            mappingTable = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+
+            for (index = 0;index < count;index++) {
+                if (0 != __CFWindowsCPList[index]) CFDictionarySetValue(mappingTable, (const void *)(uintptr_t)__CFWindowsCPList[index], (const void *)(uintptr_t)__CFKnownEncodingList[index]);
+            }
+        }
+        __CFSpinUnlock(&lock);
+
+        if (CFDictionaryGetValueIfPresent(mappingTable, (const void *)(uintptr_t)codepage, (const void **)&value)) return (CFStringEncoding)value;
+    }
+
+
+    return kCFStringEncodingInvalidId;
+}
+
+__private_extern__ bool __CFStringEncodingGetCanonicalName(CFStringEncoding encoding, char *buffer, CFIndex bufferSize) {
+    const char *format = "%s";
+    const char *name = NULL;
+    uint32_t value = 0;
+    CFIndex index;
+
+    switch (encoding & 0x0F00) {
+        case 0x0100: // UTF range
+            switch (encoding) {
+                case kCFStringEncodingUTF7: name = "utf-7"; break;
+                case kCFStringEncodingUTF8: name = "utf-8"; break;
+                case kCFStringEncodingUTF16: name = "utf-16"; break;
+                case kCFStringEncodingUTF16BE: name = "utf-16be"; break;
+                case kCFStringEncodingUTF16LE: name = "utf-16le"; break;
+                case kCFStringEncodingUTF32: name = "utf-32"; break;
+                case kCFStringEncodingUTF32BE: name = "utf-32be"; break;
+                case kCFStringEncodingUTF32LE: name = "utf-32le"; break;
+            }
+            break;
+
+        case 0x0200: // ISO 8859 range
+            format = "iso-8859-%d";
+            value = (encoding & 0xFF);
+            break;
+
+        case 0x0400: // DOS code page range
+        case 0x0500: // Windows code page range
+            index = __CFGetEncodingIndex(encoding);
+            
+            if (kCFNotFound != index) {
+                value = __CFWindowsCPList[index];
+                if (0 != value) format = ((0x0400 == (encoding & 0x0F00)) ? "cp%d" : "windows-%d");
+            }
+            break;
+
+        default: // others
+            index = __CFGetEncodingIndex(encoding);
+
+            if (kCFNotFound != index) {
+                if (((0 == (encoding & 0x0F00)) && (kCFStringEncodingMacRoman != encoding)) || (kCFStringEncodingMacRomanLatin1 == encoding)) format = "x-mac-%s";
+                name = (const char *)__CFCanonicalNameList[index];
+            }
+            break;
+    }
+
+    if ((0 == value) && (NULL == name)) {
+        return false;
+    } else if (0 != value) {
+        return ((snprintf(buffer, bufferSize, format, value) < bufferSize) ? true : false);
+    } else {
+        return ((snprintf(buffer, bufferSize, format, name) < bufferSize) ? true : false);
+    }
+}
+
+#define LENGTH_LIMIT (256)
+static Boolean __CFCanonicalNameCompare(const void *value1, const void *value2) { return ((0 == strncasecmp_l((const char *)value1, (const char *)value2, LENGTH_LIMIT, NULL)) ? true : false); }
+
+static CFHashCode __CFCanonicalNameHash(const void *value) {
+    const char *name = (const char *)value;
+    CFHashCode code = 0;
+
+    while ((0 != *name) && ((name - (const char *)value) < LENGTH_LIMIT)) {
+        char character = *(name++);
+
+        code += (character + (((character >= 'A') && (character <= 'Z')) ? 'a' - 'A' : 0));
+    }
+
+    return code * (name - (const char *)value);
+}
+
+__private_extern__ CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *canonicalName) {
+    CFStringEncoding encoding;
+    CFIndex prefixLength;
+    static CFMutableDictionaryRef mappingTable = NULL;
+    static CFSpinLock_t lock = CFSpinLockInit;
+
+    prefixLength = strlen("iso-8859-");
+    if (0 == strncasecmp_l(canonicalName, "iso-8859-", prefixLength, NULL)) {// do ISO
+        encoding = strtol(canonicalName + prefixLength, NULL, 10);
+
+        return (((0 == encoding) || (encoding > 16)) ? kCFStringEncodingInvalidId : encoding + 0x0200);
+    }
+
+    prefixLength = strlen("cp");
+    if (0 == strncasecmp_l(canonicalName, "cp", prefixLength, NULL)) {// do DOS
+        encoding = strtol(canonicalName + prefixLength, NULL, 10);
+
+        return __CFStringEncodingGetFromWindowsCodePage(encoding);
+    }
+
+    prefixLength = strlen("windows-");
+    if (0 == strncasecmp_l(canonicalName, "windows-", prefixLength, NULL)) {// do DOS
+        encoding = strtol(canonicalName + prefixLength, NULL, 10);
+        
+        return __CFStringEncodingGetFromWindowsCodePage(encoding);
+    }
+    
+    __CFSpinLock(&lock);
+    if (NULL == mappingTable) {
+        CFIndex index, count = sizeof(__CFKnownEncodingList) / sizeof(*__CFKnownEncodingList);
+
+        CFDictionaryKeyCallBacks keys = {
+            0, NULL, NULL, NULL, &__CFCanonicalNameCompare, &__CFCanonicalNameHash
+        };
+
+        mappingTable = CFDictionaryCreateMutable(NULL, 0, &keys, NULL);
+
+        // Add UTFs
+        CFDictionarySetValue(mappingTable, "utf-7", (const void *)kCFStringEncodingUTF7);
+        CFDictionarySetValue(mappingTable, "utf-8", (const void *)kCFStringEncodingUTF8);
+        CFDictionarySetValue(mappingTable, "utf-16", (const void *)kCFStringEncodingUTF16);
+        CFDictionarySetValue(mappingTable, "utf-16be", (const void *)kCFStringEncodingUTF16BE);
+        CFDictionarySetValue(mappingTable, "utf-16le", (const void *)kCFStringEncodingUTF16LE);
+        CFDictionarySetValue(mappingTable, "utf-32", (const void *)kCFStringEncodingUTF32);
+        CFDictionarySetValue(mappingTable, "utf-32be", (const void *)kCFStringEncodingUTF32BE);
+        CFDictionarySetValue(mappingTable, "utf-32le", (const void *)kCFStringEncodingUTF32LE);
+
+        for (index = 0;index < count;index++) {
+            if (NULL != __CFCanonicalNameList[index]) CFDictionarySetValue(mappingTable, (const void *)(uintptr_t)__CFCanonicalNameList[index], (const void *)(uintptr_t)__CFKnownEncodingList[index]);
+        }
+    }
+    __CFSpinUnlock(&lock);
+
+    if (0 == strncasecmp_l(canonicalName, "macintosh", sizeof("macintosh") - 1, NULL)) return kCFStringEncodingMacRoman;
+
+    
+    prefixLength = strlen("x-mac-");
+    encoding = (CFStringEncoding)(CFIndex)CFDictionaryGetValue(mappingTable, canonicalName + ((0 == strncasecmp_l(canonicalName, "x-mac-", prefixLength, NULL)) ? prefixLength : 0));
+
+    return ((0 == encoding) ? kCFStringEncodingInvalidId : encoding);
+}
+#undef LENGTH_LIMIT
+
+#if DEPLOYMENT_TARGET_MACOSX
+// This list indexes from DOS range
+static uint16_t __CFISO8859SimilarScriptList[] = {
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacCentralEurRoman,
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacCentralEurRoman,
+    kCFStringEncodingMacCyrillic,
+    kCFStringEncodingMacArabic,
+    kCFStringEncodingMacGreek,
+    kCFStringEncodingMacHebrew,
+    kCFStringEncodingMacTurkish,
+    kCFStringEncodingMacInuit,
+    kCFStringEncodingMacThai,
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacCentralEurRoman,
+    kCFStringEncodingMacCeltic,
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacRomanian};
+
+static uint16_t __CFOtherSimilarScriptList[] = {
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacGreek,
+    kCFStringEncodingMacCentralEurRoman,
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacGreek,
+    kCFStringEncodingMacCentralEurRoman,
+    kCFStringEncodingMacCyrillic,
+    kCFStringEncodingMacTurkish,
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacIcelandic,
+    kCFStringEncodingMacHebrew,
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacArabic,
+    kCFStringEncodingMacInuit,
+    kCFStringEncodingMacCyrillic,
+    kCFStringEncodingMacGreek,
+    kCFStringEncodingMacThai,
+    kCFStringEncodingMacJapanese,
+    kCFStringEncodingMacChineseSimp,
+    kCFStringEncodingMacKorean,
+    kCFStringEncodingMacChineseTrad,
+    
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacCentralEurRoman,
+    kCFStringEncodingMacCyrillic,
+    kCFStringEncodingMacGreek,
+    kCFStringEncodingMacTurkish,
+    kCFStringEncodingMacHebrew,
+    kCFStringEncodingMacArabic,
+    kCFStringEncodingMacCentralEurRoman,
+    kCFStringEncodingMacVietnamese,
+    kCFStringEncodingMacKorean,
+
+    kCFStringEncodingMacRoman,
+
+    kCFStringEncodingMacJapanese,
+    kCFStringEncodingMacChineseSimp,
+    
+    kCFStringEncodingMacJapanese,
+    kCFStringEncodingMacJapanese,
+    kCFStringEncodingMacJapanese,
+    kCFStringEncodingMacJapanese,
+    kCFStringEncodingMacChineseSimp,
+    kCFStringEncodingMacChineseSimp,
+    kCFStringEncodingMacKorean,
+    kCFStringEncodingMacJapanese,
+    kCFStringEncodingMacChineseSimp,
+    kCFStringEncodingMacChineseTrad,
+    kCFStringEncodingMacKorean,
+
+    kCFStringEncodingMacJapanese,
+
+    kCFStringEncodingMacCyrillic,
+
+    kCFStringEncodingMacChineseTrad,
+
+    kCFStringEncodingMacRoman,
+    kCFStringEncodingMacChineseSimp,
+    kCFStringEncodingMacChineseTrad,
+    kCFStringEncodingMacVietnamese,
+    kCFStringEncodingMacUkrainian,
+    kCFStringEncodingMacChineseTrad,
+    kCFStringEncodingMacRoman,
+    
+    kCFStringEncodingMacRoman,
+    
+    kCFStringEncodingMacRoman
+};
+
+static const char *__CFISONameList[] = {
+    "Western (ISO Latin 1)",
+    "Central European (ISO Latin 2)",
+    "Western (ISO Latin 3)",
+    "Central European (ISO Latin 4)",
+    "Cyrillic (ISO 8859-5)",
+    "Arabic (ISO 8859-6)",
+    "Greek (ISO 8859-7)",
+    "Hebrew (ISO 8859-8)",
+    "Turkish (ISO Latin 5)",
+    "Nordic (ISO Latin 6)",
+    "Thai (ISO 8859-11)",
+    NULL,
+    "Baltic (ISO Latin 7)",
+    "Celtic (ISO Latin 8)",
+    "Western (ISO Latin 9)",
+    "Romanian (ISO Latin 10)",
+};
+
+static const char *__CFOtherNameList[] = {
+    "Western (Mac OS Roman)",
+    "Japanese (Mac OS)",
+    "Traditional Chinese (Mac OS)",
+    "Korean (Mac OS)",
+    "Arabic (Mac OS)",
+    "Hebrew (Mac OS)",
+    "Greek (Mac OS)",
+    "Cyrillic (Mac OS)",
+    "Devanagari (Mac OS)",
+    "Gurmukhi (Mac OS)",
+    "Gujarati (Mac OS)",
+    "Oriya (Mac OS)",
+    "Bengali (Mac OS)",
+    "Tamil (Mac OS)",
+    "Telugu (Mac OS)",
+    "Kannada (Mac OS)",
+    "Malayalam (Mac OS)",
+    "Sinhalese (Mac OS)",
+    "Burmese (Mac OS)",
+    "Khmer (Mac OS)",
+    "Thai (Mac OS)",
+    "Laotian (Mac OS)",
+    "Georgian (Mac OS)",
+    "Armenian (Mac OS)",
+    "Simplified Chinese (Mac OS)",
+    "Tibetan (Mac OS)",
+    "Mongolian (Mac OS)",
+    "Ethiopic (Mac OS)",
+    "Central European (Mac OS)",
+    "Vietnamese (Mac OS)",
+    "Symbol (Mac OS)",
+    "Dingbats (Mac OS)",
+    "Turkish (Mac OS)",
+    "Croatian (Mac OS)",
+    "Icelandic (Mac OS)",
+    "Romanian (Mac OS)",
+    "Celtic (Mac OS)",
+    "Gaelic (Mac OS)",
+    "Farsi (Mac OS)",
+    "Cyrillic (Mac OS Ukrainian)",
+    "Inuit (Mac OS)",
+    "Latin-US (DOS)",
+    "Greek (DOS)",
+    "Baltic (DOS)",
+    "Western (DOS Latin 1)",
+    "Greek (DOS Greek 1)",
+    "Central European (DOS Latin 2)",
+    "Cyrillic (DOS)",
+    "Turkish (DOS)",
+    "Portuguese (DOS)",
+    "Icelandic (DOS)",
+    "Hebrew (DOS)",
+    "Canadian French (DOS)",
+    "Arabic (DOS)",
+    "Nordic (DOS)",
+    "Russian (DOS)",
+    "Greek (DOS Greek 2)",
+    "Thai (Windows, DOS)",
+    "Japanese (Windows, DOS)",
+    "Simplified Chinese (Windows, DOS)",
+    "Korean (Windows, DOS)",
+    "Traditional Chinese (Windows, DOS)",
+    "Western (Windows Latin 1)",
+    "Central European (Windows Latin 2)",
+    "Cyrillic (Windows)",
+    "Greek (Windows)",
+    "Turkish (Windows Latin 5)",
+    "Hebrew (Windows)",
+    "Arabic (Windows)",
+    "Baltic (Windows)",
+    "Vietnamese (Windows)",
+    "Korean (Windows Johab)",
+    "Western (ASCII)",
+    "Japanese (Shift JIS X0213)",
+    "Chinese (GB 18030)",
+    "Japanese (ISO 2022-JP)",
+    "Japanese (ISO 2022-JP-2)",
+    "Japanese (ISO 2022-JP-1)",
+    "Japanese (ISO 2022-JP-3)",
+    "Chinese (ISO 2022-CN)",
+    "Chinese (ISO 2022-CN-EXT)",
+    "Korean (ISO 2022-KR)",
+    "Japanese (EUC)",
+    "Simplified Chinese (GB 2312)",
+    "Traditional Chinese (EUC)",
+    "Korean (EUC)",
+    "Japanese (Shift JIS)",
+    "Cyrillic (KOI8-R)",
+    "Traditional Chinese (Big 5)",
+    "Western (Mac Mail)",
+    "Simplified Chinese (HZ GB 2312)",
+    "Traditional Chinese (Big 5 HKSCS)",
+    NULL,
+    "Ukrainian (KOI8-U)",
+    "Traditional Chinese (Big 5-E)",
+    NULL,
+    "Western (NextStep)",
+    "Western (EBCDIC Latin 1)",
+};
+#endif /* DEPLOYMENT_TARGET_MACOSX */
+
+__private_extern__ CFStringEncoding __CFStringEncodingGetMostCompatibleMacScript(CFStringEncoding encoding) {
+#if DEPLOYMENT_TARGET_MACOSX
+    switch (encoding & 0x0F00) {
+        case 0: return encoding & 0xFF; break; // Mac scripts
+
+        case 0x0100: return kCFStringEncodingUnicode; break; // Unicode
+
+        case 0x200: // ISO 8859
+            return (((encoding & 0xFF) <= (sizeof(__CFISO8859SimilarScriptList) / sizeof(*__CFISO8859SimilarScriptList))) ? __CFISO8859SimilarScriptList[(encoding & 0xFF) - 1] : kCFStringEncodingInvalidId);
+            break;
+
+        default: {
+            CFIndex index = __CFGetEncodingIndex(encoding);
+            
+            if (kCFNotFound != index) {
+                index -= __CFGetEncodingIndex(kCFStringEncodingDOSLatinUS);
+                return __CFOtherSimilarScriptList[index];
+            }
+        }
+    }
+#endif /* DEPLOYMENT_TARGET_MACOSX */
+
+    return kCFStringEncodingInvalidId;
+}
+
+__private_extern__ const char *__CFStringEncodingGetName(CFStringEncoding encoding) {
+    switch (encoding) {
+        case kCFStringEncodingUTF8: return "Unicode (UTF-8)"; break;
+        case kCFStringEncodingUTF16: return "Unicode (UTF-16)"; break;
+        case kCFStringEncodingUTF16BE: return "Unicode (UTF-16BE)"; break;
+        case kCFStringEncodingUTF16LE: return "Unicode (UTF-16LE)"; break;
+        case kCFStringEncodingUTF32: return "Unicode (UTF-32)"; break;
+        case kCFStringEncodingUTF32BE: return "Unicode (UTF-32BE)"; break;
+        case kCFStringEncodingUTF32LE: return "Unicode (UTF-32LE)"; break;
+        case kCFStringEncodingNonLossyASCII: return "Non-lossy ASCII"; break;
+        case kCFStringEncodingUTF7: return "Unicode (UTF-7)"; break;
+    }
+
+#if DEPLOYMENT_TARGET_MACOSX
+    if (0x0200 == (encoding & 0x0F00)) {
+        encoding &= 0x00FF;
+
+        if (encoding <= (sizeof(__CFISONameList) / sizeof(*__CFISONameList))) return __CFISONameList[encoding - 1];
+    } else {
+        CFIndex index = __CFGetEncodingIndex(encoding);
+
+        if (kCFNotFound != index) return __CFOtherNameList[index];
+    }
+#endif /* DEPLOYMENT_TARGET_MACOSX */
+    
+    return NULL;
+}
diff --git a/CFStringEncodingDatabase.h b/CFStringEncodingDatabase.h
new file mode 100644 (file)
index 0000000..69dc960
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*
+ *  CFStringEncodingDatabase.h
+ *  CoreFoundation
+ *
+ *  Created by Aki Inoue on 07/12/05.
+ *  Copyright (c) 2007-2009, Apple Inc. All rights reserved.
+ *
+ */
+
+#include <CoreFoundation/CFString.h>
+
+__private_extern__ uint16_t __CFStringEncodingGetWindowsCodePage(CFStringEncoding encoding);
+__private_extern__ CFStringEncoding __CFStringEncodingGetFromWindowsCodePage(uint16_t codepage);
+
+__private_extern__ bool __CFStringEncodingGetCanonicalName(CFStringEncoding encoding, char *buffer, CFIndex bufferSize);
+__private_extern__ CFStringEncoding __CFStringEncodingGetFromCanonicalName(const char *canonicalName);
+
+__private_extern__ CFStringEncoding __CFStringEncodingGetMostCompatibleMacScript(CFStringEncoding encoding);
+
+__private_extern__ const char *__CFStringEncodingGetName(CFStringEncoding encoding); // Returns simple non-localizd name
index 79d7c24fd2e2dc031988bd0001a099e687ea4117..4a00e00bc6a8f284424bddbad04f4e9f4c4c2396 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringEncodingExt.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFSTRINGENCODINGEXT__)
@@ -200,6 +200,11 @@ enum {
     kCFStringEncodingEBCDIC_US = 0x0C01,       /* basic EBCDIC-US */
     kCFStringEncodingEBCDIC_CP037 = 0x0C02,    /* code page 037, extended EBCDIC (Latin-1 set) for US,Canada... */
 
+#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED
+    kCFStringEncodingUTF7 = 0x04000100, /* kTextEncodingUnicodeDefault + kUnicodeUTF7Format RFC2152 */
+    kCFStringEncodingUTF7_IMAP = 0x0A10, /* UTF-7 (IMAP folder variant) RFC3501 */
+#endif /* MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED */
+
     /* Deprecated constants */
     kCFStringEncodingShiftJIS_X0213_00 = 0x0628 /* Shift-JIS format encoding of JIS X0213 planes 1 and 2 (DEPRECATED) */
 };
index 1814473dd98fd4c26ed640962b615d5440cd2736..47fb7cf20d781fe3cc789ea5d6d8304e3ff3c81f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringEncodings.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Aki Inoue
 */
 
 #include "CFInternal.h"
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFByteOrder.h>
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include <string.h>
-#include "CFStringEncodingConverterExt.h"
-#include "CFUniChar.h"
-#include "CFUnicodeDecomposition.h"
+#include <CoreFoundation/CFStringEncodingConverterExt.h>
+#include <CoreFoundation/CFUniChar.h>
+#include <CoreFoundation/CFUnicodeDecomposition.h>
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <xlocale.h>
+#include <CoreFoundation/CFStringDefaultEncoding.h>
+#endif
 
 static UInt32 __CFWantsToUseASCIICompatibleConversion = (UInt32)-1;
 CF_INLINE UInt32 __CFGetASCIICompatibleFlag(void) {
@@ -50,7 +61,7 @@ Boolean (*__CFCharToUniCharFunc)(UInt32 flags, uint8_t ch, UniChar *unicodeChar)
 
 // To avoid early initialization issues, we just initialize this here
 // This should not be const as it is changed
-UniChar __CFCharToUniCharTable[256] = {
+__private_extern__ UniChar __CFCharToUniCharTable[256] = {
   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
@@ -69,7 +80,7 @@ UniChar __CFCharToUniCharTable[256] = {
 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
 };    
 
-void __CFSetCharToUniCharFunc(Boolean (*func)(UInt32 flags, UInt8 ch, UniChar *unicodeChar)) {
+__private_extern__ void __CFSetCharToUniCharFunc(Boolean (*func)(UInt32 flags, UInt8 ch, UniChar *unicodeChar)) {
     if (__CFCharToUniCharFunc != func) {
         int ch;
         __CFCharToUniCharFunc = func;
@@ -119,6 +130,10 @@ enum {
 };
 
 Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringEncoding encoding, Boolean alwaysUnicode, CFVarWidthCharBuffer *buffer, Boolean *useClientsMemoryPtr, UInt32 converterFlags) {
+    CFIndex idx;
+    const uint8_t *chars = (const uint8_t *)bytes;
+    const uint8_t *end = chars + len;
+    Boolean result = TRUE;
 
     if (useClientsMemoryPtr) *useClientsMemoryPtr = false;
 
@@ -176,6 +191,7 @@ Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringE
                 if (NULL == buffer->chars.ascii) { // we never reallocate when buffer is supplied
                     if (buffer->numChars > MAX_LOCAL_CHARS) {
                         buffer->chars.ascii = (UInt8 *)CFAllocatorAllocate(buffer->allocator, (buffer->numChars * sizeof(uint8_t)), 0);
+                       if (!buffer->chars.ascii) goto memoryErrorExit;
                         buffer->shouldFreeChars = true;
                     } else {
                         buffer->chars.ascii = (uint8_t *)buffer->localBuffer;
@@ -194,6 +210,7 @@ Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringE
                 if (NULL == buffer->chars.unicode) { // we never reallocate when buffer is supplied
                     if (buffer->numChars > MAX_LOCAL_UNICHARS) {
                         buffer->chars.unicode = (UniChar *)CFAllocatorAllocate(buffer->allocator, (buffer->numChars * sizeof(UTF16Char)), 0);
+                       if (!buffer->chars.unicode) goto memoryErrorExit;
                         buffer->shouldFreeChars = true;
                     } else {
                         buffer->chars.unicode = (UTF16Char *)buffer->localBuffer;
@@ -244,7 +261,7 @@ Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringE
                 if (*characters & asciiMask) {
                     buffer->isASCII = false;
                     if (*characters & bmpMask) {
-                        if (strictUTF32 && ((swap ? (UTF32Char)CFSwapInt32(*characters) : *characters) > 0x10FFFF)) return false; // outside of Unicode Scaler Value
+                        if (strictUTF32 && ((swap ? (UTF32Char)CFSwapInt32(*characters) : *characters) > 0x10FFFF)) return false; // outside of Unicode Scaler Value. Haven't allocated buffer, yet.
                         ++(buffer->numChars);
                     }
                 }
@@ -257,6 +274,7 @@ Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringE
             if (NULL == buffer->chars.ascii) { // we never reallocate when buffer is supplied
                 if (buffer->numChars > MAX_LOCAL_CHARS) {
                     buffer->chars.ascii = (UInt8 *)CFAllocatorAllocate(buffer->allocator, (buffer->numChars * sizeof(uint8_t)), 0);
+                   if (!buffer->chars.ascii) goto memoryErrorExit;
                     buffer->shouldFreeChars = true;
                 } else {
                     buffer->chars.ascii = (uint8_t *)buffer->localBuffer;
@@ -273,33 +291,73 @@ Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringE
             if (NULL == buffer->chars.unicode) { // we never reallocate when buffer is supplied
                 if (buffer->numChars > MAX_LOCAL_UNICHARS) {
                     buffer->chars.unicode = (UniChar *)CFAllocatorAllocate(buffer->allocator, (buffer->numChars * sizeof(UTF16Char)), 0);
+                   if (!buffer->chars.unicode) goto memoryErrorExit;
                     buffer->shouldFreeChars = true;
                 } else {
                     buffer->chars.unicode = (UTF16Char *)buffer->localBuffer;
                 }
             }
-            return (CFUniCharFromUTF32(src, limit - src, buffer->chars.unicode, (strictUTF32 ? false : true), __CF_BIG_ENDIAN__ ? !swap : swap) ? TRUE : FALSE);
+            result = (CFUniCharFromUTF32(src, limit - src, buffer->chars.unicode, (strictUTF32 ? false : true), __CF_BIG_ENDIAN__ ? !swap : swap) ? TRUE : FALSE);
         }
-    } else {
-        CFIndex idx;
-        const uint8_t *chars = (const uint8_t *)bytes;
-        const uint8_t *end = chars + len;
-    
-        switch (encoding) {
-        case kCFStringEncodingNonLossyASCII: {
-            UTF16Char currentValue = 0;
-            uint8_t character;
-            int8_t mode = __NSNonLossyASCIIMode;
-    
-            buffer->isASCII = false;
+    } else if (kCFStringEncodingUTF8 == encoding) {    
+        if ((len >= 3) && (chars[0] == 0xef) && (chars[1] == 0xbb) && (chars[2] == 0xbf)) {    // If UTF8 BOM, skip
+            chars += 3;
+            len -= 3;
+            if (0 == len) return true;
+        }
+        if (buffer->isASCII) {
+            for (idx = 0; idx < len; idx++) {
+                if (128 <= chars[idx]) {
+                    buffer->isASCII = false;
+                    break;
+                }
+            }
+        }
+        if (buffer->isASCII) {
+            buffer->numChars = len;
+            buffer->shouldFreeChars = !buffer->chars.ascii && (len <= MAX_LOCAL_CHARS) ? false : true;
+            buffer->chars.ascii = (buffer->chars.ascii ? buffer->chars.ascii : (len <= MAX_LOCAL_CHARS) ? (uint8_t *)buffer->localBuffer : (UInt8 *)CFAllocatorAllocate(buffer->allocator, len * sizeof(uint8_t), 0));
+           if (!buffer->chars.ascii) goto memoryErrorExit;
+            memmove(buffer->chars.ascii, chars, len * sizeof(uint8_t));
+        } else {
+            CFIndex numDone;
+            static CFStringEncodingToUnicodeProc __CFFromUTF8 = NULL;
+            
+            if (!__CFFromUTF8) {
+                const CFStringEncodingConverter *converter = CFStringEncodingGetConverter(kCFStringEncodingUTF8);
+                __CFFromUTF8 = (CFStringEncodingToUnicodeProc)converter->toUnicode;
+            }
+            
             buffer->shouldFreeChars = !buffer->chars.unicode && (len <= MAX_LOCAL_UNICHARS) ? false : true;
             buffer->chars.unicode = (buffer->chars.unicode ? buffer->chars.unicode : (len <= MAX_LOCAL_UNICHARS) ? (UniChar *)buffer->localBuffer : (UniChar *)CFAllocatorAllocate(buffer->allocator, len * sizeof(UniChar), 0));
+           if (!buffer->chars.unicode) goto memoryErrorExit;
             buffer->numChars = 0;
-    
             while (chars < end) {
-                character = (*chars++);
-    
-                switch (mode) {
+                numDone = 0;
+                chars += __CFFromUTF8(converterFlags, chars, end - chars, &(buffer->chars.unicode[buffer->numChars]), len - buffer->numChars, &numDone);
+                
+                if (0 == numDone) {
+                    result = FALSE;
+                    break;
+                }
+                buffer->numChars += numDone;
+            }
+        }
+    } else if (kCFStringEncodingNonLossyASCII == encoding) {
+        UTF16Char currentValue = 0;
+        uint8_t character;
+        int8_t mode = __NSNonLossyASCIIMode;
+        
+        buffer->isASCII = false;
+        buffer->shouldFreeChars = !buffer->chars.unicode && (len <= MAX_LOCAL_UNICHARS) ? false : true;
+        buffer->chars.unicode = (buffer->chars.unicode ? buffer->chars.unicode : (len <= MAX_LOCAL_UNICHARS) ? (UniChar *)buffer->localBuffer : (UniChar *)CFAllocatorAllocate(buffer->allocator, len * sizeof(UniChar), 0));
+       if (!buffer->chars.unicode) goto memoryErrorExit;
+        buffer->numChars = 0;
+        
+        while (chars < end) {
+            character = (*chars++);
+            
+            switch (mode) {
                 case __NSNonLossyASCIIMode:
                     if (character == '\\') {
                         mode = __NSNonLossyBackslashMode;
@@ -309,8 +367,8 @@ Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringE
                         mode = __NSNonLossyErrorMode;
                     }
                     break;
-    
-                case __NSNonLossyBackslashMode:
+                    
+                    case __NSNonLossyBackslashMode:
                     if ((character == 'U') || (character == 'u')) {
                         mode = __NSNonLossyHexInitialMode;
                         currentValue = 0;
@@ -324,8 +382,8 @@ Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringE
                         mode = __NSNonLossyErrorMode;
                     }
                     break;
-    
-                default:
+                    
+                    default:
                     if (mode < __NSNonLossyHexFinalMode) {
                         if ((character >= '0') && (character <= '9')) {
                             currentValue = (currentValue << 4) | (character - '0');
@@ -348,135 +406,90 @@ Boolean __CFStringDecodeByteStream3(const uint8_t *bytes, CFIndex len, CFStringE
                         }
                     }
                     break;
-                }
-    
-                if (mode == __NSNonLossyASCIIMode) {
-                    buffer->chars.unicode[buffer->numChars++] = currentValue;
-                } else if (mode == __NSNonLossyErrorMode) {
-                    return false;
-                }
             }
-            return (mode == __NSNonLossyASCIIMode);
-        }
-    
-        case kCFStringEncodingUTF8:
-            if ((len >= 3) && (chars[0] == 0xef) && (chars[1] == 0xbb) && (chars[2] == 0xbf)) {        // If UTF8 BOM, skip
-                chars += 3;
-                len -= 3;
-                if (0 == len) return true;
+            
+            if (mode == __NSNonLossyASCIIMode) {
+                buffer->chars.unicode[buffer->numChars++] = currentValue;
+            } else if (mode == __NSNonLossyErrorMode) {
+                break;
             }
-            if (buffer->isASCII) {
-                for (idx = 0; idx < len; idx++) {
-                    if (128 <= chars[idx]) {
-                        buffer->isASCII = false;
-                        break;
-                    }
+        }
+        result = ((mode == __NSNonLossyASCIIMode) ? YES : NO);
+    } else {
+        const CFStringEncodingConverter *converter = CFStringEncodingGetConverter(encoding);
+        
+        if (!converter) return false;
+        
+        Boolean isASCIISuperset = __CFStringEncodingIsSupersetOfASCII(encoding);
+        
+        if (!isASCIISuperset) buffer->isASCII = false;
+        
+        if (buffer->isASCII) {
+            for (idx = 0; idx < len; idx++) {
+                if (128 <= chars[idx]) {
+                    buffer->isASCII = false;
+                    break;
                 }
             }
+        }
+        
+        if (converter->encodingClass == kCFStringEncodingConverterCheapEightBit) {
             if (buffer->isASCII) {
                 buffer->numChars = len;
                 buffer->shouldFreeChars = !buffer->chars.ascii && (len <= MAX_LOCAL_CHARS) ? false : true;
                 buffer->chars.ascii = (buffer->chars.ascii ? buffer->chars.ascii : (len <= MAX_LOCAL_CHARS) ? (uint8_t *)buffer->localBuffer : (UInt8 *)CFAllocatorAllocate(buffer->allocator, len * sizeof(uint8_t), 0));
+               if (!buffer->chars.ascii) goto memoryErrorExit;
                 memmove(buffer->chars.ascii, chars, len * sizeof(uint8_t));
             } else {
-                CFIndex numDone;
-                static CFStringEncodingToUnicodeProc __CFFromUTF8 = NULL;
-    
-                if (!__CFFromUTF8) {
-                    const CFStringEncodingConverter *converter = CFStringEncodingGetConverter(kCFStringEncodingUTF8);
-                    __CFFromUTF8 = (CFStringEncodingToUnicodeProc)converter->toUnicode;
-                }
-    
                 buffer->shouldFreeChars = !buffer->chars.unicode && (len <= MAX_LOCAL_UNICHARS) ? false : true;
                 buffer->chars.unicode = (buffer->chars.unicode ? buffer->chars.unicode : (len <= MAX_LOCAL_UNICHARS) ? (UniChar *)buffer->localBuffer : (UniChar *)CFAllocatorAllocate(buffer->allocator, len * sizeof(UniChar), 0));
-                buffer->numChars = 0;
-                while (chars < end) {
-                    numDone = 0;
-                    chars += __CFFromUTF8(converterFlags, chars, end - chars, &(buffer->chars.unicode[buffer->numChars]), len - buffer->numChars, &numDone);
-    
-                    if (0 == numDone) {
-                        if (buffer->shouldFreeChars) CFAllocatorDeallocate(buffer->allocator, buffer->chars.unicode);
-                        buffer->isASCII = !alwaysUnicode;
-                        buffer->shouldFreeChars = false;
-                        buffer->chars.ascii = NULL;
-                        buffer->numChars = 0;
-                        return false;
-                    }
-                    buffer->numChars += numDone;
-                }
-            }
-            break;
-    
-        default:
-            if (CFStringEncodingIsValidEncoding(encoding)) {
-                const CFStringEncodingConverter *converter = CFStringEncodingGetConverter(encoding);
-                Boolean isASCIISuperset = __CFStringEncodingIsSupersetOfASCII(encoding);
-                
-                if (!converter) return false;
-    
-                if (!isASCIISuperset) buffer->isASCII = false;
-
-                if (buffer->isASCII) {
+               if (!buffer->chars.unicode) goto memoryErrorExit;
+                buffer->numChars = len;
+                if (kCFStringEncodingASCII == encoding || kCFStringEncodingISOLatin1 == encoding) {
+                    for (idx = 0; idx < len; idx++) buffer->chars.unicode[idx] = (UniChar)chars[idx];
+                } else {
                     for (idx = 0; idx < len; idx++) {
-                        if (128 <= chars[idx]) {
-                            buffer->isASCII = false;
+                        if (chars[idx] < 0x80 && isASCIISuperset) {
+                            buffer->chars.unicode[idx] = (UniChar)chars[idx];
+                        } else if (!((CFStringEncodingCheapEightBitToUnicodeProc)converter->toUnicode)(0, chars[idx], buffer->chars.unicode + idx)) {
+                            result = FALSE;
                             break;
                         }
                     }
                 }
-
-                if (converter->encodingClass == kCFStringEncodingConverterCheapEightBit) {
-                    if (buffer->isASCII) {
-                        buffer->numChars = len;
-                        buffer->shouldFreeChars = !buffer->chars.ascii && (len <= MAX_LOCAL_CHARS) ? false : true;
-                        buffer->chars.ascii = (buffer->chars.ascii ? buffer->chars.ascii : (len <= MAX_LOCAL_CHARS) ? (uint8_t *)buffer->localBuffer : (UInt8 *)CFAllocatorAllocate(buffer->allocator, len * sizeof(uint8_t), 0));
-                        memmove(buffer->chars.ascii, chars, len * sizeof(uint8_t));
-                    } else {
-                        buffer->shouldFreeChars = !buffer->chars.unicode && (len <= MAX_LOCAL_UNICHARS) ? false : true;
-                        buffer->chars.unicode = (buffer->chars.unicode ? buffer->chars.unicode : (len <= MAX_LOCAL_UNICHARS) ? (UniChar *)buffer->localBuffer : (UniChar *)CFAllocatorAllocate(buffer->allocator, len * sizeof(UniChar), 0));
-                        buffer->numChars = len;
-                        if (kCFStringEncodingASCII == encoding || kCFStringEncodingISOLatin1 == encoding) {
-                            for (idx = 0; idx < len; idx++) buffer->chars.unicode[idx] = (UniChar)chars[idx];
-                        } else {
-                            for (idx = 0; idx < len; idx++)
-                                if (chars[idx] < 0x80 && isASCIISuperset)
-                                    buffer->chars.unicode[idx] = (UniChar)chars[idx];
-                                else if (!((CFStringEncodingCheapEightBitToUnicodeProc)converter->toUnicode)(0, chars[idx], buffer->chars.unicode + idx))
-                                    return false;
-                        }
-                    }
-                } else {
-                    if (buffer->isASCII) {
-                        buffer->numChars = len;
-                        buffer->shouldFreeChars = !buffer->chars.ascii && (len <= MAX_LOCAL_CHARS) ? false : true;
-                        buffer->chars.ascii = (buffer->chars.ascii ? buffer->chars.ascii : (len <= MAX_LOCAL_CHARS) ? (uint8_t *)buffer->localBuffer : (UInt8 *)CFAllocatorAllocate(buffer->allocator, len * sizeof(uint8_t), 0));
-                        memmove(buffer->chars.ascii, chars, len * sizeof(uint8_t));
-                    } else {
-                        CFIndex guessedLength = CFStringEncodingCharLengthForBytes(encoding, 0, bytes, len);
-                        static UInt32 lossyFlag = (UInt32)-1;
-    
-                        buffer->shouldFreeChars = !buffer->chars.unicode && (guessedLength <= MAX_LOCAL_UNICHARS) ? false : true;
-                        buffer->chars.unicode = (buffer->chars.unicode ? buffer->chars.unicode : (guessedLength <= MAX_LOCAL_UNICHARS) ? (UniChar *)buffer->localBuffer : (UniChar *)CFAllocatorAllocate(buffer->allocator, guessedLength * sizeof(UniChar), 0));
-    
-                        if (lossyFlag == (UInt32)-1) lossyFlag = (_CFExecutableLinkedOnOrAfter(CFSystemVersionPanther) ? 0 : kCFStringEncodingAllowLossyConversion);
-    
-                        if (CFStringEncodingBytesToUnicode(encoding, lossyFlag|__CFGetASCIICompatibleFlag(), bytes, len, NULL, buffer->chars.unicode, (guessedLength > MAX_LOCAL_UNICHARS ? guessedLength : MAX_LOCAL_UNICHARS), &(buffer->numChars))) {
-                            if (buffer->shouldFreeChars) CFAllocatorDeallocate(buffer->allocator, buffer->chars.unicode);
-                            buffer->isASCII = !alwaysUnicode;
-                            buffer->shouldFreeChars = false;
-                            buffer->chars.ascii = NULL;
-                            buffer->numChars = 0;
-                            return false;
-                        }
-                    }
-                }
+            }
+        } else {
+            if (buffer->isASCII) {
+                buffer->numChars = len;
+                buffer->shouldFreeChars = !buffer->chars.ascii && (len <= MAX_LOCAL_CHARS) ? false : true;
+                buffer->chars.ascii = (buffer->chars.ascii ? buffer->chars.ascii : (len <= MAX_LOCAL_CHARS) ? (uint8_t *)buffer->localBuffer : (UInt8 *)CFAllocatorAllocate(buffer->allocator, len * sizeof(uint8_t), 0));
+               if (!buffer->chars.ascii) goto memoryErrorExit;
+                memmove(buffer->chars.ascii, chars, len * sizeof(uint8_t));
             } else {
-                return false;
+                CFIndex guessedLength = CFStringEncodingCharLengthForBytes(encoding, 0, bytes, len);
+                static UInt32 lossyFlag = (UInt32)-1;
+                
+                buffer->shouldFreeChars = !buffer->chars.unicode && (guessedLength <= MAX_LOCAL_UNICHARS) ? false : true;
+                buffer->chars.unicode = (buffer->chars.unicode ? buffer->chars.unicode : (guessedLength <= MAX_LOCAL_UNICHARS) ? (UniChar *)buffer->localBuffer : (UniChar *)CFAllocatorAllocate(buffer->allocator, guessedLength * sizeof(UniChar), 0));
+               if (!buffer->chars.unicode) goto memoryErrorExit;
+                
+                if (lossyFlag == (UInt32)-1) lossyFlag = (_CFExecutableLinkedOnOrAfter(CFSystemVersionPanther) ? 0 : kCFStringEncodingAllowLossyConversion);
+                
+                if (CFStringEncodingBytesToUnicode(encoding, lossyFlag|__CFGetASCIICompatibleFlag(), bytes, len, NULL, buffer->chars.unicode, (guessedLength > MAX_LOCAL_UNICHARS ? guessedLength : MAX_LOCAL_UNICHARS), &(buffer->numChars))) result = FALSE;
             }
         }
     }
 
-    return true;
+    if (FALSE == result) {
+memoryErrorExit:       // Added for <rdar://problem/6581621>, but it's not clear whether an exception would be a better option
+       result = FALSE; // In case we come here from a goto
+        if (buffer->shouldFreeChars && buffer->chars.unicode) CFAllocatorDeallocate(buffer->allocator, buffer->chars.unicode);
+        buffer->isASCII = !alwaysUnicode;
+        buffer->shouldFreeChars = false;
+        buffer->chars.ascii = NULL;
+        buffer->numChars = 0;
+    }
+    return result;
 }
 
 
@@ -631,6 +644,8 @@ CFIndex __CFStringEncodeByteStream(CFStringRef string, CFIndex rangeLoc, CFIndex
         const unsigned char *cString = NULL;
         Boolean isASCIISuperset = __CFStringEncodingIsSupersetOfASCII(encoding);
 
+        if (!CFStringEncodingIsValidEncoding(encoding)) return 0;
+
         if (!CF_IS_OBJC(CFStringGetTypeID(), string) && isASCIISuperset) { // Checking for NSString to avoid infinite recursion
             const unsigned char *ptr;
             if ((cString = (const unsigned char *)CFStringGetCStringPtr(string, __CFStringGetEightBitStringEncoding()))) {
@@ -641,7 +656,9 @@ CFIndex __CFStringEncodeByteStream(CFStringRef string, CFIndex rangeLoc, CFIndex
                     if (usedBufLen) *usedBufLen = numCharsProcessed;
                     return numCharsProcessed;
                 }
-                while (*ptr < 0x80 && rangeLen > 0) {
+               
+                CFIndex uninterestingTailLen = buffer ? (rangeLen - MIN(max, rangeLen)) : 0;
+                while (*ptr < 0x80 && rangeLen > uninterestingTailLen) {
                     ++ptr;
                     --rangeLen;
                 }
@@ -694,18 +711,15 @@ CFIndex __CFStringEncodeByteStream(CFStringRef string, CFIndex rangeLoc, CFIndex
         flags = (lossByte ? ((unsigned char)lossByte == 0xFF && encoding == kCFStringEncodingASCII ? kCFStringEncodingAllowLossyConversion : CFStringEncodingLossyByteToMask(lossByte)) : 0) | (generatingExternalFile ? kCFStringEncodingPrependBOM : 0) | (isASCIISuperset ? 0 : __CFGetASCIICompatibleFlag());
 
         if (!cString && (cString = (const unsigned char *)CFStringGetCharactersPtr(string))) { // Must be Unicode string
-            if (CFStringEncodingIsValidEncoding(encoding)) { // Converter available in CF
-                CFStringEncodingUnicodeToBytes(encoding, flags, (const UniChar *)cString + rangeLoc, rangeLen, &numCharsProcessed, buffer, max, &totalBytesWritten);
-            } else {
-                return 0;
-            }
+            CFStringEncodingUnicodeToBytes(encoding, flags, (const UniChar *)cString + rangeLoc, rangeLen, &numCharsProcessed, buffer, max, &totalBytesWritten);
         } else {
             UniChar charBuf[kCFCharConversionBufferLength];
             CFIndex currentLength;
             CFIndex usedLen;
             CFIndex lastUsedLen = 0, lastNumChars = 0;
             uint32_t result;
-            Boolean isCFBuiltin = CFStringEncodingIsValidEncoding(encoding);
+            uint32_t streamingMask;
+            uint32_t streamID = 0;
 #define MAX_DECOMP_LEN (6)
 
             while (rangeLen > 0) {
@@ -715,61 +729,69 @@ CFIndex __CFStringEncodeByteStream(CFStringRef string, CFIndex rangeLoc, CFIndex
                 // could be in the middle of surrogate pair; back up.
                 if ((rangeLen > kCFCharConversionBufferLength) && CFUniCharIsSurrogateHighCharacter(charBuf[kCFCharConversionBufferLength - 1])) --currentLength;
 
-                if (isCFBuiltin) { // Converter available in CF
-                    if ((result = CFStringEncodingUnicodeToBytes(encoding, flags, charBuf, currentLength, &numChars, buffer, max, &usedLen)) != kCFStringEncodingConversionSuccess) {
-                        if (kCFStringEncodingInvalidInputStream == result) {
-                            CFRange composedRange;
-                            // Check the tail
-                            if ((rangeLen > kCFCharConversionBufferLength) && ((currentLength - numChars) < MAX_DECOMP_LEN)) {
-                                composedRange = CFStringGetRangeOfComposedCharactersAtIndex(string, rangeLoc + currentLength);
-
-                                if ((composedRange.length <= MAX_DECOMP_LEN) && (composedRange.location < (rangeLoc + numChars))) {
-                                    result = CFStringEncodingUnicodeToBytes(encoding, flags, charBuf, composedRange.location - rangeLoc, &numChars, buffer, max, &usedLen);
-                                }
+                streamingMask = ((rangeLen > currentLength) ? kCFStringEncodingPartialInput : 0)|CFStringEncodingStreamIDToMask(streamID);
+
+                result = CFStringEncodingUnicodeToBytes(encoding, flags|streamingMask, charBuf, currentLength, &numChars, buffer, max, &usedLen);
+                streamID = CFStringEncodingStreamIDFromMask(result);
+                result &= ~CFStringEncodingStreamIDMask;
+
+                if (result != kCFStringEncodingConversionSuccess) {
+                    if (kCFStringEncodingInvalidInputStream == result) {
+                        CFRange composedRange;
+                        // Check the tail
+                        if ((rangeLen > kCFCharConversionBufferLength) && ((currentLength - numChars) < MAX_DECOMP_LEN)) {
+                            composedRange = CFStringGetRangeOfComposedCharactersAtIndex(string, rangeLoc + currentLength);
+                            
+                            if ((composedRange.length <= MAX_DECOMP_LEN) && (composedRange.location < (rangeLoc + numChars))) {
+                                result = CFStringEncodingUnicodeToBytes(encoding, flags|streamingMask, charBuf, composedRange.location - rangeLoc, &numChars, buffer, max, &usedLen);
+                                streamID = CFStringEncodingStreamIDFromMask(result);
+                                result &= ~CFStringEncodingStreamIDMask;
                             }
-
-                            // Check the head
-                            if ((kCFStringEncodingConversionSuccess != result) && (lastNumChars > 0) && (numChars < MAX_DECOMP_LEN)) {
-                                composedRange = CFStringGetRangeOfComposedCharactersAtIndex(string, rangeLoc);
-
-                                if ((composedRange.length <= MAX_DECOMP_LEN) && (composedRange.location < rangeLoc)) {
-                                    // Try if the composed range can be converted
-                                    CFStringGetCharacters(string, composedRange, charBuf);
-
-                                    if (CFStringEncodingUnicodeToBytes(encoding, flags, charBuf, composedRange.length, &numChars, NULL, 0, &usedLen) == kCFStringEncodingConversionSuccess) { // OK let's try the last run
-                                        CFIndex lastRangeLoc = rangeLoc - lastNumChars;
-
-                                        currentLength = composedRange.location - lastRangeLoc;
-                                        CFStringGetCharacters(string, CFRangeMake(lastRangeLoc, currentLength), charBuf);
-
-                                        if ((result = CFStringEncodingUnicodeToBytes(encoding, flags, charBuf, currentLength, &numChars, (max ? buffer - lastUsedLen : NULL), (max ? max + lastUsedLen : 0), &usedLen)) == kCFStringEncodingConversionSuccess) { // OK let's try the last run
-                                            // Looks good. back up
-                                            totalBytesWritten -= lastUsedLen;
-                                            numCharsProcessed -= lastNumChars;
-
-                                            rangeLoc = lastRangeLoc;
-                                            rangeLen += lastNumChars;
-
-                                            if (max) {
-                                                buffer -= lastUsedLen;
-                                                max += lastUsedLen;
-                                            }
+                        }
+                        
+                        // Check the head
+                        if ((kCFStringEncodingConversionSuccess != result) && (lastNumChars > 0) && (numChars < MAX_DECOMP_LEN)) {
+                            composedRange = CFStringGetRangeOfComposedCharactersAtIndex(string, rangeLoc);
+                            
+                            if ((composedRange.length <= MAX_DECOMP_LEN) && (composedRange.location < rangeLoc)) {
+                                // Try if the composed range can be converted
+                                CFStringGetCharacters(string, composedRange, charBuf);
+                                
+                                if (CFStringEncodingUnicodeToBytes(encoding, flags, charBuf, composedRange.length, &numChars, NULL, 0, &usedLen) == kCFStringEncodingConversionSuccess) { // OK let's try the last run
+                                    CFIndex lastRangeLoc = rangeLoc - lastNumChars;
+                                    
+                                    currentLength = composedRange.location - lastRangeLoc;
+                                    CFStringGetCharacters(string, CFRangeMake(lastRangeLoc, currentLength), charBuf);
+
+                                    result = CFStringEncodingUnicodeToBytes(encoding, flags|streamingMask, charBuf, currentLength, &numChars, (max ? buffer - lastUsedLen : NULL), (max ? max + lastUsedLen : 0), &usedLen);
+                                    streamID = CFStringEncodingStreamIDFromMask(result);
+                                    result &= ~CFStringEncodingStreamIDMask;
+
+                                    if (result == kCFStringEncodingConversionSuccess) { // OK let's try the last run
+                                        // Looks good. back up
+                                        totalBytesWritten -= lastUsedLen;
+                                        numCharsProcessed -= lastNumChars;
+                                        
+                                        rangeLoc = lastRangeLoc;
+                                        rangeLen += lastNumChars;
+                                        
+                                        if (max) {
+                                            buffer -= lastUsedLen;
+                                            max += lastUsedLen;
                                         }
                                     }
                                 }
                             }
                         }
-
-                        if (kCFStringEncodingConversionSuccess != result) { // really failed
-                            totalBytesWritten += usedLen;
-                            numCharsProcessed += numChars;
-                            break;
-                        }
                     }
-                } else {
-                    return 0;
+                    
+                    if (kCFStringEncodingConversionSuccess != result) { // really failed
+                        totalBytesWritten += usedLen;
+                        numCharsProcessed += numChars;
+                        break;
+                    }
                 }
-
+                
                 totalBytesWritten += usedLen;
                 numCharsProcessed += numChars;
 
@@ -799,14 +821,16 @@ CFIndex CFStringGetMaximumSizeOfFileSystemRepresentation(CFStringRef string) {
     switch (enc) {
        case kCFStringEncodingASCII:
        case kCFStringEncodingMacRoman:
-           return len * 3 + 1;
+            if (len > (LONG_MAX - 1L) / 3L) return kCFNotFound;     // Avoid wrap-around
+           return len * 3L + 1L;
        default:
-           return len * 9 + 1;
+            if (len > (LONG_MAX - 1L) / 9L) return kCFNotFound;     // Avoid wrap-around
+           return len * 9L + 1L;
     }
 } 
 
 Boolean CFStringGetFileSystemRepresentation(CFStringRef string, char *buffer, CFIndex maxBufLen) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define MAX_STACK_BUFFER_LEN   (255)
     const UTF16Char *characters = CFStringGetCharactersPtr(string);
     const char *bufferLimit = buffer + maxBufLen;
@@ -851,12 +875,161 @@ Boolean CFStringGetFileSystemRepresentation(CFStringRef string, char *buffer, CF
     } else {
         return false;
     }
-#else __MACH__
+#else
     return CFStringGetCString(string, buffer, maxBufLen, CFStringFileSystemEncoding());
-#endif __MACH__
+#endif
 }
 
 Boolean _CFStringGetFileSystemRepresentation(CFStringRef string, uint8_t *buffer, CFIndex maxBufLen) {
     return CFStringGetFileSystemRepresentation(string, (char *)buffer, maxBufLen);
 }
 
+
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+
+/* This function is used to obtain users' default script/region code.
+   The function first looks at environment variable __kCFUserEncodingEnvVariableName, then, reads the configuration file in user's home directory.
+*/
+void _CFStringGetUserDefaultEncoding(UInt32 *oScriptValue, UInt32 *oRegionValue) {
+    char *stringValue;
+    char buffer[__kCFMaxDefaultEncodingFileLength];
+    int uid = getuid();
+
+    if ((stringValue = getenv(__kCFUserEncodingEnvVariableName)) != NULL) {
+        if ((uid == strtol_l(stringValue, &stringValue, 0, NULL)) && (':' == *stringValue)) {
+            ++stringValue;
+        } else {
+            stringValue = NULL;
+        }
+    }
+
+    if ((stringValue == NULL) && ((uid > 0) || getenv("HOME"))) {
+        char passwdExtraBuf[1000 + MAXPATHLEN];  // Extra memory buffer for getpwuid_r(); no clue as to how large this should be...
+        struct passwd passwdBuf, *passwdp = NULL;
+
+        switch (getpwuid_r((uid_t)uid, &passwdBuf, passwdExtraBuf, sizeof(passwdExtraBuf), &passwdp)) {
+            case 0:         // Success
+                break;  
+            case ERANGE:    // Somehow we didn't give it enough memory; let the system handle the storage this time; but beware 5778609
+                passwdp = getpwuid((uid_t)uid); 
+                break;
+            default:
+                passwdp = NULL;
+        }
+        if (passwdp) {
+            char filename[MAXPATHLEN + 1];
+
+           const char *path = NULL;
+           if (!issetugid()) {
+               path = getenv("CFFIXED_USER_HOME");
+           }
+           if (!path) {
+               path = passwdp->pw_dir;
+           }
+
+            strlcpy(filename, path, sizeof(filename));
+            strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
+
+           int no_hang_fd = __CFProphylacticAutofsAccess ? open("/dev/autofs_nowait", 0) : -1;
+            int fd = open(filename, O_RDONLY, 0);
+            if (fd == -1) {
+                // Cannot open the file. Let's fallback to smRoman/verUS
+                snprintf(filename, sizeof(filename), "0x%X:0:0", uid);
+                setenv(__kCFUserEncodingEnvVariableName, filename, 1);
+            } else {
+                int readSize;
+                readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
+                buffer[(readSize < 0 ? 0 : readSize)] = '\0';
+                close(fd);
+                stringValue = buffer;
+
+                // Well, we already have a buffer, let's reuse it
+                snprintf(filename, sizeof(filename), "0x%X:%s", uid, buffer);
+                setenv(__kCFUserEncodingEnvVariableName, filename, 1);
+            }
+           if (-1 != no_hang_fd) close(no_hang_fd);
+        }
+    }
+
+    if (stringValue) {
+        *oScriptValue = strtol_l(stringValue, &stringValue, 0, NULL);
+        if (*stringValue == ':') {
+            if (oRegionValue) *oRegionValue = strtol_l(++stringValue, NULL, 0, NULL);
+            return;
+        }
+    }
+
+    // Falling back
+    *oScriptValue = 0; // smRoman
+    if (oRegionValue) *oRegionValue = 0; // verUS
+}
+
+void _CFStringGetInstallationEncodingAndRegion(uint32_t *encoding, uint32_t *region) {
+    char buffer[__kCFMaxDefaultEncodingFileLength];
+    char *stringValue = NULL;
+
+    *encoding = 0;
+    *region = 0;
+
+    struct passwd *passwdp = getpwuid((uid_t)0);
+    if (passwdp) {
+       const char *path = passwdp->pw_dir;
+
+        char filename[MAXPATHLEN + 1];
+        strlcpy(filename, path, sizeof(filename));
+        strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
+        
+       int no_hang_fd = __CFProphylacticAutofsAccess ? open("/dev/autofs_nowait", 0) : -1;
+       int fd = open(filename, O_RDONLY, 0);
+       if (0 <= fd) {
+            size_t size = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
+            buffer[(size < 0 ? 0 : size)] = '\0';
+            close(fd);
+            stringValue = buffer;
+        }
+       if (-1 != no_hang_fd) close(no_hang_fd);
+    }
+    
+    if (stringValue) {
+        *encoding = strtol_l(stringValue, &stringValue, 0, NULL);
+        if (*stringValue == ':') *region = strtol_l(++stringValue, NULL, 0, NULL);
+    }
+}
+
+Boolean _CFStringSaveUserDefaultEncoding(UInt32 iScriptValue, UInt32 iRegionValue) {
+    Boolean success = false;
+    struct passwd *passwdp = getpwuid(getuid());
+    if (passwdp) {
+       const char *path = passwdp->pw_dir;
+       if (!issetugid()) {
+           char *value = getenv("CFFIXED_USER_HOME");
+           if (value) path = value; // override
+       }
+
+        char filename[MAXPATHLEN + 1];
+        strlcpy(filename, path, sizeof(filename));
+        strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
+
+       int no_hang_fd = __CFProphylacticAutofsAccess ? open("/dev/autofs_nowait", 0) : -1;
+        (void)unlink(filename);
+       int fd = open(filename, O_WRONLY|O_CREAT, 0400);
+       if (0 <= fd) {
+            char buffer[__kCFMaxDefaultEncodingFileLength];
+            size_t size = snprintf(buffer, __kCFMaxDefaultEncodingFileLength, "0x%X:0x%X", (unsigned int)iScriptValue, (unsigned int)iRegionValue);
+           if (size <= __kCFMaxDefaultEncodingFileLength) {
+                int ret = write(fd, buffer, size);
+               if (size <= ret) success = true;
+           }
+           int save_err = errno;
+            close(fd);
+           errno = save_err;
+        }
+       int save_err = errno;
+       if (-1 != no_hang_fd) close(no_hang_fd);
+       errno = save_err;
+    }
+    return success;
+}
+
+#endif
+
index 4ae14613698cda38fe32c96d4f267e5decf43a49..e90a55dc5a13c34601bf5d35fd611ee12644efe5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringScanner.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Ali Ozer
 */
 
@@ -161,7 +161,7 @@ static const unsigned char __CFNumberSet[16] = {
     0X00, // 0, 0, 0, 0, 0, 0, 0, 0, //  dle dc1 dc2 dc3 dc4 nak syn etb
     0X00, // 0, 0, 0, 0, 0, 0, 0, 0, //  can em  sub esc fs  gs  rs  us
     0X00, // 0, 0, 0, 0, 0, 0, 0, 0, //  sp   !   "   #   $   %   &   '
-    0X28, // 0, 0, 0, 1, 0, 1, 0, 0, //  (   )   *   +   ,   -   .   /
+    0X68, // 0, 0, 0, 1, 0, 1, 1, 0, //  (   )   *   +   ,   -   .   /
     0xFF, // 1, 1, 1, 1, 1, 1, 1, 1, //  0   1   2   3   4   5   6   7
     0X03, // 1, 1, 0, 0, 0, 0, 0, 0, //  8   9   :   ;   <   =   >   ?
     0X20, // 0, 0, 0, 0, 0, 1, 0, 0, //  @   A   B   C   D   E   F   G
@@ -180,19 +180,12 @@ __private_extern__ Boolean __CFStringScanDouble(CFStringInlineBuffer *buf, CFTyp
     char localCharBuffer[STACK_BUFFER_SIZE];
     char *charPtr = localCharBuffer;
     char *endCharPtr;
-    UniChar decimalChar = '.';
     SInt32 numChars = 0;
     SInt32 capacity = STACK_BUFFER_SIZE;       // in chars
     double result;
     UniChar ch;
     CFAllocatorRef tmpAlloc = NULL;
 
-#if 0
-    if (locale != NULL) {
-        CFStringRef decimalSeparator = [locale objectForKey: @"NSDecimalSeparator"];
-        if (decimalSeparator != nil) decimalChar = [decimalSeparator characterAtIndex:0];
-    }
-#endif
     ch = __CFStringGetFirstNonSpaceCharacterFromInlineBuffer(buf, indexPtr);
     // At this point indexPtr points at the first non-space char
 #if 0
@@ -234,12 +227,8 @@ __private_extern__ Boolean __CFStringScanDouble(CFStringInlineBuffer *buf, CFTyp
         }
     }
 #endif 0
-    do {
-       if (ch >= 128 || (__CFNumberSet[ch >> 3] & (1 << (ch & 7))) == 0) {
-            // Not in __CFNumberSet
-           if (ch != decimalChar) break;
-            ch = '.';  // Replace the decimal character with something strtod will understand
-        }
+    // Get characters until one not in __CFNumberSet[] is encountered
+    while ((ch < 128) && (__CFNumberSet[ch >> 3] & (1 << (ch & 7)))) {
         if (numChars >= capacity - 1) {
            capacity += ALLOC_CHUNK_SIZE;
            if (tmpAlloc == NULL) tmpAlloc = __CFGetDefaultAllocator();
@@ -252,7 +241,7 @@ __private_extern__ Boolean __CFStringScanDouble(CFStringInlineBuffer *buf, CFTyp
         }
        charPtr[numChars++] = (char)ch;
        ch = __CFStringGetCharacterFromInlineBufferAux(buf, *indexPtr + numChars);
-    } while (true);
+    };
     charPtr[numChars] = 0;     // Null byte for strtod
 
     result = strtod_l(charPtr, &endCharPtr, NULL);
index 015a244bc1ab7dd26d69381f86ca0c497dbde0a6..f13146dea291022bc7c4a92e022cb833666230ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFStringUtilities.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Aki Inoue
 */
 
 #include "CFInternal.h"
-#include "CFStringEncodingConverterExt.h"
-#include "CFUniChar.h"
+#include <CoreFoundation/CFStringEncodingConverterExt.h>
+#include <CoreFoundation/CFUniChar.h>
 #include <CoreFoundation/CFStringEncodingExt.h>
+#include "CFStringEncodingDatabase.h"
+#include "CFICUConverters.h"
 #include <CoreFoundation/CFPreferences.h>
 #include <limits.h>
-#if (DEPLOYMENT_TARGET_MACOSX) || DEPLOYMENT_TARGET_LINUX
-#include <stdlib.h>
-#elif  defined(__WIN32__)
 #include <stdlib.h>
+#include <unicode/ucol.h>
+#include <unicode/ucoleitr.h>
+#include <string.h>
+
+#if  DEPLOYMENT_TARGET_WINDOWS
 #include <tchar.h>
 #endif
 
@@ -69,26 +73,12 @@ CFStringRef CFStringGetNameOfEncoding(CFStringEncoding theEncoding) {
     CFStringRef theName = mappingTable ? (CFStringRef)CFDictionaryGetValue(mappingTable, (const void*)(uintptr_t)theEncoding) : NULL;
 
     if (!theName) {
-        switch (theEncoding) {
-            case kCFStringEncodingUTF8: theName = CFSTR("Unicode (UTF-8)"); break;
-            case kCFStringEncodingUTF16: theName = CFSTR("Unicode (UTF-16)"); break;
-            case kCFStringEncodingUTF16BE: theName = CFSTR("Unicode (UTF-16BE)"); break;
-            case kCFStringEncodingUTF16LE: theName = CFSTR("Unicode (UTF-16LE)"); break;
-            case kCFStringEncodingUTF32: theName = CFSTR("Unicode (UTF-32)"); break;
-            case kCFStringEncodingUTF32BE: theName = CFSTR("Unicode (UTF-32BE)"); break;
-            case kCFStringEncodingUTF32LE: theName = CFSTR("Unicode (UTF-32LE)"); break;
-            case kCFStringEncodingNonLossyASCII: theName = CFSTR("Non-lossy ASCII"); break;
-    
-            default: {
-                const char *encodingName = CFStringEncodingName(theEncoding);
-    
-                if (encodingName) {
-                    theName = CFStringCreateWithCString(kCFAllocatorSystemDefault, encodingName, kCFStringEncodingASCII);
-                }
-            }
-            break;
+        const char *encodingName = __CFStringEncodingGetName(theEncoding);
+        
+        if (encodingName) {
+            theName = CFStringCreateWithCString(kCFAllocatorSystemDefault, encodingName, kCFStringEncodingASCII);
         }
-
+        
         if (theName) {
             if (!mappingTable) mappingTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, (const CFDictionaryKeyCallBacks *)NULL, &kCFTypeDictionaryValueCallBacks);
 
@@ -100,104 +90,54 @@ CFStringRef CFStringGetNameOfEncoding(CFStringEncoding theEncoding) {
     return theName;
 }
 
-CFStringEncoding CFStringConvertIANACharSetNameToEncoding(CFStringRef  charsetName) {
-    static CFMutableDictionaryRef mappingTable = NULL;
-    CFStringEncoding result = kCFStringEncodingInvalidId;
-    CFMutableStringRef lowerCharsetName;
-
-    /* Check for common encodings first */
-    if (CFStringCompare(charsetName, CFSTR("utf-8"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
-        return kCFStringEncodingUTF8;
-    } else if (CFStringCompare(charsetName, CFSTR("iso-8859-1"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
-        return kCFStringEncodingISOLatin1;
-    }
-
-    /* Create lowercase copy */
-    lowerCharsetName = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, charsetName);
-    CFStringLowercase(lowerCharsetName, NULL);
+CFStringEncoding CFStringConvertIANACharSetNameToEncoding(CFStringRef charsetName) {
+    CFStringEncoding encoding = kCFStringEncodingInvalidId;
+#define BUFFER_SIZE (100)
+    char buffer[BUFFER_SIZE];
+    const char *name = CFStringGetCStringPtr(charsetName, __CFStringGetEightBitStringEncoding());
 
-    if (mappingTable == NULL) {
-        CFMutableDictionaryRef table = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, (const CFDictionaryValueCallBacks *)NULL);
-        const CFStringEncoding *encodings = CFStringGetListOfAvailableEncodings();
+    if (NULL == name) {
+        if (false == CFStringGetCString(charsetName, buffer, BUFFER_SIZE, __CFStringGetEightBitStringEncoding())) return kCFStringEncodingInvalidId;
 
-        while (*encodings != kCFStringEncodingInvalidId) {
-            const char **nameList = CFStringEncodingCanonicalCharsetNames(*encodings);
+        name = buffer;
+    }
 
-            if (nameList) {
-                while (*nameList) {
-                    CFStringRef name = CFStringCreateWithCString(kCFAllocatorSystemDefault, *nameList++, kCFStringEncodingASCII);
+    encoding = __CFStringEncodingGetFromCanonicalName(name);
 
-                    if (name) {
-                        CFDictionaryAddValue(table, (const void*)name, (const void*)(uintptr_t)*encodings);
-                        CFRelease(name);
-                    }
-                }
-            }
-            encodings++;
-        }
-        // Adding Unicode names
-        CFDictionaryAddValue(table, (const void*)CFSTR("unicode-1-1"), (const void*)kCFStringEncodingUTF16);
-        CFDictionaryAddValue(table, (const void*)CFSTR("iso-10646-ucs-2"), (const void*)kCFStringEncodingUTF16);
-        CFDictionaryAddValue(table, (const void*)CFSTR("utf-16"), (const void*)kCFStringEncodingUTF16);
-        CFDictionaryAddValue(table, (const void*)CFSTR("utf-16be"), (const void*)kCFStringEncodingUTF16BE);
-        CFDictionaryAddValue(table, (const void*)CFSTR("utf-16le"), (const void*)kCFStringEncodingUTF16LE);
-        CFDictionaryAddValue(table, (const void*)CFSTR("utf-32"), (const void*)kCFStringEncodingUTF32);
-        CFDictionaryAddValue(table, (const void*)CFSTR("utf-32be"), (const void*)kCFStringEncodingUTF32BE);
-        CFDictionaryAddValue(table, (const void*)CFSTR("utf-32le"), (const void*)kCFStringEncodingUTF32LE);
-
-        mappingTable = table;
-    }
+    if (kCFStringEncodingInvalidId == encoding) encoding = __CFStringEncodingGetFromICUName(name);
 
-    if (CFDictionaryContainsKey(mappingTable, (const void*)lowerCharsetName)) {
-        result = (CFStringEncoding)(uintptr_t)CFDictionaryGetValue(mappingTable, (const void*)lowerCharsetName);
-    }
-    
-    CFRelease(lowerCharsetName);
 
-    return result;
+    return encoding;
 }
 
 CFStringRef CFStringConvertEncodingToIANACharSetName(CFStringEncoding encoding) {
+    CFStringRef name = NULL;
+    CFIndex value = encoding;
     static CFMutableDictionaryRef mappingTable = NULL;
-    CFStringRef theName = mappingTable ? (CFStringRef)CFDictionaryGetValue(mappingTable, (const void*)(uintptr_t)encoding) : NULL;
+    static CFSpinLock_t lock = CFSpinLockInit;
 
-    if (!theName) {
-        switch (encoding) {
-            case kCFStringEncodingUTF16: theName = CFSTR("UTF-16"); break;
-            case kCFStringEncodingUTF16BE: theName = CFSTR("UTF-16BE"); break;
-            case kCFStringEncodingUTF16LE: theName = CFSTR("UTF-16LE"); break;
-            case kCFStringEncodingUTF32: theName = CFSTR("UTF-32"); break;
-            case kCFStringEncodingUTF32BE: theName = CFSTR("UTF-32BE"); break;
-            case kCFStringEncodingUTF32LE: theName = CFSTR("UTF-32LE"); break;
-    
-    
-            default: {
-                const char **nameList = CFStringEncodingCanonicalCharsetNames(encoding);
-    
-                if (nameList && *nameList) {
-                    CFMutableStringRef upperCaseName;
-    
-                    theName = CFStringCreateWithCString(kCFAllocatorSystemDefault, *nameList, kCFStringEncodingASCII);
-                    if (theName) {
-                        upperCaseName = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, 0, theName);
-                        CFStringUppercase(upperCaseName, 0);
-                        CFRelease(theName);
-                        theName = upperCaseName;
-                    }
-                }
-            }
-            break;
-        }
+    __CFSpinLock(&lock);
+    name = ((NULL == mappingTable) ? NULL : (CFStringRef)CFDictionaryGetValue(mappingTable, (const void*)value));
 
-        if (theName) {
-            if (!mappingTable) mappingTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, (const CFDictionaryKeyCallBacks *)NULL, &kCFTypeDictionaryValueCallBacks);
+    if (NULL == name) {
+#define STACK_BUFFER_SIZE (100)
+        char buffer[STACK_BUFFER_SIZE];
 
-            CFDictionaryAddValue(mappingTable, (const void*)(uintptr_t)encoding, (const void*)theName);
-            CFRelease(theName);
+        if (__CFStringEncodingGetCanonicalName(encoding, buffer, STACK_BUFFER_SIZE)) name = CFStringCreateWithCString(NULL, buffer, kCFStringEncodingASCII);
+
+
+        if (NULL != name) {
+            CFIndex value = encoding;
+
+            if (NULL == mappingTable) mappingTable = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks);
+
+            CFDictionaryAddValue(mappingTable, (const void*)value, (const void*)name);
+            CFRelease(name);
         }
     }
+    __CFSpinUnlock(&lock);
 
-    return theName;
+    return name;
 }
 
 enum {
@@ -226,262 +166,563 @@ enum {
 
 unsigned long CFStringConvertEncodingToNSStringEncoding(CFStringEncoding theEncoding) {
     switch (theEncoding & 0xFFF) {
-        case kCFStringEncodingASCII: return NSASCIIStringEncoding;
-        case kCFStringEncodingNextStepLatin: return NSNEXTSTEPStringEncoding;
-        case kCFStringEncodingISOLatin1: return NSISOLatin1StringEncoding;
-        case kCFStringEncodingNonLossyASCII: return NSNonLossyASCIIStringEncoding;
+        case kCFStringEncodingUnicode:
+            if (theEncoding == kCFStringEncodingUTF16) return NSUnicodeStringEncoding;
+            else if (theEncoding == kCFStringEncodingUTF8) return NSUTF8StringEncoding;
+            break;
+
         case kCFStringEncodingWindowsLatin1: return NSWindowsCP1252StringEncoding;
         case kCFStringEncodingMacRoman: return NSMacOSRomanStringEncoding;
-#if DEPLOYMENT_TARGET_MACOSX
-        case kCFStringEncodingEUC_JP: return NSJapaneseEUCStringEncoding;
-        case kCFStringEncodingMacSymbol: return NSSymbolStringEncoding;
+
+        case kCFStringEncodingASCII: return NSASCIIStringEncoding;
+
         case kCFStringEncodingDOSJapanese: return NSShiftJISStringEncoding;
-        case kCFStringEncodingISOLatin2: return NSISOLatin2StringEncoding;
         case kCFStringEncodingWindowsCyrillic: return NSWindowsCP1251StringEncoding;
         case kCFStringEncodingWindowsGreek: return NSWindowsCP1253StringEncoding;
         case kCFStringEncodingWindowsLatin5: return NSWindowsCP1254StringEncoding;
         case kCFStringEncodingWindowsLatin2: return NSWindowsCP1250StringEncoding;
-        case kCFStringEncodingISO_2022_JP: return NSISO2022JPStringEncoding;
-#endif
-#if DEPLOYMENT_TARGET_MACOSX
-        case kCFStringEncodingUnicode:
-            if (theEncoding == kCFStringEncodingUTF16) return NSUnicodeStringEncoding;
-            else if (theEncoding == kCFStringEncodingUTF8) return NSUTF8StringEncoding;
-#endif
-            /* fall-through for other encoding schemes */
+        case kCFStringEncodingISOLatin1: return NSISOLatin1StringEncoding;
 
-        default:
-            return NSENCODING_MASK | theEncoding;
+        case kCFStringEncodingNonLossyASCII: return NSNonLossyASCIIStringEncoding;
+        case kCFStringEncodingEUC_JP: return NSJapaneseEUCStringEncoding;
+        case kCFStringEncodingMacSymbol: return NSSymbolStringEncoding;
+        case kCFStringEncodingISOLatin2: return NSISOLatin2StringEncoding;
+        case kCFStringEncodingISO_2022_JP: return NSISO2022JPStringEncoding;
+        case kCFStringEncodingNextStepLatin: return NSNEXTSTEPStringEncoding;
     }
+
+    return NSENCODING_MASK | theEncoding;
 }
 
 CFStringEncoding CFStringConvertNSStringEncodingToEncoding(unsigned long theEncoding) {
+    const uint16_t encodings[] = {
+        kCFStringEncodingASCII,
+        kCFStringEncodingNextStepLatin,
+        kCFStringEncodingEUC_JP,
+        0,
+        kCFStringEncodingISOLatin1,
+        kCFStringEncodingMacSymbol,
+        kCFStringEncodingNonLossyASCII,
+        kCFStringEncodingDOSJapanese,
+        kCFStringEncodingISOLatin2,
+        kCFStringEncodingUTF16,
+        kCFStringEncodingWindowsCyrillic,
+        kCFStringEncodingWindowsLatin1,
+        kCFStringEncodingWindowsGreek,
+        kCFStringEncodingWindowsLatin5,
+        kCFStringEncodingWindowsLatin2
+    };
+
+    if (NSUTF8StringEncoding == theEncoding) return kCFStringEncodingUTF8;
+
+    if ((theEncoding > 0) && (theEncoding <= NSWindowsCP1250StringEncoding)) return encodings[theEncoding - 1];
+
     switch (theEncoding) {
-        case NSASCIIStringEncoding: return kCFStringEncodingASCII;
-        case NSNEXTSTEPStringEncoding: return kCFStringEncodingNextStepLatin;
-        case NSUTF8StringEncoding: return kCFStringEncodingUTF8;
-        case NSISOLatin1StringEncoding: return kCFStringEncodingISOLatin1;
-        case NSNonLossyASCIIStringEncoding: return kCFStringEncodingNonLossyASCII;
-        case NSUnicodeStringEncoding: return kCFStringEncodingUTF16;
-        case NSWindowsCP1252StringEncoding: return kCFStringEncodingWindowsLatin1;
         case NSMacOSRomanStringEncoding: return kCFStringEncodingMacRoman;
-#if DEPLOYMENT_TARGET_MACOSX
-        case NSSymbolStringEncoding: return kCFStringEncodingMacSymbol;
-        case NSJapaneseEUCStringEncoding: return kCFStringEncodingEUC_JP;
-        case NSShiftJISStringEncoding: return kCFStringEncodingDOSJapanese;
         case NSISO2022JPStringEncoding: return kCFStringEncodingISO_2022_JP;
-        case NSISOLatin2StringEncoding: return kCFStringEncodingISOLatin2;
-        case NSWindowsCP1251StringEncoding: return kCFStringEncodingWindowsCyrillic;
-        case NSWindowsCP1253StringEncoding: return kCFStringEncodingWindowsGreek;
-        case NSWindowsCP1254StringEncoding: return kCFStringEncodingWindowsLatin5;
-        case NSWindowsCP1250StringEncoding: return kCFStringEncodingWindowsLatin2;
-#endif
+
         default:
             return ((theEncoding & NSENCODING_MASK) ? theEncoding & ~NSENCODING_MASK : kCFStringEncodingInvalidId);
     }
 }
 
-#define MACCODEPAGE_BASE (10000)
-#define ISO8859CODEPAGE_BASE (28590)
+UInt32 CFStringConvertEncodingToWindowsCodepage(CFStringEncoding theEncoding) {
+    uint16_t codepage = __CFStringEncodingGetWindowsCodePage(theEncoding);
 
-static const uint16_t _CFToDOSCodePageList[] = {
-    437, -1, -1, -1, -1, 737, 775, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x400
-    850, 851, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 874, -1, 01, // 0x410
-    932, 936, 949 , 950, // 0x420
-};
+    return ((0 == codepage) ? kCFStringEncodingInvalidId : codepage);
+}
 
-static const uint16_t _CFToWindowsCodePageList[] = {
-    1252, 1250, 1251, 1253, 1254, 1255, 1256, 1257, 1258,
-};
+CFStringEncoding CFStringConvertWindowsCodepageToEncoding(UInt32 theEncoding) {
+    return __CFStringEncodingGetFromWindowsCodePage(theEncoding);
+}
+
+CFStringEncoding CFStringGetMostCompatibleMacStringEncoding(CFStringEncoding encoding) {
+    CFStringEncoding macEncoding = __CFStringEncodingGetMostCompatibleMacScript(encoding);
 
-static const uint16_t _CFEUCToCodePage[] = { // 0x900
-    51932, 51936, 51950, 51949,
+
+    return macEncoding;
+}
+
+#define kCFStringCompareAllocationIncrement (128)
+
+
+// -------------------------------------------------------------------------------------------------
+//     CompareSpecials - ignore case & diacritic differences
+//
+//     Decomposed have 2nd-4th chars of type Mn or Mc, or in range 1160-11FF (jamo)
+//     Fullwidth & halfwidth are in range FF00-FFEF
+//     Parenthesized & circled are in range 3200-32FF
+// -------------------------------------------------------------------------------------------------
+
+enum {
+       kUpperCaseWeightMin     = 0x80 | 0x0F,
+       kUpperCaseWeightMax     = 0x80 | 0x17,
+       kUpperToLowerDelta      = 0x80 | 0x0A,  // 0x0A = 0x0F - 0x05
+       kMaskPrimarySecondary   = 0xFFFFFF00,
+       kMaskPrimaryOnly        = 0xFFFF0000,
+       kMaskSecondaryOnly      = 0x0000FF00,
+       kMaskCaseTertiary       = 0x000000FF    // 2 hi bits case, 6 lo bits tertiary
 };
 
-UInt32 CFStringConvertEncodingToWindowsCodepage(CFStringEncoding theEncoding) {
-#if DEPLOYMENT_TARGET_MACOSX
-    CFStringEncoding encodingBase = theEncoding & 0x0FFF;
-#endif
+static SInt32 __CompareSpecials(const UCollator *collator, CFOptionFlags options, const UniChar *text1Ptr, UniCharCount text1Length, const UniChar *text2Ptr, UniCharCount text2Length) {
+       UErrorCode icuStatus = U_ZERO_ERROR;
+       SInt32  orderWidth = 0;
+       SInt32  orderCompos = 0;
+
+       UCollationElements * collElems1 = ucol_openElements(collator, (const UChar *)text1Ptr, text1Length, &icuStatus);
+       UCollationElements * collElems2 = ucol_openElements(collator, (const UChar *)text2Ptr, text2Length, &icuStatus);
+       if (U_SUCCESS(icuStatus)) {
+               int32_t startOffset1 = 0;
+               int32_t startOffset2 = 0;
+               
+               while (true) {
+                       int32_t elemOrder1, elemOrder2;
+                       int32_t offset1, offset2;
+                       
+                       elemOrder1 = ucol_next(collElems1, &icuStatus);
+                       elemOrder2 = ucol_next(collElems2, &icuStatus);
+                       if ( U_FAILURE(icuStatus) || elemOrder1 == (int32_t)UCOL_NULLORDER || elemOrder2 == (int32_t)UCOL_NULLORDER ) {
+                               break;
+                       }
+
+                       offset1 = ucol_getOffset(collElems1);
+                       offset2 = ucol_getOffset(collElems2);
+                       if ( (elemOrder1 & kMaskPrimarySecondary) == (elemOrder2 & kMaskPrimarySecondary) ) {
+                               if ( (elemOrder1 & kMaskPrimaryOnly) != 0 ) {
+                                       // keys may differ in case, width, circling, etc.
+
+                                       int32_t tertiary1 = (elemOrder1 & kMaskCaseTertiary);
+                                       int32_t tertiary2 = (elemOrder2 & kMaskCaseTertiary);
+                                       // fold upper to lower case
+                                       if (tertiary1 >= kUpperCaseWeightMin && tertiary1 <= kUpperCaseWeightMax) {
+                                               tertiary1 -= kUpperToLowerDelta;
+                                       }
+                                       if (tertiary2 >= kUpperCaseWeightMin && tertiary2 <= kUpperCaseWeightMax) {
+                                               tertiary2 -= kUpperToLowerDelta;
+                                       }
+                                       // now compare
+                                       if (tertiary1 != tertiary2) {
+                                               orderWidth = (tertiary1 < tertiary2)? -1: 1;
+                                               break;
+                                       }
+
+                               } else if ( (elemOrder1 & kMaskSecondaryOnly) != 0 ) {
+                                       // primary weights are both zero, but secondaries are not.
+                                       if ( orderCompos == 0 && (options & kCFCompareNonliteral) == 0 ) {
+                                               // We have a code element which is a diacritic.
+                                               // It may have come from a composed char or a combining char.
+                                               // If it came from a combining char (longer element length) it sorts first.
+                                               // This is only an approximation to what the Mac OS 9 code did, but this is an
+                                               // unusual case anyway.
+                                               int32_t elem1Length = offset1 - startOffset1;
+                                               int32_t elem2Length = offset2 - startOffset2;
+                                               if (elem1Length != elem2Length) {
+                                                       orderCompos = (elem1Length > elem2Length)? -1: 1;
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       startOffset1 = offset1;
+                       startOffset2 = offset2;
+               }
+               ucol_closeElements(collElems1);
+               ucol_closeElements(collElems2);
+       }
+       
+       return (orderWidth != 0)? orderWidth: orderCompos;
+}
 
-    switch (theEncoding & 0x0F00) {
-#if DEPLOYMENT_TARGET_MACOSX
-    case 0: // Mac OS script
-        if (encodingBase <= kCFStringEncodingMacCentralEurRoman) {
-            return MACCODEPAGE_BASE + encodingBase;
-        } else if (encodingBase == kCFStringEncodingMacTurkish) {
-            return 10081;
-        } else if (encodingBase == kCFStringEncodingMacCroatian) {
-            return 10082;
-        } else if (encodingBase == kCFStringEncodingMacIcelandic) {
-            return 10079;
-        }
-        break;
-#endif
+static SInt32 __CompareCodePoints(const UniChar *text1Ptr, UniCharCount text1Length, const UniChar *text2Ptr, UniCharCount text2Length ) {
+       const UniChar * text1P = text1Ptr;
+       const UniChar * text2P = text2Ptr;
+       UInt32          textLimit = (text1Length <= text2Length)? text1Length: text2Length;
+       UInt32          textCounter;
+       SInt32          orderResult = 0;
+
+       // Loop through either string...the first difference differentiates this.
+       for (textCounter = 0; textCounter < textLimit && *text1P == *text2P; textCounter++) {
+               text1P++;
+               text2P++;
+       }
+       if (textCounter < textLimit) {
+               // code point difference
+               orderResult = (*text1P < *text2P) ? -1 : 1;
+       } else if (text1Length != text2Length) {
+               // one string has extra stuff at end
+               orderResult = (text1Length < text2Length) ? -1 : 1;
+       }
+       return orderResult;
+}
 
-    case 0x100: // Unicode
-        switch (theEncoding) {
-        case kCFStringEncodingUTF8: return 65001;
-        case kCFStringEncodingUTF16: return 1200;
-        case kCFStringEncodingUTF16BE: return 1201;
-        case kCFStringEncodingUTF32: return 65005;
-        case kCFStringEncodingUTF32BE: return 65006;
-        }
-        break;
-
-#if (DEPLOYMENT_TARGET_MACOSX) 
-    case 0x0200: // ISO 8859 series
-        if (encodingBase <= kCFStringEncodingISOLatin10) return ISO8859CODEPAGE_BASE + (encodingBase - 0x200);
-        break;
-
-    case 0x0400: // DOS codepage
-        if (encodingBase <= kCFStringEncodingDOSChineseTrad) return _CFToDOSCodePageList[encodingBase - 0x400]; 
-        break;
-
-    case 0x0500: // ANSI (Windows) codepage
-        if (encodingBase <= kCFStringEncodingWindowsVietnamese) return _CFToWindowsCodePageList[theEncoding - 0x500];
-        else if (encodingBase == kCFStringEncodingWindowsKoreanJohab) return 1361;
-        break;
-
-    case 0x600: // National standards
-        if (encodingBase == kCFStringEncodingASCII) return 20127;
-        else if (encodingBase == kCFStringEncodingGB_18030_2000) return 54936;
-        break;
-
-    case 0x0800: // ISO 2022 series
-        switch (encodingBase) {
-        case kCFStringEncodingISO_2022_JP: return 50220;
-        case kCFStringEncodingISO_2022_CN: return 50227;
-        case kCFStringEncodingISO_2022_KR: return 50225;
-        }
-        break;
 
-    case 0x0900: // EUC series
-        if (encodingBase <= kCFStringEncodingEUC_KR) return _CFEUCToCodePage[encodingBase - 0x0900];
-        break;
+extern const CFStringRef __kCFLocaleCollatorID;
+
+static UCollator *__CFStringCreateCollator(CFLocaleRef compareLocale) {
+    CFStringRef canonLocaleCFStr = (CFStringRef)CFLocaleGetValue(compareLocale, __kCFLocaleCollatorID);
+    char icuLocaleStr[128] = {0};
+    CFStringGetCString(canonLocaleCFStr, icuLocaleStr, sizeof(icuLocaleStr), kCFStringEncodingASCII);
+    UErrorCode icuStatus = U_ZERO_ERROR;
+    UCollator * collator = ucol_open(icuLocaleStr, &icuStatus);
+    ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &icuStatus);
+    ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING, UCOL_NON_IGNORABLE, &icuStatus);
+    ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &icuStatus);
+    ucol_setAttribute(collator, UCOL_CASE_LEVEL, UCOL_OFF, &icuStatus);
+    ucol_setAttribute(collator, UCOL_NUMERIC_COLLATION, UCOL_OFF, &icuStatus);
+    return collator;
+}
 
+#define kCFMaxCachedDefaultCollators (8)
+static UCollator *__CFDefaultCollators[kCFMaxCachedDefaultCollators];
+static CFIndex __CFDefaultCollatorsCount = 0;
+static const void *__CFDefaultCollatorLocale = NULL;
+static CFSpinLock_t __CFDefaultCollatorLock = CFSpinLockInit;
 
-    case 0x0A00: // Misc encodings
-        switch (encodingBase) {
-        case kCFStringEncodingKOI8_R: return 20866;
-        case kCFStringEncodingHZ_GB_2312: return 52936;
-        case kCFStringEncodingKOI8_U: return 21866;
-        }
-        break;
+static UCollator *__CFStringCopyDefaultCollator(CFLocaleRef compareLocale) {
+    CFLocaleRef currentLocale = NULL;
+    UCollator * collator = NULL;
 
-    case 0x0C00: // IBM EBCDIC encodings
-        if (encodingBase == kCFStringEncodingEBCDIC_CP037) return 37;
-        break;
-#endif
+    if (compareLocale != __CFDefaultCollatorLocale) {
+        currentLocale = CFLocaleCopyCurrent();
+        CFRelease(currentLocale);
+        if (compareLocale != currentLocale) return NULL;
     }
 
-    return kCFStringEncodingInvalidId;
-}
+    __CFSpinLock(&__CFDefaultCollatorLock);
+    if ((NULL != currentLocale) && (__CFDefaultCollatorLocale != currentLocale)) {
+        while (__CFDefaultCollatorsCount > 0) ucol_close(__CFDefaultCollators[--__CFDefaultCollatorsCount]);
+        __CFDefaultCollatorLocale = currentLocale;
+    }
 
-#if DEPLOYMENT_TARGET_MACOSX
-static const struct {
-    uint16_t acp;
-    uint16_t encoding;
-} _CFACPToCFTable[] = {
-    {37, kCFStringEncodingEBCDIC_CP037},
-    {437, kCFStringEncodingDOSLatinUS},
-    {737, kCFStringEncodingDOSGreek},
-    {775, kCFStringEncodingDOSBalticRim},
-    {850, kCFStringEncodingDOSLatin1},
-    {851, kCFStringEncodingDOSGreek1},
-    {852, kCFStringEncodingDOSLatin2},
-    {855, kCFStringEncodingDOSCyrillic},
-    {857, kCFStringEncodingDOSTurkish},
-    {860, kCFStringEncodingDOSPortuguese},
-    {861, kCFStringEncodingDOSIcelandic},
-    {862, kCFStringEncodingDOSHebrew},
-    {863, kCFStringEncodingDOSCanadianFrench},
-    {864, kCFStringEncodingDOSArabic},
-    {865, kCFStringEncodingDOSNordic},
-    {866, kCFStringEncodingDOSRussian},
-    {869, kCFStringEncodingDOSGreek2},
-    {874, kCFStringEncodingDOSThai},
-    {932, kCFStringEncodingDOSJapanese},
-    {936, kCFStringEncodingDOSChineseSimplif},
-    {949, kCFStringEncodingDOSKorean},
-    {950, kCFStringEncodingDOSChineseTrad},
-    {1250, kCFStringEncodingWindowsLatin2},
-    {1251, kCFStringEncodingWindowsCyrillic},
-    {1252, kCFStringEncodingWindowsLatin1},
-    {1253, kCFStringEncodingWindowsGreek},
-    {1254, kCFStringEncodingWindowsLatin5},
-    {1255, kCFStringEncodingWindowsHebrew},
-    {1256, kCFStringEncodingWindowsArabic},
-    {1257, kCFStringEncodingWindowsBalticRim},
-    {1258, kCFStringEncodingWindowsVietnamese},
-    {1361, kCFStringEncodingWindowsKoreanJohab},
-    {20127, kCFStringEncodingASCII},
-    {20866, kCFStringEncodingKOI8_R},
-    {21866, kCFStringEncodingKOI8_U},
-    {50220, kCFStringEncodingISO_2022_JP},
-    {50225, kCFStringEncodingISO_2022_KR},
-    {50227, kCFStringEncodingISO_2022_CN},
-    {51932, kCFStringEncodingEUC_JP},
-    {51936, kCFStringEncodingEUC_CN},
-    {51949, kCFStringEncodingEUC_KR},
-    {51950, kCFStringEncodingEUC_TW},
-    {52936, kCFStringEncodingHZ_GB_2312},
-    {54936, kCFStringEncodingGB_18030_2000},
-};
+    if (__CFDefaultCollatorsCount > 0) collator = __CFDefaultCollators[--__CFDefaultCollatorsCount];
+    __CFSpinUnlock(&__CFDefaultCollatorLock);
 
-static SInt32 bsearchEncoding(uint16_t target) {
-    const unsigned int *start, *end, *divider;
-    unsigned int size = sizeof(_CFACPToCFTable) / sizeof(UInt32);
+    if (NULL == collator) {
+       collator = __CFStringCreateCollator(compareLocale);
+    }
 
-    start = (const unsigned int*)_CFACPToCFTable; end = (const unsigned int*)_CFACPToCFTable + (size - 1);
-    while (start <= end) {
-        divider = start + ((end - start) / 2);
+    return collator;
+}
 
-        if (*(const uint16_t*)divider == target) return *((const uint16_t*)divider + 1);
-        else if (*(const uint16_t*)divider > target) end = divider - 1;
-        else if (*(const uint16_t*)(divider + 1) > target) return *((const uint16_t*)divider + 1);
-        else start = divider + 1;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+static void __collatorFinalize(UCollator *collator) {
+    CFLocaleRef locale = pthread_getspecific(__CFTSDKeyCollatorLocale);
+    pthread_setspecific(__CFTSDKeyCollatorUCollator, NULL);
+    pthread_setspecific(__CFTSDKeyCollatorLocale, NULL);
+    __CFSpinLock(&__CFDefaultCollatorLock);
+    if ((__CFDefaultCollatorLocale == locale) && (__CFDefaultCollatorsCount < kCFMaxCachedDefaultCollators)) {
+        __CFDefaultCollators[__CFDefaultCollatorsCount++] = collator;
+        collator = NULL;
     }
-    return (kCFStringEncodingInvalidId);
+    __CFSpinUnlock(&__CFDefaultCollatorLock);
+    if (NULL != collator) ucol_close(collator);
+    if (locale) CFRelease(locale);
 }
 #endif
 
-CFStringEncoding CFStringConvertWindowsCodepageToEncoding(UInt32 theEncoding) {
-    if (theEncoding == 0 || theEncoding == 1) { // ID for default (system) codepage
-        return CFStringGetSystemEncoding();
-    } else if ((theEncoding >= MACCODEPAGE_BASE) && (theEncoding < 20000)) { // Mac script
-        if (theEncoding <= 10029) return theEncoding - MACCODEPAGE_BASE; // up to Mac Central European
-#if (DEPLOYMENT_TARGET_MACOSX) 
-        else if (theEncoding == 10079) return kCFStringEncodingMacIcelandic;
-        else if (theEncoding == 10081) return kCFStringEncodingMacTurkish;
-        else if (theEncoding == 10082) return kCFStringEncodingMacCroatian;
-#endif
-    } else if ((theEncoding >= ISO8859CODEPAGE_BASE) && (theEncoding <= 28605)) { // ISO 8859
-        return (theEncoding - ISO8859CODEPAGE_BASE) + 0x200;
-    } else if (theEncoding == 65001) { // UTF-8
-        return kCFStringEncodingUTF8;
-    } else if (theEncoding == 12000) { // UTF-16
-        return kCFStringEncodingUTF16;
-    } else if (theEncoding == 12001) { // UTF-16BE
-        return kCFStringEncodingUTF16BE;
-    } else if (theEncoding == 65005) { // UTF-32
-        return kCFStringEncodingUTF32;
-    } else if (theEncoding == 65006) { // UTF-32BE
-        return kCFStringEncodingUTF32BE;
+// -------------------------------------------------------------------------------------------------
+// __CompareTextDefault
+// 
+// A primary difference is denoted by values 2/-2 in orderP. Other differences are indicated with a -1/1.
+// A negative value indicates that text1 sorts before text2.
+// -------------------------------------------------------------------------------------------------
+static OSStatus __CompareTextDefault(UCollator *collator, CFOptionFlags options, const UniChar *text1Ptr, UniCharCount text1Length, const UniChar *text2Ptr, UniCharCount text2Length, Boolean *equivalentP, SInt32 *orderP) {
+
+       // collator must have default settings restored on exit from this function
+
+       *equivalentP = true;
+       *orderP = 0;    
+
+       if (options & kCFCompareNumerically) {
+           UErrorCode icuStatus = U_ZERO_ERROR;        
+           ucol_setAttribute(collator, UCOL_NUMERIC_COLLATION, UCOL_ON, &icuStatus);
+       }
+
+       // Most string differences are Primary. Do a primary check first, then if there
+       // are no differences do a comparison with the options in the collator.
+       UCollationResult icuResult = ucol_strcoll(collator, (const UChar *)text1Ptr, text1Length, (const UChar *)text2Ptr, text2Length);
+       if (icuResult != UCOL_EQUAL) {
+               *orderP = (icuResult == UCOL_LESS) ? -2 : 2;
+       }
+       if (*orderP == 0) {
+               UErrorCode icuStatus = U_ZERO_ERROR;    
+                ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &icuStatus);
+                ucol_setAttribute(collator, UCOL_STRENGTH, (options & kCFCompareDiacriticInsensitive) ? UCOL_PRIMARY : UCOL_SECONDARY, &icuStatus);
+                ucol_setAttribute(collator, UCOL_CASE_LEVEL, (options & kCFCompareCaseInsensitive) ? UCOL_OFF : UCOL_ON, &icuStatus);
+               if (!U_SUCCESS(icuStatus)) {
+                   icuStatus = U_ZERO_ERROR;
+                   ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &icuStatus);
+                   ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &icuStatus);
+                   ucol_setAttribute(collator, UCOL_CASE_LEVEL, UCOL_OFF, &icuStatus);
+                   ucol_setAttribute(collator, UCOL_NUMERIC_COLLATION, UCOL_OFF, &icuStatus);
+                   return 666;
+               }
+
+               // We don't have a primary difference. Recompare with standard collator.
+               icuResult = ucol_strcoll(collator, (const UChar *)text1Ptr, text1Length, (const UChar *)text2Ptr, text2Length);
+               if (icuResult != UCOL_EQUAL) {
+                       *orderP = (icuResult == UCOL_LESS) ? -1 : 1;
+               }
+               icuStatus = U_ZERO_ERROR;
+                ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &icuStatus);
+               ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &icuStatus);
+               ucol_setAttribute(collator, UCOL_CASE_LEVEL, UCOL_OFF, &icuStatus);
+       }
+       if (*orderP == 0 && (options & kCFCompareNonliteral) == 0) {
+               *orderP = __CompareSpecials(collator, options, text1Ptr, text1Length, text2Ptr, text2Length);
+       }
+
+       *equivalentP = (*orderP == 0);
+
+       // If strings are equivalent but we care about order and have not yet checked
+       // to the level of code point order, then do some more checks for order
+       if (*orderP == 0) {
+               UErrorCode icuStatus = U_ZERO_ERROR;    
+               // First try to see if ICU can find any differences above code point level
+                ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_ON, &icuStatus);
+               ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_TERTIARY, &icuStatus);
+               ucol_setAttribute(collator, UCOL_CASE_LEVEL, UCOL_ON, &icuStatus);
+               if (!U_SUCCESS(icuStatus)) {
+                   icuStatus = U_ZERO_ERROR;
+                   ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &icuStatus);
+                   ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &icuStatus);
+                   ucol_setAttribute(collator, UCOL_CASE_LEVEL, UCOL_OFF, &icuStatus);
+                   ucol_setAttribute(collator, UCOL_NUMERIC_COLLATION, UCOL_OFF, &icuStatus);
+                   return 666;
+               }
+               icuResult = ucol_strcoll(collator, (const UChar *)text1Ptr, text1Length, (const UChar *)text2Ptr, text2Length);
+               if (icuResult != UCOL_EQUAL) {
+                       *orderP = (icuResult == UCOL_LESS) ? -1 : 1;
+               } else {
+                       // no ICU differences above code point level, compare code points
+                       *orderP = __CompareCodePoints( text1Ptr, text1Length, text2Ptr, text2Length );
+               }
+               icuStatus = U_ZERO_ERROR;
+                ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UCOL_OFF, &icuStatus);
+               ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &icuStatus);
+               ucol_setAttribute(collator, UCOL_CASE_LEVEL, UCOL_OFF, &icuStatus);
+       }
+
+       if (options & kCFCompareNumerically) {
+           UErrorCode icuStatus = U_ZERO_ERROR;        
+           ucol_setAttribute(collator, UCOL_NUMERIC_COLLATION, UCOL_OFF, &icuStatus);
+       }
+       return 0; // noErr
+}
+
+static inline CFIndex __extendLocationBackward(CFIndex location, CFStringInlineBuffer *str, const uint8_t *nonBaseBMP, const uint8_t *punctBMP) {
+    while (location > 0) {
+        UTF32Char ch = CFStringGetCharacterFromInlineBuffer(str, location);
+        UTF32Char otherChar;
+        if (CFUniCharIsSurrogateLowCharacter(ch) && CFUniCharIsSurrogateHighCharacter((otherChar = CFStringGetCharacterFromInlineBuffer(str, location - 1)))) {
+            ch = CFUniCharGetLongCharacterForSurrogatePair(ch, otherChar);
+            uint8_t planeNo = (ch >> 16);
+            if ((planeNo > 1) || (!CFUniCharIsMemberOfBitmap(ch, CFUniCharGetBitmapPtrForPlane(kCFUniCharNonBaseCharacterSet, planeNo)) && !CFUniCharIsMemberOfBitmap(ch, CFUniCharGetBitmapPtrForPlane(kCFUniCharPunctuationCharacterSet, planeNo)))) break;
+            location -= 2;
+        } else {
+            if ((!CFUniCharIsMemberOfBitmap(ch, nonBaseBMP) && !CFUniCharIsMemberOfBitmap(ch, punctBMP)) || ((ch >= 0x2E80) && (ch < 0xAC00))) break;
+            --location;
+        }
+    }
+
+    return location;
+}
+
+static inline CFIndex __extendLocationForward(CFIndex location, CFStringInlineBuffer *str, const uint8_t *alnumBMP, const uint8_t *punctBMP, const uint8_t *controlBMP, CFIndex strMax) {
+    do {
+        UTF32Char ch = CFStringGetCharacterFromInlineBuffer(str, location);
+        UTF32Char otherChar;
+        if (CFUniCharIsSurrogateHighCharacter(ch) && CFUniCharIsSurrogateLowCharacter((otherChar = CFStringGetCharacterFromInlineBuffer(str, location + 1)))) {
+            ch = CFUniCharGetLongCharacterForSurrogatePair(ch, otherChar);
+            location += 2;
+            uint8_t planeNo = (ch >> 16);
+            if (!CFUniCharIsMemberOfBitmap(ch, CFUniCharGetBitmapPtrForPlane(kCFUniCharAlphaNumericCharacterSet, planeNo)) && !CFUniCharIsMemberOfBitmap(ch, CFUniCharGetBitmapPtrForPlane(kCFUniCharPunctuationCharacterSet, planeNo)) && !CFUniCharIsMemberOfBitmap(ch, CFUniCharGetBitmapPtrForPlane(kCFUniCharControlAndFormatterCharacterSet, planeNo))) break;
+        } else {
+            ++location;
+            if ((!CFUniCharIsMemberOfBitmap(ch, alnumBMP) && !CFUniCharIsMemberOfBitmap(ch, punctBMP) && !CFUniCharIsMemberOfBitmap(ch, controlBMP)) || ((ch >= 0x2E80) && (ch < 0xAC00))) break;
+        }
+    } while (location < strMax);
+    return location;
+}
+
+__private_extern__ CFComparisonResult _CFCompareStringsWithLocale(CFStringInlineBuffer *str1, CFRange str1Range, CFStringInlineBuffer *str2, CFRange str2Range, CFOptionFlags options, const void *compareLocale) {
+    const UniChar *characters1;
+    const UniChar *characters2;
+    CFComparisonResult compResult = kCFCompareEqualTo;
+    CFRange range1 = str1Range;
+    CFRange range2 = str2Range;
+    SInt32 order;
+    Boolean isEqual;
+    bool forcedOrdering = ((options & kCFCompareForcedOrdering) ? true : false);
+
+    UCollator *collator = NULL;
+    bool defaultCollator = true;
+    static const uint8_t *alnumBMP = NULL;
+    static const uint8_t *nonBaseBMP = NULL;
+    static const uint8_t *punctBMP = NULL;
+    static const uint8_t *controlBMP = NULL;
+    
+    if (NULL == alnumBMP) {
+       alnumBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharAlphaNumericCharacterSet, 0);
+       nonBaseBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharNonBaseCharacterSet, 0);
+       punctBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharPunctuationCharacterSet, 0);
+       controlBMP = CFUniCharGetBitmapPtrForPlane(kCFUniCharControlAndFormatterCharacterSet, 0);
+    }
+    
+    // Determine the range of characters surrodiing the current index significant for localized comparison. The range is extended backward and forward as long as they are contextual. Contextual characters include all letters and punctuations. Since most control/format characters are ignorable in localized comparison, we also include them extending forward.
+    
+    range1.location = str1Range.location;
+    range2.location = str2Range.location;
+    
+    // go backward
+    // The characters upto the current index are already determined to be equal by the CFString's standard character folding algorithm. Extend as long as truly contextual (all letters and punctuations).
+    if (range1.location > 0) {
+       range1.location = __extendLocationBackward(range1.location - 1, str1, nonBaseBMP, punctBMP);
+    }
+    
+    if (range2.location > 0) {
+       range2.location = __extendLocationBackward(range2.location - 1, str2, nonBaseBMP, punctBMP);
+    }
+    
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    // First we try to use the last one used on this thread, if the locale is the same,
+    // otherwise we try to check out a default one, or then we create one.
+    UCollator *threadCollator = pthread_getspecific(__CFTSDKeyCollatorUCollator);
+    CFLocaleRef threadLocale = pthread_getspecific(__CFTSDKeyCollatorLocale);
+    if (compareLocale == threadLocale) {
+       collator = threadCollator;
     } else {
-#if DEPLOYMENT_TARGET_MACOSX
-        return bsearchEncoding(theEncoding);
 #endif
+       collator = __CFStringCopyDefaultCollator((CFLocaleRef)compareLocale);
+       defaultCollator = true;
+       if (NULL == collator) {
+           collator = __CFStringCreateCollator((CFLocaleRef)compareLocale);
+           defaultCollator = false;
+       }
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     }
+#endif
 
-    return kCFStringEncodingInvalidId;
-}
+    characters1 = CFStringGetCharactersPtrFromInlineBuffer(str1, range1);
+    characters2 = CFStringGetCharactersPtrFromInlineBuffer(str2, range2);
 
-CFStringEncoding CFStringGetMostCompatibleMacStringEncoding(CFStringEncoding encoding) {
-    CFStringEncoding macEncoding;
+    if ((NULL != characters1) && (NULL != characters2)) { // do fast
+       range1.length = (str1Range.location + str1Range.length) - range1.location;
+       range2.length = (str2Range.location + str2Range.length) - range2.location;
 
-    macEncoding = CFStringEncodingGetScriptCodeForEncoding(encoding);
+        if ((NULL != collator) && (__CompareTextDefault(collator, options, characters1, range1.length, characters2, range2.length, &isEqual, &order) == 0 /* noErr */)) {
+            compResult = ((isEqual && !forcedOrdering) ? kCFCompareEqualTo : ((order < 0) ? kCFCompareLessThan : kCFCompareGreaterThan));
+        } else {
+            compResult = ((memcmp(characters1, characters2, sizeof(UniChar) * range1.length) < 0) ? kCFCompareLessThan : kCFCompareGreaterThan);
+        }
+    } else {
+        UniChar *buffer1 = NULL;
+        UniChar *buffer2 = NULL;
+        UTF16Char sBuffer1[kCFStringCompareAllocationIncrement];
+        UTF16Char sBuffer2[kCFStringCompareAllocationIncrement];
+        CFIndex buffer1Len = 0, buffer2Len = 0;
+        CFIndex str1Max = str1Range.location + str1Range.length;
+        CFIndex str2Max = str2Range.location + str2Range.length;
+        CFIndex bufferSize;
+
+        // Extend forward and compare until the result is deterministic. The result is indeterministic if the differences are weak and can be resolved by character folding. For example, comparision between "abc" and "ABC" is considered to be indeterministic.
+        do {
+            if (str1Range.location < str1Max) {
+               str1Range.location = __extendLocationForward(str1Range.location, str1, alnumBMP, punctBMP, controlBMP, str1Max);
+                range1.length = (str1Range.location - range1.location);
+                characters1 = CFStringGetCharactersPtrFromInlineBuffer(str1, range1);
+
+                if (NULL == characters1) {
+                    if ((0 > buffer1Len) || (range1.length > kCFStringCompareAllocationIncrement)) {
+                        if (buffer1Len < range1.length) {
+                            bufferSize = range1.length + (kCFStringCompareAllocationIncrement - (range1.length % kCFStringCompareAllocationIncrement));
+                            if (0 == buffer1Len) {
+                                buffer1 = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UTF16Char) * bufferSize, 0);
+                            } else if (buffer1Len < range1.length) {
+                                buffer1 = (UniChar *)CFAllocatorReallocate(kCFAllocatorSystemDefault, buffer1, sizeof(UTF16Char) * bufferSize, 0);
+                            }
+                            buffer1Len = bufferSize;
+                        }
+                    } else {
+                        buffer1 = sBuffer1;
+                    }
 
-    return macEncoding;
-}
+                    CFStringGetCharactersFromInlineBuffer(str1, range1, buffer1);
+                    characters1 = buffer1;
+                }
+            }
+
+            if (str2Range.location < str2Max) {
+               str2Range.location = __extendLocationForward(str2Range.location, str2, alnumBMP, punctBMP, controlBMP, str2Max);                
+                range2.length = (str2Range.location - range2.location);
+                characters2 = CFStringGetCharactersPtrFromInlineBuffer(str2, range2);
+                
+                if (NULL == characters2) {
+                    if ((0 > buffer2Len) || (range2.length > kCFStringCompareAllocationIncrement)) {
+                        if (buffer2Len < range2.length) {
+                            bufferSize = range2.length + (kCFStringCompareAllocationIncrement - (range2.length % kCFStringCompareAllocationIncrement));
+                            if (0 == buffer2Len) {
+                                buffer2 = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(UTF16Char) * bufferSize, 0);
+                            } else if (buffer2Len < range2.length) {
+                                buffer2 = (UniChar *)CFAllocatorReallocate(kCFAllocatorSystemDefault, buffer2, sizeof(UTF16Char) * bufferSize, 0);
+                            }
+                            buffer2Len = bufferSize;
+                        }
+                    } else {
+                        buffer2 = sBuffer2;
+                    }
+
+                    CFStringGetCharactersFromInlineBuffer(str2, range2, buffer2);
+                    characters2 = buffer2;
+                }
+            }
+
+            if ((NULL != collator) && (__CompareTextDefault(collator, options, characters1, range1.length, characters2, range2.length, &isEqual, &order) ==  0 /* noErr */)) {
+                if (isEqual) {
+                    if (forcedOrdering && (kCFCompareEqualTo == compResult) && (0 != order)) compResult = ((order < 0) ? kCFCompareLessThan : kCFCompareGreaterThan);
+                    order = 0;
+                }
+            } else {
+                order = memcmp(characters1, characters2, sizeof(UTF16Char) * ((range1.length < range2.length) ? range1.length : range2.length));
+                if (0 == order) {
+                    if (range1.length < range2.length) {
+                        order = -2;
+                    } else if (range2.length < range1.length) {
+                        order = 2;
+                    }
+                } else if (order < 0) {
+                    --order;
+                } else if (order > 0) {
+                    ++order;
+                }
+            }
+
+            if ((order < -1) || (order > 1)) break; // the result is deterministic
+
+            if (0 == order) {
+                range1.location = str1Range.location;
+                range2.location = str2Range.location;
+            }
+        } while ((str1Range.location < str1Max) || (str2Range.location < str2Max));
 
+        if (0 != order) compResult = ((order < 0) ? kCFCompareLessThan : kCFCompareGreaterThan);
+
+        if (buffer1Len > 0) CFAllocatorDeallocate(kCFAllocatorSystemDefault, buffer1);
+        if (buffer2Len > 0) CFAllocatorDeallocate(kCFAllocatorSystemDefault, buffer2);
+    }
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    if (collator == threadCollator) {
+       // do nothing, already cached
+    } else {
+       if (threadLocale) __collatorFinalize((UCollator *)pthread_getspecific(__CFTSDKeyCollatorUCollator)); // need to dealloc collators
+
+        pthread_key_init_np(__CFTSDKeyCollatorUCollator, (void *)__collatorFinalize);
+       pthread_setspecific(__CFTSDKeyCollatorUCollator, collator);
+       pthread_setspecific(__CFTSDKeyCollatorLocale, CFRetain(compareLocale));
+    }
+#endif
+
+    return compResult;
+}
 
index 7104c2d27cf08da7601cd42b0e1efeb1ff8e9c52..9801c8bf93d97422a5c3524933425e50b4092ce4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFSystemDirectories.c
-       Copyright 1997-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1997-2009, Apple Inc. All rights reserved.
        Responsibility: Ali Ozer
 */
 
@@ -35,7 +35,7 @@
 #include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 
 /* We use the System framework implementation on Mach.
 */
@@ -64,7 +64,7 @@ CFSearchPathEnumerationState __CFGetNextSearchPathEnumeration(CFSearchPathEnumer
 #endif
 
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
 
 CFArrayRef CFCopySearchPathForDirectoriesInDomains(CFSearchPathDirectory directory, CFSearchPathDomainMask domainMask, Boolean expandTilde) {
     CFMutableArrayRef array;
index a93584b30f53020cdd54715c1deaebb258c087a5..3af1cc9dcb8764f1012a1aec6261c30964c92b5d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
        Responsibility: Christopher Kane
 */
 
+
+
 #include <CoreFoundation/CFTimeZone.h>
 #include <CoreFoundation/CFPropertyList.h>
-#include "CFPriv.h"
+#include <CoreFoundation/CFDateFormatter.h>
+#include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
 #include <math.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unicode/ucal.h>
-#if DEPLOYMENT_TARGET_MACOSX
+#include <CoreFoundation/CFDateFormatter.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
 #include <dirent.h>
 #include <unistd.h>
 #include <sys/fcntl.h>
 #include <tzfile.h>
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
-#if DEPLOYMENT_TARGET_MACOSX
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define TZZONELINK     TZDEFAULT
 #define TZZONEINFO     TZDIR "/"
+#elif DEPLOYMENT_TARGET_WINDOWS
+static CFStringRef __tzZoneInfo = NULL;
+static char *__tzDir = NULL;
+static void __InitTZStrings(void);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 CONST_STRING_DECL(kCFTimeZoneSystemTimeZoneDidChangeNotification, "kCFTimeZoneSystemTimeZoneDidChangeNotification")
@@ -60,6 +73,11 @@ static CFArrayRef __CFKnownTimeZoneList = NULL;
 static CFMutableDictionaryRef __CFTimeZoneCache = NULL;
 static CFSpinLock_t __CFTimeZoneGlobalLock = CFSpinLockInit;
 
+#if DEPLOYMENT_TARGET_WINDOWS
+static CFDictionaryRef __CFTimeZoneWinToOlsonDict = NULL;
+static CFSpinLock_t __CFTimeZoneWinToOlsonLock = CFSpinLockInit;
+#endif
+
 CF_INLINE void __CFTimeZoneLockGlobal(void) {
     __CFSpinLock(&__CFTimeZoneGlobalLock);
 }
@@ -84,10 +102,53 @@ CF_INLINE void __CFTimeZoneUnlockCompatibilityMapping(void) {
     __CFSpinUnlock(&__CFTimeZoneCompatibilityMappingLock);
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+/* This function should be used for WIN32 instead of
+ * __CFCopyRecursiveDirectoryList function.
+ * It takes TimeZone names from the registry
+ * (Aleksey Dukhnyakov)
+ */
+static CFMutableArrayRef __CFCopyWindowsTimeZoneList() {
+    CFMutableArrayRef result = NULL;
+    HKEY hkResult;
+    TCHAR lpName[MAX_PATH+1];
+    DWORD dwIndex, retCode;
+
+    if (RegOpenKey(HKEY_LOCAL_MACHINE,_T(TZZONEINFO),&hkResult) !=
+        ERROR_SUCCESS )
+        return NULL;
+
+    result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+    for (dwIndex=0; (retCode = RegEnumKey(hkResult,dwIndex,lpName,MAX_PATH)) != ERROR_NO_MORE_ITEMS ; dwIndex++) {
+        if (retCode != ERROR_SUCCESS) {
+            RegCloseKey(hkResult);
+            CFRelease(result);
+            return NULL;
+        } else {
+#if defined(UNICODE)
+           CFStringRef string = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (const UInt8 *)lpName, (_tcslen(lpName) * sizeof(UniChar)), kCFStringEncodingUnicode, false);
+#else
+           CFStringRef string = CFStringCreateWithBytes(kCFAllocatorSystemDefault, lpName, _tcslen(lpName), CFStringGetSystemEncoding(), false);
+#endif
+           CFArrayAppendValue(result, string);
+           CFRelease(string);
+        }
+    }
+
+    RegCloseKey(hkResult);
+    return result;
+}
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED  || DEPLOYMENT_TARGET_WINDOWS
 static CFMutableArrayRef __CFCopyRecursiveDirectoryList() {
     CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+#if DEPLOYMENT_TARGET_WINDOWS
+    if (!__tzDir) __InitTZStrings();
+    if (!__tzDir) return result;
+    int fd = open(__tzDir, O_RDONLY);
+#else
     int fd = open(TZDIR "/zone.tab", O_RDONLY);
+#endif
+
     for (; 0 <= fd;) {
         uint8_t buffer[4096];
         ssize_t len = read(fd, buffer, sizeof(buffer));
@@ -201,7 +262,7 @@ static CFComparisonResult __CFCompareTZPeriods(const void *val1, const void *val
 
 static CFIndex __CFBSearchTZPeriods(CFTimeZoneRef tz, CFAbsoluteTime at) {
     CFTZPeriod elem;
-    __CFTZPeriodInit(&elem, (int32_t)floor(at), NULL, 0, false);
+    __CFTZPeriodInit(&elem, (int32_t)floor(at + 1.0), NULL, 0, false);
     CFIndex idx = CFBSearch(&elem, sizeof(CFTZPeriod), tz->_periods, tz->_periodCnt, __CFCompareTZPeriods, NULL);
     if (tz->_periodCnt <= idx) {
        idx = tz->_periodCnt;
@@ -228,7 +289,7 @@ CF_INLINE void __CFEntzcode(int32_t value, unsigned char *bufp) {
     bufp[3] = (value >> 0) & 0xff;
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
 static Boolean __CFParseTimeZoneData(CFAllocatorRef allocator, CFDataRef data, CFTZPeriod **tzpp, CFIndex *cntp) {
     int32_t len, timecnt, typecnt, charcnt, idx, cnt;
     const uint8_t *p, *timep, *typep, *ttisp, *charp;
@@ -345,7 +406,7 @@ static Boolean __CFParseTimeZoneData(CFAllocatorRef allocator, CFDataRef data, C
     }
     return result;
 }
-#elif 0 || 0
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
 static Boolean __CFParseTimeZoneData(CFAllocatorRef allocator, CFDataRef data, CFTZPeriod **tzpp, CFIndex *cntp) {
 /* We use Win32 function to find TimeZone
  * (Aleksey Dukhnyakov)
@@ -419,23 +480,281 @@ CFTypeID CFTimeZoneGetTypeID(void) {
 }
 
 
-#if DEPLOYMENT_TARGET_MACOSX
-static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
-    CFTimeZoneRef result = NULL;
+#if DEPLOYMENT_TARGET_WINDOWS_SYNC
+static const char *__CFTimeZoneWinToOlsonDefaults =
+/* Mappings to time zones in Windows Registry are best-guess */
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+" <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">"
+" <plist version=\"1.0\">"
+" <dict>"
+"    <key>Afghanistan</key>                 <string>Asia/Kabul</string>"
+"    <key>Afghanistan Standard Time</key>   <string>Asia/Kabul</string>"
+"    <key>Alaskan</key>                     <string>America/Anchorage</string>"
+"    <key>Alaskan Standard Time</key>       <string>America/Anchorage</string>"
+"    <key>Arab</key>                        <string>Asia/Riyadh</string>"
+"    <key>Arab Standard Time</key>          <string>Asia/Riyadh</string>"
+"    <key>Arabian</key>                     <string>Asia/Muscat</string>"
+"    <key>Arabian Standard Time</key>       <string>Asia/Muscat</string>"
+"    <key>Arabic Standard Time</key>        <string>Asia/Baghdad</string>"
+"    <key>Atlantic</key>                    <string>America/Halifax</string>"
+"    <key>Atlantic Standard Time</key>      <string>America/Halifax</string>"
+"    <key>AUS Central</key>                 <string>Australia/Darwin</string>"
+"    <key>AUS Central Standard Time</key>      <string>Australia/Darwin</string>"
+"    <key>AUS Eastern</key>                 <string>Australia/Sydney</string>"
+"    <key>AUS Eastern Standard Time</key>      <string>Australia/Sydney</string>"
+"    <key>Azerbaijan Standard Time</key>       <string>Asia/Baku</string>"
+"    <key>Azores</key>                      <string>Atlantic/Azores</string>"
+"    <key>Azores Standard Time</key>        <string>Atlantic/Azores</string>"
+"    <key>Bangkok</key>                     <string>Asia/Bangkok</string>"
+"    <key>Bangkok Standard Time</key>       <string>Asia/Bangkok</string>"
+"    <key>Beijing</key>                     <string>Asia/Shanghai</string>"
+"    <key>Canada Central</key>              <string>America/Regina</string>"
+"    <key>Canada Central Standard Time</key> <string>America/Regina</string>"
+"    <key>Cape Verde Standard Time</key>    <string>Atlantic/Cape_Verde</string>"
+"    <key>Caucasus</key>                    <string>Asia/Yerevan</string>"
+"    <key>Caucasus Standard Time</key>      <string>Asia/Yerevan</string>"
+"    <key>Cen. Australia</key>              <string>Australia/Adelaide</string>"
+"    <key>Cen. Australia Standard Time</key> <string>Australia/Adelaide</string>"
+"    <key>Central</key>                     <string>America/Chicago</string>"
+"    <key>Central America Standard Time</key> <string>America/Regina</string>"
+"    <key>Central Asia</key>                <string>Asia/Dhaka</string>"
+"    <key>Central Asia Standard Time</key>     <string>Asia/Dhaka</string>"
+"    <key>Central Brazilian Standard Time</key>        <string>America/Manaus</string>"
+"    <key>Central Europe</key>              <string>Europe/Prague</string>"
+"    <key>Central Europe Standard Time</key> <string>Europe/Prague</string>"
+"    <key>Central European</key>            <string>Europe/Belgrade</string>"
+"    <key>Central European Standard Time</key> <string>Europe/Belgrade</string>"
+"    <key>Central Pacific</key>             <string>Pacific/Guadalcanal</string>"
+"    <key>Central Pacific Standard Time</key>  <string>Pacific/Guadalcanal</string>"
+"    <key>Central Standard Time</key>       <string>America/Chicago</string>"
+"    <key>Central Standard Time (Mexico)</key> <string>America/Mexico_City</string>"
+"    <key>China</key>                       <string>Asia/Shanghai</string>"
+"    <key>China Standard Time</key>         <string>Asia/Shanghai</string>"
+"    <key>Dateline</key>                    <string>GMT-1200</string>"
+"    <key>Dateline Standard Time</key>      <string>GMT-1200</string>"
+"    <key>E. Africa</key>                   <string>Africa/Nairobi</string>"
+"    <key>E. Africa Standard Time</key>     <string>Africa/Nairobi</string>"
+"    <key>E. Australia</key>                <string>Australia/Brisbane</string>"
+"    <key>E. Australia Standard Time</key>     <string>Australia/Brisbane</string>"
+"    <key>E. Europe</key>                   <string>Europe/Minsk</string>"
+"    <key>E. Europe Standard Time</key>     <string>Europe/Minsk</string>"
+"    <key>E. South America</key>            <string>America/Sao_Paulo</string>"
+"    <key>E. South America Standard Time</key> <string>America/Sao_Paulo</string>"
+"    <key>Eastern</key>                     <string>America/New_York</string>"
+"    <key>Eastern Standard Time</key>       <string>America/New_York</string>"
+"    <key>Egypt</key>       <string>Africa/Cairo</string>"
+"    <key>Egypt Standard Time</key> <string>Africa/Cairo</string>"
+"    <key>Ekaterinburg</key>                <string>Asia/Yekaterinburg</string>"
+"    <key>Ekaterinburg Standard Time</key>     <string>Asia/Yekaterinburg</string>"
+"    <key>Fiji</key>   <string>Pacific/Fiji</string>"
+"    <key>Fiji Standard Time</key>     <string>Pacific/Fiji</string>"
+"    <key>FLE</key>    <string>Europe/Helsinki</string>"
+"    <key>FLE Standard Time</key>      <string>Europe/Helsinki</string>"
+"    <key>Georgian Standard Time</key> <string>Asia/Tbilisi</string>"
+"    <key>GFT</key>    <string>Europe/Athens</string>"
+"    <key>GFT Standard Time</key>      <string>Europe/Athens</string>"
+"    <key>GMT</key>    <string>Europe/London</string>"
+"    <key>GMT Standard Time</key>      <string>Europe/London</string>"
+"    <key>Greenland Standard Time</key>        <string>America/Godthab</string>"
+"    <key>Greenwich</key>      <string>GMT</string>"
+"    <key>Greenwich Standard Time</key>        <string>GMT</string>"
+"    <key>GTB</key>    <string>Europe/Athens</string>"
+"    <key>GTB Standard Time</key>      <string>Europe/Athens</string>"
+"    <key>Hawaiian</key>       <string>Pacific/Honolulu</string>"
+"    <key>Hawaiian Standard Time</key> <string>Pacific/Honolulu</string>"
+"    <key>India</key>  <string>Asia/Calcutta</string>"
+"    <key>India Standard Time</key>    <string>Asia/Calcutta</string>"
+"    <key>Iran</key>   <string>Asia/Tehran</string>"
+"    <key>Iran Standard Time</key>     <string>Asia/Tehran</string>"
+"    <key>Israel</key> <string>Asia/Jerusalem</string>"
+"    <key>Israel Standard Time</key>   <string>Asia/Jerusalem</string>"
+"    <key>Jordan Standard Time</key>   <string>Asia/Amman</string>"
+"    <key>Korea</key>  <string>Asia/Seoul</string>"
+"    <key>Korea Standard Time</key>    <string>Asia/Seoul</string>"
+"    <key>Mexico</key> <string>America/Mexico_City</string>"
+"    <key>Mexico Standard Time</key>   <string>America/Mexico_City</string>"
+"    <key>Mexico Standard Time 2</key> <string>America/Chihuahua</string>"
+"    <key>Mid-Atlantic</key>   <string>Atlantic/South_Georgia</string>"
+"    <key>Mid-Atlantic Standard Time</key>     <string>Atlantic/South_Georgia</string>"
+"    <key>Middle East Standard Time</key>      <string>Asia/Beirut</string>"
+"    <key>Mountain</key>       <string>America/Denver</string>"
+"    <key>Mountain Standard Time</key> <string>America/Denver</string>"
+"    <key>Mountain Standard Time (Mexico)</key>        <string>America/Chihuahua</string>"
+"    <key>Myanmar Standard Time</key>  <string>Asia/Rangoon</string>"
+"    <key>N. Central Asia Standard Time</key>   <string>Asia/Novosibirsk</string>"
+"    <key>Namibia Standard Time</key>   <string>Africa/Windhoek</string>"
+"    <key>Nepal Standard Time</key>    <string>Asia/Katmandu</string>"
+"    <key>New Zealand</key>    <string>Pacific/Auckland</string>"
+"    <key>New Zealand Standard Time</key>      <string>Pacific/Auckland</string>"
+"    <key>Newfoundland</key>   <string>America/St_Johns</string>"
+"    <key>Newfoundland Standard Time</key>     <string>America/St_Johns</string>"
+"    <key>North Asia East Standard Time</key>  <string>Asia/Ulaanbaatar</string>"
+"    <key>North Asia Standard Time</key>       <string>Asia/Krasnoyarsk</string>"
+"    <key>Pacific</key>        <string>America/Los_Angeles</string>"
+"    <key>Pacific SA</key>     <string>America/Santiago</string>"
+"    <key>Pacific SA Standard Time</key>       <string>America/Santiago</string>"
+"    <key>Pacific Standard Time</key>  <string>America/Los_Angeles</string>"
+"    <key>Pacific Standard Time (Mexico)</key> <string>America/Tijuana</string>"
+"    <key>Prague Bratislava</key>      <string>Europe/Prague</string>"
+"    <key>Romance</key>        <string>Europe/Paris</string>"
+"    <key>Romance Standard Time</key>  <string>Europe/Paris</string>"
+"    <key>Russian</key>        <string>Europe/Moscow</string>"
+"    <key>Russian Standard Time</key>  <string>Europe/Moscow</string>"
+"    <key>SA Eastern</key>     <string>America/Buenos_Aires</string>"
+"    <key>SA Eastern Standard Time</key>       <string>America/Buenos_Aires</string>"
+"    <key>SA Pacific</key>     <string>America/Bogota</string>"
+"    <key>SA Pacific Standard Time</key>       <string>America/Bogota</string>"
+"    <key>SA Western</key>     <string>America/Caracas</string>"
+"    <key>SA Western Standard Time</key>       <string>America/Caracas</string>"
+"    <key>Samoa</key>  <string>Pacific/Apia</string>"
+"    <key>Samoa Standard Time</key>    <string>Pacific/Apia</string>"
+"    <key>Saudi Arabia</key>   <string>Asia/Riyadh</string>"
+"    <key>Saudi Arabia Standard Time</key>     <string>Asia/Riyadh</string>"
+"    <key>SE Asia Standard Time</key>  <string>Asia/Bangkok</string>"
+"    <key>Singapore</key>      <string>Asia/Singapore</string>"
+"    <key>Singapore Standard Time</key>        <string>Asia/Singapore</string>"
+"    <key>South Africa</key>   <string>Africa/Harare</string>"
+"    <key>South Africa Standard Time</key>     <string>Africa/Harare</string>"
+"    <key>Sri Lanka</key>      <string>Asia/Colombo</string>"
+"    <key>Sri Lanka Standard Time</key>        <string>Asia/Colombo</string>"
+"    <key>Sydney Standard Time</key>   <string>Australia/Sydney</string>"
+"    <key>Taipei</key> <string>Asia/Taipei</string>"
+"    <key>Taipei Standard Time</key>   <string>Asia/Taipei</string>"
+"    <key>Tasmania</key>       <string>Australia/Hobart</string>"
+"    <key>Tasmania Standard Time</key> <string>Australia/Hobart</string>"
+"    <key>Tasmania Standard Time</key> <string>Australia/Hobart</string>"
+"    <key>Tokyo</key>  <string>Asia/Tokyo</string>"
+"    <key>Tokyo Standard Time</key>    <string>Asia/Tokyo</string>"
+"    <key>Tonga Standard Time</key>    <string>Pacific/Tongatapu</string>"
+"    <key>US Eastern</key>     <string>America/Indianapolis</string>"
+"    <key>US Eastern Standard Time</key>       <string>America/Indianapolis</string>"
+"    <key>US Mountain</key>    <string>America/Phoenix</string>"
+"    <key>US Mountain Standard Time</key>      <string>America/Phoenix</string>"
+"    <key>Vladivostok</key>    <string>Asia/Vladivostok</string>"
+"    <key>Vladivostok Standard Time</key>      <string>Asia/Vladivostok</string>"
+"    <key>W. Australia</key>   <string>Australia/Perth</string>"
+"    <key>W. Australia Standard Time</key>     <string>Australia/Perth</string>"
+"    <key>W. Central Africa Standard Time</key>        <string>Africa/Luanda</string>"
+"    <key>W. Europe</key>      <string>Europe/Berlin</string>"
+"    <key>W. Europe Standard Time</key>        <string>Europe/Berlin</string>"
+"    <key>Warsaw</key> <string>Europe/Warsaw</string>"
+"    <key>West Asia</key>      <string>Asia/Karachi</string>"
+"    <key>West Asia Standard Time</key>        <string>Asia/Karachi</string>"
+"    <key>West Pacific</key>   <string>Pacific/Guam</string>"
+"    <key>West Pacific Standard Time</key>     <string>Pacific/Guam</string>"
+"    <key>Western Brazilian Standard Time</key>        <string>America/Rio_Branco</string>"
+"    <key>Yakutsk</key>        <string>Asia/Yakutsk</string>"
+" </dict>"
+" </plist>";
 
+CF_INLINE void __CFTimeZoneLockWinToOlson(void) {
+    __CFSpinLock(&__CFTimeZoneWinToOlsonLock);
+}
+
+CF_INLINE void __CFTimeZoneUnlockWinToOlson(void) {
+    __CFSpinUnlock(&__CFTimeZoneWinToOlsonLock);
+}
+
+CFDictionaryRef CFTimeZoneCopyWinToOlsonDictionary(void) {
+    CFDictionaryRef dict;
+    __CFTimeZoneLockWinToOlson();
+    if (NULL == __CFTimeZoneWinToOlsonDict) {
+        CFDataRef data = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)__CFTimeZoneWinToOlsonDefaults, strlen(__CFTimeZoneWinToOlsonDefaults));
+        __CFTimeZoneWinToOlsonDict = (CFDictionaryRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListImmutable, NULL);
+        CFRelease(data);
+    }
+    if (NULL == __CFTimeZoneWinToOlsonDict) {
+        __CFTimeZoneWinToOlsonDict = CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, NULL, NULL);
+    }
+    dict = __CFTimeZoneWinToOlsonDict ? (CFDictionaryRef)CFRetain(__CFTimeZoneWinToOlsonDict) : NULL;
+    __CFTimeZoneUnlockWinToOlson();
+    return dict;
+}
+
+void CFTimeZoneSetWinToOlsonDictionary(CFDictionaryRef dict) {
+    __CFGenericValidateType(dict, CFDictionaryGetTypeID());
+    __CFTimeZoneLockWinToOlson();
+    if (dict != __CFTimeZoneWinToOlsonDict) {
+        if (dict) CFRetain(dict);
+        if (__CFTimeZoneWinToOlsonDict) CFRelease(__CFTimeZoneWinToOlsonDict);
+        __CFTimeZoneWinToOlsonDict = dict;
+    }
+    __CFTimeZoneUnlockWinToOlson();
+}
+
+CFTimeZoneRef CFTimeZoneCreateWithWindowsName(CFAllocatorRef allocator, CFStringRef winName) {
+    if (!winName) return NULL;
+    
+    CFDictionaryRef winToOlson = CFTimeZoneCopyWinToOlsonDictionary();
+    if (!winToOlson) return NULL;
+    
+    CFStringRef olsonName = CFDictionaryGetValue(winToOlson, winName);
+    CFTimeZoneRef retval = NULL;
+    if (olsonName) {
+         retval = CFTimeZoneCreateWithName(allocator, olsonName, false);
+    }
+    CFRelease(winToOlson);
+    return retval;
+}
 
-    char *tzenv;
+extern CFStringRef _CFGetWindowsAppleSystemLibraryDirectory(void);
+void __InitTZStrings(void) {
+    static CFSpinLock_t __CFTZDirLock = CFSpinLockInit;
+    __CFSpinLock(&__CFTZDirLock);
+    if (!__tzZoneInfo) {
+        CFStringRef winDir = _CFGetWindowsAppleSystemLibraryDirectory();
+        __tzZoneInfo = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\\etc\\zoneinfo"), winDir);
+    }   
+    if (!__tzDir && __tzZoneInfo) {
+        int length = CFStringGetLength(__tzZoneInfo) + sizeof("\\zone.tab") + 1;
+        __tzDir = malloc(length); // If we don't use ascii, we'll need to malloc more space
+        if (!__tzDir || !CFStringGetCString(__tzZoneInfo, __tzDir, length, kCFStringEncodingASCII)) {
+            free(__tzDir);
+        } else {
+            strcat(__tzDir, "\\zone.tab");
+        }
+    }
+    __CFSpinUnlock(&__CFTZDirLock);
+}
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
+static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
+    CFTimeZoneRef result = NULL;
+    
+#if DEPLOYMENT_TARGET_WINDOWS_SYNC
+    CFStringRef name = NULL;
+    TIME_ZONE_INFORMATION tzi = { 0 };
+    DWORD rval = GetTimeZoneInformation(&tzi);
+    if (rval != TIME_ZONE_ID_INVALID) {
+        LPWSTR standardName = (LPWSTR)&tzi.StandardName;
+        CFStringRef cfStandardName = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (UInt8 *)standardName, wcslen(standardName)*sizeof(WCHAR), kCFStringEncodingUTF16LE, false);
+        if (cfStandardName) {
+            CFDictionaryRef winToOlson = CFTimeZoneCopyWinToOlsonDictionary();
+            if (winToOlson) {
+                name = CFDictionaryGetValue(winToOlson, cfStandardName);
+                if (name) CFRetain(name);
+                CFRelease(winToOlson);
+            }
+            CFRelease(cfStandardName);
+        }
+    } else {
+        CFLog(kCFLogLevelError, CFSTR("Couldn't get time zone information error %d"), GetLastError());
+    }
+    if (name) {
+#else
+    const char *tzenv;
     int ret;
     char linkbuf[CFMaxPathSize];
 
-    tzenv = getenv("TZFILE");
+    tzenv = __CFgetenv("TZFILE");
     if (NULL != tzenv) {
        CFStringRef name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)tzenv, strlen(tzenv), kCFStringEncodingUTF8, false);
        result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, false);
        CFRelease(name);
        if (result) return result;
     }
-    tzenv = getenv("TZ");
+    tzenv = __CFgetenv("TZ");
     if (NULL != tzenv) {
        CFStringRef name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)tzenv, strlen(tzenv), kCFStringEncodingUTF8, false);
        result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, true);
@@ -451,13 +770,15 @@ static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
        } else {
            name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf, strlen(linkbuf), kCFStringEncodingUTF8, false);
        }
+#endif
+
        result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, false);
        CFRelease(name);
        if (result) return result;
     }
     return CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorSystemDefault, 0.0);
 }
-#elif 0 || 0
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
 static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
     CFTimeZoneRef result = NULL;
 /* The GetTimeZoneInformation function retrieves the current
@@ -559,8 +880,10 @@ CFArrayRef CFTimeZoneCopyKnownNames(void) {
 /* TimeZone information locate in the registry for Win32
  * (Aleksey Dukhnyakov)
  */
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
         list = __CFCopyRecursiveDirectoryList();
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
+        list = __CFCopyWindowsTimeZoneList();
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
@@ -581,7 +904,7 @@ CFArrayRef CFTimeZoneCopyKnownNames(void) {
     return tzs;
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
 /* The criteria here are sort of: coverage for the U.S. and Europe,
  * large cities, abbreviation uniqueness, and perhaps a few others.
  * But do not make the list too large with obscure information.
@@ -641,7 +964,7 @@ static const char *__CFTimeZoneAbbreviationDefaults =
 "    <key>WIT</key>  <string>Asia/Jakarta</string>"
 " </dict>"
 " </plist>";
-#elif 0 || 0
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
 static const char *__CFTimeZoneAbbreviationDefaults =
 /* Mappings to time zones in Windows Registry are best-guess */
 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
@@ -724,13 +1047,9 @@ void CFTimeZoneSetAbbreviationDictionary(CFDictionaryRef dict) {
     if (dict != __CFTimeZoneAbbreviationDict) {
        if (dict) CFRetain(dict);
        if (__CFTimeZoneAbbreviationDict) {
-           CFIndex count, idx;
-           count = CFDictionaryGetCount(__CFTimeZoneAbbreviationDict);
-           CFTypeRef *keys = (CFTypeRef *)malloc(sizeof(CFTypeRef *) * count);
-           for (idx = 0; idx < count; idx++) {
-               CFDictionaryRemoveValue(__CFTimeZoneCache, (CFStringRef)keys[idx]);
+           for (id key in (id)__CFTimeZoneAbbreviationDict) {
+               CFDictionaryRemoveValue(__CFTimeZoneCache, (CFStringRef)key);
            }
-           free(keys);
            CFRelease(__CFTimeZoneAbbreviationDict);
        }
        __CFTimeZoneAbbreviationDict = dict;
@@ -780,7 +1099,7 @@ CFTimeZoneRef CFTimeZoneCreate(CFAllocatorRef allocator, CFStringRef name, CFDat
     return memory;
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
 static CFTimeZoneRef __CFTimeZoneCreateFixed(CFAllocatorRef allocator, int32_t seconds, CFStringRef name, int isDST) {
     CFTimeZoneRef result;
     CFDataRef data;
@@ -806,7 +1125,7 @@ static CFTimeZoneRef __CFTimeZoneCreateFixed(CFAllocatorRef allocator, int32_t s
     CFRelease(data);
     return result;
 }
-#elif 0 || 0
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
 static CFTimeZoneRef __CFTimeZoneCreateFixed(CFAllocatorRef allocator, int32_t seconds, CFStringRef name, int isDST) {
 /* CFTimeZoneRef->_data will contain TIME_ZONE_INFORMATION structure
  * to find current timezone
@@ -843,7 +1162,13 @@ CFTimeZoneRef CFTimeZoneCreateWithTimeIntervalFromGMT(CFAllocatorRef allocator,
     seconds -= ((ti < 0) ? -hour : hour) * 3600;
     minute = (ti < 0) ? (-seconds / 60) : (seconds / 60);
     if (fabs(ti) < 1.0) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
        name = (CFStringRef)CFRetain(CFSTR("GMT"));
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
+        name = (CFStringRef)CFRetain(CFSTR("Greenwich Standard Time"));
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
     } else {
        name = CFStringCreateWithFormat(allocator, NULL, CFSTR("GMT%c%02d%02d"), (ti < 0.0 ? '-' : '+'), hour, minute);
     }
@@ -871,12 +1196,42 @@ CFTimeZoneRef CFTimeZoneCreateWithName(CFAllocatorRef allocator, CFStringRef nam
        return (CFTimeZoneRef)CFRetain(result);
     }
     __CFTimeZoneUnlockGlobal();
-#if DEPLOYMENT_TARGET_MACOSX
+    CFIndex len = CFStringGetLength(name);
+    if (6 == len || 8 == len) {
+       UniChar buffer[8];
+       CFStringGetCharacters(name, CFRangeMake(0, len), buffer);
+       if ('G' == buffer[0] && 'M' == buffer[1] && 'T' == buffer[2] && ('+' == buffer[3] || '-' == buffer[3])) {
+           if (('0' <= buffer[4] && buffer[4] <= '9') && ('0' <= buffer[5] && buffer[5] <= '9')) {
+               int32_t hours = (buffer[4] - '0') * 10 + (buffer[5] - '0');
+               if (-14 <= hours && hours <= 14) {
+                   CFTimeInterval ti = hours * 3600.0;
+                   if (6 == len) {
+                       return CFTimeZoneCreateWithTimeIntervalFromGMT(allocator, ('-' == buffer[3] ? -1.0 : 1.0) * ti);
+                   } else {
+                       if (('0' <= buffer[6] && buffer[6] <= '9') && ('0' <= buffer[7] && buffer[7] <= '9')) {
+                           int32_t minutes = (buffer[6] - '0') * 10 + (buffer[7] - '0');
+                           if ((-14 == hours && 0 == minutes) || (14 == hours && 0 == minutes) || (0 <= minutes && minutes <= 59)) {
+                               ti = ti + minutes * 60.0;
+                               return CFTimeZoneCreateWithTimeIntervalFromGMT(allocator, ('-' == buffer[3] ? -1.0 : 1.0) * ti);
+                           }
+                       }
+                   }
+               }
+           }
+       }
+    }
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
     CFURLRef baseURL, tempURL;
     void *bytes;
     CFIndex length;
 
+#if DEPLOYMENT_TARGET_WINDOWS_SYNC
+    if (!__tzZoneInfo) __InitTZStrings();
+    if (!__tzZoneInfo) return NULL;
+    baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, __tzZoneInfo, kCFURLWindowsPathStyle, true);
+#else
     baseURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, CFSTR(TZZONEINFO), kCFURLPOSIXPathStyle, true);
+#endif
     if (tryAbbrev) {
        CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
        tzName = CFDictionaryGetValue(abbrevs, name);
@@ -896,9 +1251,15 @@ CFTimeZoneRef CFTimeZoneCreateWithName(CFAllocatorRef allocator, CFStringRef nam
        CFStringRef mapping = CFDictionaryGetValue(dict, name);
        if (mapping) {
            name = mapping;
+#if DEPLOYMENT_TARGET_WINDOWS_SYNC
+       } else if (CFStringHasPrefix(name, __tzZoneInfo)) {
+           CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
+           CFStringDelete(unprefixed, CFRangeMake(0, CFStringGetLength(__tzZoneInfo)));
+#else
        } else if (CFStringHasPrefix(name, CFSTR(TZZONEINFO))) {
            CFMutableStringRef unprefixed = CFStringCreateMutableCopy(kCFAllocatorSystemDefault, CFStringGetLength(name), name);
            CFStringDelete(unprefixed, CFRangeMake(0, sizeof(TZZONEINFO)));
+#endif
            mapping = CFDictionaryGetValue(dict, unprefixed);
            if (mapping) {
                name = mapping;
@@ -934,7 +1295,7 @@ CFTimeZoneRef CFTimeZoneCreateWithName(CFAllocatorRef allocator, CFStringRef nam
     }
     return result;
 }
-#elif 0 || 0
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
 /* Reading GMT offset and daylight flag from the registry
  * for TimeZone name
  * (Aleksey Dukhnyakov)
@@ -1053,35 +1414,187 @@ CFDataRef CFTimeZoneGetData(CFTimeZoneRef tz) {
     return tz->_data;
 }
 
+/* This function converts CFAbsoluteTime to (Win32) SYSTEMTIME
+ * (Aleksey Dukhnyakov)
+ */
+#if DEPLOYMENT_TARGET_WINDOWS
+BOOL __CFTimeZoneGetWin32SystemTime(SYSTEMTIME * sys_time, CFAbsoluteTime time)
+{
+    LONGLONG l;
+    FILETIME * ftime=(FILETIME*)&l;
+
+    /*  seconds between 1601 and 1970 : 11644473600,
+     *  seconds between 1970 and 2001 : 978307200,
+     *  FILETIME - number of 100-nanosecond intervals since January 1, 1601
+     */
+    l=(LONGLONG)(time+11644473600LL+978307200)*10000000;
+    if (FileTimeToSystemTime(ftime,sys_time))
+        return TRUE;
+    else
+        return FALSE;
+}
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
 CFTimeInterval CFTimeZoneGetSecondsFromGMT(CFTimeZoneRef tz, CFAbsoluteTime at) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
     CFIndex idx;
     CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval, tz, "_secondsFromGMTForAbsoluteTime:", at);
     __CFGenericValidateType(tz, CFTimeZoneGetTypeID());
     idx = __CFBSearchTZPeriods(tz, at);
     return __CFTZPeriodGMTOffset(&(tz->_periods[idx]));
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
+/* To calculate seconds from GMT, calculate current timezone time and
+ * subtract GMT timnezone time
+ * (Aleksey Dukhnyakov)
+ */
+       TIME_ZONE_INFORMATION tzi;
+       FILETIME ftime1,ftime2;
+       SYSTEMTIME stime0,stime1,stime2;
+       LONGLONG * l1= (LONGLONG*)&ftime1;
+    LONGLONG * l2= (LONGLONG*)&ftime2;
+    CFRange range={0,sizeof(TIME_ZONE_INFORMATION)};
+    double result;
+
+    CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval, tz, "_secondsFromGMTForAbsoluteTime:", at);
+
+    CFDataGetBytes(tz->_data,range,(UInt8 *)&tzi);
+
+    if (!__CFTimeZoneGetWin32SystemTime(&stime0,at) ||
+            !SystemTimeToTzSpecificLocalTime(&tzi,&stime0,&stime1) ||
+               !SystemTimeToFileTime(&stime1,&ftime1) )
+       {
+        CFAssert(0, __kCFLogAssertion, "Win32 system time/timezone failed !\n");
+               return 0;
+       }
+
+    tzi.DaylightDate.wMonth=0;
+       tzi.StandardDate.wMonth=0;
+    tzi.StandardBias=0;
+    tzi.DaylightBias=0;
+    tzi.Bias=0;
+
+       if ( !SystemTimeToTzSpecificLocalTime(&tzi,&stime0,&stime2) ||
+            !SystemTimeToFileTime(&stime2,&ftime2))
+    {
+        CFAssert(0, __kCFLogAssertion, "Win32 system time/timezone failed !\n");
+               return 0;
+    }
+    result=(double)((*l1-*l2)/10000000);
+       return result;
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 }
 
+#if DEPLOYMENT_TARGET_WINDOWS_SAFARI
+/*
+ * Get abbreviation for name for WIN32 platform
+ * (Aleksey Dukhnyakov)
+ */
+
+typedef struct {
+    CFStringRef tzName;
+    CFStringRef tzAbbr;
+} _CFAbbrFind;
+
+static void _CFFindKeyForValue(const void *key, const void *value, void *context) {
+    if ( ((_CFAbbrFind *)context)->tzAbbr != NULL ) {
+        if ( ((_CFAbbrFind *)context)->tzName == (CFStringRef) value ) {
+            ((_CFAbbrFind *)context)->tzAbbr = (CFStringRef)key ;
+        }
+    }
+}
+
+CFIndex __CFTimeZoneInitAbbrev(CFTimeZoneRef tz) {
+
+    if ( tz->_periods->abbrev == NULL ) {
+        _CFAbbrFind abbr = { NULL, NULL };
+        CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary();
+
+        CFDictionaryApplyFunction(abbrevs, _CFFindKeyForValue, &abbr);
+
+        if ( abbr.tzAbbr != NULL)
+            tz->_periods->abbrev = (CFStringRef)CFStringCreateCopy(kCFAllocatorSystemDefault, abbr.tzAbbr);
+        else
+            tz->_periods->abbrev = (CFStringRef)CFStringCreateCopy(kCFAllocatorSystemDefault, tz->_name);
+/* We should return name of TimeZone if couldn't find abbrevation.
+ * (Ala on MACOSX)
+ *
+ * (Aleksey Dukhnyakov)
+*/
+        CFRelease( abbrevs );
+    }
+
+    return 0;
+}
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+
 CFStringRef CFTimeZoneCopyAbbreviation(CFTimeZoneRef tz, CFAbsoluteTime at) {
     CFStringRef result;
     CFIndex idx;
     CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFStringRef, tz, "_abbreviationForAbsoluteTime:", at);
     __CFGenericValidateType(tz, CFTimeZoneGetTypeID());
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
     idx = __CFBSearchTZPeriods(tz, at);
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
+/*
+ * Initialize abbreviation for this TimeZone
+ * (Aleksey Dukhnyakov)
+ */
+    idx = __CFTimeZoneInitAbbrev(tz);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     result = __CFTZPeriodAbbreviation(&(tz->_periods[idx]));
     return result ? (CFStringRef)CFRetain(result) : NULL;
 }
 
 Boolean CFTimeZoneIsDaylightSavingTime(CFTimeZoneRef tz, CFAbsoluteTime at) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS_SYNC
     CFIndex idx;
     CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), Boolean, tz, "_isDaylightSavingTimeForAbsoluteTime:", at);
     __CFGenericValidateType(tz, CFTimeZoneGetTypeID());
     idx = __CFBSearchTZPeriods(tz, at);
     return __CFTZPeriodIsDST(&(tz->_periods[idx]));
+#elif DEPLOYMENT_TARGET_WINDOWS_SAFARI
+/* Compare current timezone time and current timezone time without
+ * transition to day light saving time
+ * (Aleskey Dukhnyakov)
+ */
+       TIME_ZONE_INFORMATION tzi;
+       SYSTEMTIME stime0,stime1,stime2;
+    CFRange range={0,sizeof(TIME_ZONE_INFORMATION)};
+
+    CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), Boolean, tz, "_isDaylightSavingTimeForAbsoluteTime:", at);
+
+    CFDataGetBytes(tz->_data,range,(UInt8 *)&tzi);
+
+       if ( !__CFTimeZoneGetWin32SystemTime(&stime0,at) ||
+            !SystemTimeToTzSpecificLocalTime(&tzi,&stime0,&stime1)) {
+        CFAssert(0, __kCFLogAssertion, "Win32 system time/timezone failed !\n");
+               return FALSE;
+    }
+
+    tzi.DaylightDate.wMonth=0;
+       tzi.StandardDate.wMonth=0;
+
+       if ( !SystemTimeToTzSpecificLocalTime(&tzi,&stime0,&stime2)) {
+        CFAssert(0, __kCFLogAssertion, "Win32 system time/timezone failed !\n");
+               return FALSE;
+    }
+
+    if ( !memcmp(&stime1,&stime2,sizeof(stime1)) )
+        return FALSE;
+
+    return TRUE;
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 }
 
@@ -1110,11 +1623,6 @@ CFAbsoluteTime CFTimeZoneGetNextDaylightSavingTimeTransition(CFTimeZoneRef tz, C
     return (CFAbsoluteTime)__CFTZPeriodStartSeconds(&(tz->_periods[idx + 1]));
 }
 
-enum {
-       kCFTimeZoneNameStyleGeneric = 4,
-       kCFTimeZoneNameStyleShortGeneric = 5
-};
-
 extern UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz);
 
 #define BUFFER_SIZE 768
@@ -1124,6 +1632,14 @@ CFStringRef CFTimeZoneCopyLocalizedName(CFTimeZoneRef tz, CFTimeZoneNameStyle st
     __CFGenericValidateType(tz, CFTimeZoneGetTypeID());
     __CFGenericValidateType(locale, CFLocaleGetTypeID());
 
+    if (style == kCFTimeZoneNameStyleGeneric || style == kCFTimeZoneNameStyleShortGeneric) {
+       CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorSystemDefault, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
+       CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz);
+       CFDateFormatterSetFormat(df, (style == kCFTimeZoneNameStyleGeneric) ? CFSTR("vvvv") : CFSTR("v"));
+       CFStringRef str = CFDateFormatterCreateStringWithAbsoluteTime(CFGetAllocator(tz), df, 0.0);
+       CFRelease(df);
+       return str;
+    }
 
     CFStringRef localeID = CFLocaleGetIdentifier(locale);
     UCalendar *cal = __CFCalendarCreateUCalendar(NULL, localeID, tz);
index 8b976fb5e3ccdce9a986986af51e4bcfb89d502c..91fe02a784f00ad3b08fca8fecc65dbe4d9b6f10 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFTimeZone.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFTIMEZONE__)
@@ -95,7 +95,9 @@ enum {
        kCFTimeZoneNameStyleStandard,
        kCFTimeZoneNameStyleShortStandard,
        kCFTimeZoneNameStyleDaylightSaving,
-       kCFTimeZoneNameStyleShortDaylightSaving
+       kCFTimeZoneNameStyleShortDaylightSaving,
+       kCFTimeZoneNameStyleGeneric,
+       kCFTimeZoneNameStyleShortGeneric
 };
 typedef CFIndex CFTimeZoneNameStyle;
 
index a01feaf6d915c5e0c00e473595222c11d7e26a77..4d6ff8f52ef471b00b6aaa42aa65ab6efec825d5 100644 (file)
--- a/CFTree.c
+++ b/CFTree.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFTree.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
 #include <CoreFoundation/CFTree.h>
 #include "CFInternal.h"
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 
 struct __CFTreeCallBacks {
     CFTreeRetainCallBack               retain;
@@ -227,7 +227,7 @@ void CFTreeSetContext(CFTreeRef tree, const CFTreeContext *context) {
         newtype = __kCFTreeHasCFTypeCallBacks;
     } else {
         newtype = __kCFTreeHasCustomCallBacks;
-        CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree, tree->_callbacks, _CFAllocatorAllocateGC(allocator, sizeof(struct __CFTreeCallBacks), 0));
+        __CFAssignWithWriteBarrier((void **)&tree->_callbacks, _CFAllocatorAllocateGC(allocator, sizeof(struct __CFTreeCallBacks), 0));
         if (__CFOASafe) __CFSetLastAllocationEventName(tree->_callbacks, "CFTree (callbacks)");
         tree->_callbacks->retain = context->retain;
         tree->_callbacks->release = context->release;
@@ -241,7 +241,7 @@ void CFTreeSetContext(CFTreeRef tree, const CFTreeContext *context) {
     if (NULL != newcb->retain) {
         tree->_info = (void *)INVOKE_CALLBACK1(newcb->retain, context->info);
     } else {
-        CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree, tree->_info, context->info);
+        __CFAssignWithWriteBarrier((void **)&tree->_info, context->info);
     }
     if (NULL != oldcb->release) {
         INVOKE_CALLBACK1(oldcb->release, oldinfo);
@@ -324,18 +324,17 @@ void CFTreeApplyFunctionToChildren(CFTreeRef tree, CFTreeApplierFunction applier
 }
 
 void CFTreePrependChild(CFTreeRef tree, CFTreeRef newChild) {
-    CFAllocatorRef allocator = CFGetAllocator(tree);
     __CFGenericValidateType(tree, __kCFTreeTypeID);
     __CFGenericValidateType(newChild, __kCFTreeTypeID);
     CFAssert1(NULL == newChild->_parent, __kCFLogAssertion, "%s(): must remove newChild from previous parent first", __PRETTY_FUNCTION__);
     CFAssert1(NULL == newChild->_sibling, __kCFLogAssertion, "%s(): must remove newChild from previous parent first", __PRETTY_FUNCTION__);
     _CFRetainGC(newChild);
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, newChild, newChild->_parent, tree);
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, newChild, newChild->_sibling, tree->_child);
+    __CFAssignWithWriteBarrier((void **)&newChild->_parent, tree);
+    __CFAssignWithWriteBarrier((void **)&newChild->_sibling, tree->_child);
     if (!tree->_child) {
-        CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree, tree->_rightmostChild, newChild);
+        __CFAssignWithWriteBarrier((void **)&tree->_rightmostChild, newChild);
     }
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree, tree->_child, newChild);
+    __CFAssignWithWriteBarrier((void **)&tree->_child, newChild);
 }
 
 void CFTreeAppendChild(CFTreeRef tree, CFTreeRef newChild) {
@@ -349,14 +348,14 @@ void CFTreeAppendChild(CFTreeRef tree, CFTreeRef newChild) {
     }
     _CFRetainGC(newChild);
     allocator = CFGetAllocator(tree);
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, newChild, newChild->_parent, tree);
+    __CFAssignWithWriteBarrier((void **)&newChild->_parent, tree);
     newChild->_sibling = NULL;
     if (!tree->_child) {
-        CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree, tree->_child, newChild);
+        __CFAssignWithWriteBarrier((void **)&tree->_child, newChild);
     } else {
-        CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree->_rightmostChild, tree->_rightmostChild->_sibling, newChild);
+        __CFAssignWithWriteBarrier((void **)&tree->_rightmostChild->_sibling, newChild);
     }
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree, tree->_rightmostChild, newChild);
+    __CFAssignWithWriteBarrier((void **)&tree->_rightmostChild, newChild);
 }
 
 void CFTreeInsertSibling(CFTreeRef tree, CFTreeRef newSibling) {
@@ -368,12 +367,12 @@ void CFTreeInsertSibling(CFTreeRef tree, CFTreeRef newSibling) {
     CFAssert1(NULL == newSibling->_sibling, __kCFLogAssertion, "%s(): must remove newSibling from previous parent first", __PRETTY_FUNCTION__);
     _CFRetainGC(newSibling);
     allocator = CFGetAllocator(tree);
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, newSibling, newSibling->_parent, tree->_parent);
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, newSibling, newSibling->_sibling, tree->_sibling);
-    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree, tree->_sibling, newSibling);
+    __CFAssignWithWriteBarrier((void **)&newSibling->_parent, tree->_parent);
+    __CFAssignWithWriteBarrier((void **)&newSibling->_sibling, tree->_sibling);
+    __CFAssignWithWriteBarrier((void **)&tree->_sibling, newSibling);
     if (tree->_parent) {
         if (tree->_parent->_rightmostChild == tree) {
-            CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree->_parent, tree->_parent->_rightmostChild, newSibling);
+            __CFAssignWithWriteBarrier((void **)&tree->_parent->_rightmostChild, newSibling);
         }
     }
 }
@@ -381,9 +380,8 @@ void CFTreeInsertSibling(CFTreeRef tree, CFTreeRef newSibling) {
 void CFTreeRemove(CFTreeRef tree) {
     __CFGenericValidateType(tree, __kCFTreeTypeID);
     if (NULL != tree->_parent) {
-        CFAllocatorRef allocator = CFGetAllocator(tree);
        if (tree == tree->_parent->_child) {
-            CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree->_parent, tree->_parent->_child, tree->_sibling);
+            __CFAssignWithWriteBarrier((void **)&tree->_parent->_child, tree->_sibling);
             if (tree->_sibling == NULL) {
                 tree->_parent->_rightmostChild = NULL;
             }
@@ -391,9 +389,9 @@ void CFTreeRemove(CFTreeRef tree) {
            CFTreeRef prevSibling = NULL;
            for (prevSibling = tree->_parent->_child; prevSibling; prevSibling = prevSibling->_sibling) {
                if (prevSibling->_sibling == tree) {
-                    CF_WRITE_BARRIER_BASE_ASSIGN(allocator, prevSibling, prevSibling->_sibling, tree->_sibling);
+                    __CFAssignWithWriteBarrier((void **)&prevSibling->_sibling, tree->_sibling);
                     if (tree->_parent->_rightmostChild == tree) {
-                        CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree->_parent, tree->_parent->_rightmostChild, prevSibling);
+                        __CFAssignWithWriteBarrier((void **)&tree->_parent->_rightmostChild, prevSibling);
                     }
                    break;
                }
@@ -441,7 +439,6 @@ void CFTreeSortChildren(CFTreeRef tree, CFComparatorFunction comparator, void *c
         CFTreeRef nextChild;
         struct _tcompareContext ctx;
         CFTreeRef *list, buffer[128];
-        CFAllocatorRef allocator = __CFGetAllocator(tree);
 
         list = (children < 128) ? buffer : (CFTreeRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, children * sizeof(CFTreeRef), 0); // XXX_PCB GC OK
        if (__CFOASafe && list != buffer) __CFSetLastAllocationEventName(tree->_callbacks, "CFTree (temp)");
@@ -455,9 +452,9 @@ void CFTreeSortChildren(CFTreeRef tree, CFComparatorFunction comparator, void *c
         ctx.context = context;
         CFQSortArray(list, children, sizeof(CFTreeRef), (CFComparatorFunction)__CFTreeCompareValues, &ctx);
 
-        CF_WRITE_BARRIER_BASE_ASSIGN(allocator, tree, tree->_child, list[0]);
+        __CFAssignWithWriteBarrier((void **)&tree->_child, list[0]);
         for (idx = 1; idx < children; idx++) {
-            CF_WRITE_BARRIER_BASE_ASSIGN(allocator, list[idx - 1], list[idx - 1]->_sibling, list[idx]);
+            __CFAssignWithWriteBarrier((void **)&list[idx - 1]->_sibling, list[idx]);
         }
         list[idx - 1]->_sibling = NULL;
         tree->_rightmostChild = list[children - 1];
index 1262498bf19177a85c31c970401ff2425c5b3eed..5e549be5a7d1d325c5420cb97312f662ca1eccaa 100644 (file)
--- a/CFTree.h
+++ b/CFTree.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFTree.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 /*!
         @header CFTree
diff --git a/CFURL.c b/CFURL.c
index 95a587273cf66adf891c81ce15942a2670f6d2a1..dfeae68b5e870dc4d66164adcca50e92cc3a4f7c 100644 (file)
--- a/CFURL.c
+++ b/CFURL.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFURL.c
-       Copyright 1998-2004, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Becky Willrich
 */
 
 #include <CoreFoundation/CFURL.h>
-#include "CFPriv.h"
-#include "CFCharacterSetPriv.h"
+#include <CoreFoundation/CFPriv.h>
+#include <CoreFoundation/CFCharacterSetPriv.h>
 #include <CoreFoundation/CFNumber.h>
 #include "CFInternal.h"
-#include "CFStringEncodingConverter.h"
-#include "CFPriv.h"
+#include <CoreFoundation/CFStringEncodingConverter.h>
+#include <CoreFoundation/CFPriv.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #if DEPLOYMENT_TARGET_MACOSX
+#include <CoreFoundation/CFNumberFormatter.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#elif DEPLOYMENT_TARGET_EMBEDDED
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static CFArrayRef HFSPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir);
+#endif
 static CFArrayRef WindowsPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir);
 static CFStringRef WindowsPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir);
 static CFStringRef POSIXPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDirectory);
 CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLRef anURL, CFURLPathStyle fsType, Boolean resolveAgainstBase);
-extern CFURLRef _CFURLCreateCurrentDirectoryURL(CFAllocatorRef allocator);
-
-#if DEPLOYMENT_TARGET_MACOSX
-
-DEFINE_WEAK_CARBONCORE_FUNC(void, DisposeHandle, (Handle A), (A))
-DEFINE_WEAK_CARBONCORE_FUNC(OSErr, FSNewAlias, (const FSRef *A, const FSRef *B, AliasHandle *C), (A, B, C), -3296)
-DEFINE_WEAK_CARBONCORE_FUNC(OSErr, FSGetVolumeInfo, (FSVolumeRefNum A, ItemCount B, FSVolumeRefNum *C, FSVolumeInfoBitmap D, FSVolumeInfo *E, HFSUniStr255*F, FSRef *G), (A, B, C, D, E, F, G), -3296)
-DEFINE_WEAK_CARBONCORE_FUNC(OSErr, FSGetCatalogInfo, (const FSRef *A, FSCatalogInfoBitmap B, FSCatalogInfo *C, HFSUniStr255 *D, FSSpec *E, FSRef *F), (A, B, C, D, E, F), -3296)
-DEFINE_WEAK_CARBONCORE_FUNC(OSErr, FSMakeFSRefUnicode, (const FSRef *A, UniCharCount B, const UniChar *C, TextEncoding D, FSRef *E), (A, B, C, D, E), -3296)
-DEFINE_WEAK_CARBONCORE_FUNC(OSStatus, FSPathMakeRef, (const uint8_t *A, FSRef *B, Boolean *C), (A, B, C), -3296)
-DEFINE_WEAK_CARBONCORE_FUNC(OSStatus, FSRefMakePath, (const FSRef *A, uint8_t *B, UInt32 C), (A, B, C), -3296)
-DEFINE_WEAK_CARBONCORE_FUNC(OSErr, FSpMakeFSRef, (const FSSpec *A, FSRef *B), (A, B), -3296)
-DEFINE_WEAK_CARBONCORE_FUNC(Size, GetAliasSizeFromPtr, (AliasPtr A), (A), 0)
-DEFINE_WEAK_CARBONCORE_FUNC(OSErr, _FSGetFSRefInformationFast, (const FSRef* A, SInt16 *B, UInt32 *C, UInt32 *D, Boolean *E, Boolean *F, HFSUniStr255 *G), (A, B, C, D, E, F, G), -3296)
-DEFINE_WEAK_CARBONCORE_FUNC(OSErr, _FSGetVolumeByName, ( CFStringRef volumeNameRef, FSVolumeRefNum* vRefNumP), ( volumeNameRef, vRefNumP), -3296 )
-
-#elif 0 || 0 || 0
+CF_EXPORT CFURLRef _CFURLCreateCurrentDirectoryURL(CFAllocatorRef allocator);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir);
+#elif DEPLOYMENT_TARGET_WINDOWS
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 
+
 #ifndef DEBUG_URL_MEMORY_USAGE
 #define DEBUG_URL_MEMORY_USAGE 0
 #endif
@@ -82,6 +80,7 @@ static UInt32 numURLs = 0;
 static UInt32 numDealloced = 0;
 static UInt32 numExtraDataAllocated = 0;
 static UInt32 numURLsWithBaseURL = 0;
+static UInt32 numNonUTF8EncodedURLs = 0;
 #endif
 
 /* The bit flags in myURL->_flags */
@@ -119,7 +118,7 @@ static UInt32 numURLsWithBaseURL = 0;
 //     #define PATH_DIFFERS       (0x08000000) unused
 // #define PARAMETERS_DIFFER  (0x10000000)     unused
 // #define QUERY_DIFFERS      (0x20000000)     unused
-// #define FRAGMENT_DIFfERS   (0x40000000)     unused
+#define PATH_HAS_FILE_ID    (0x40000000)
 #define HAS_FILE_SCHEME                (0x80000000)
 
 // Number of bits to shift to get from HAS_FOO to FOO_DIFFERS flag
@@ -135,23 +134,29 @@ static UInt32 numURLsWithBaseURL = 0;
 #define PATH_DELIM_FOR_TYPE(fsType) ((fsType) == kCFURLHFSPathStyle ? ':' : (((fsType) == kCFURLWindowsPathStyle) ? '\\' : '/'))
 #define PATH_DELIM_AS_STRING_FOR_TYPE(fsType) ((fsType) == kCFURLHFSPathStyle ? CFSTR(":") : (((fsType) == kCFURLWindowsPathStyle) ? CFSTR("\\") : CFSTR("/")))
 
+#define FILE_ID_PREFIX ".file"
+#define FILE_ID_KEY "id"
+
+#define ASSERT_CHECK_PATHSTYLE(x) 0
 
-//     In order to get the sizeof ( __CFURL ) < 32 bytes, move these items into a seperate structure which is
+//     In order to reduce the sizeof ( __CFURL ), move these items into a seperate structure which is
 //     only allocated when necessary.  In my tests, it's almost never needed -- very rarely does a CFURL have
 //     either a sanitized string or a reserved pointer for URLHandle.
 struct _CFURLAdditionalData {
     void *_reserved; // Reserved for URLHandle's use.
     CFMutableStringRef _sanitizedString; // The fully compliant RFC string.  This is only non-NULL if ORIGINAL_AND_URL_STRINGS_MATCH is false.  This should never be mutated except when the sanatized string is first computed
+    CFHashCode hashValue;
 };
 
 struct __CFURL {
     CFRuntimeBase _cfBase;
     UInt32 _flags;
-    CFStringRef  _string; // Never NULL; the meaning of _string depends on URL_PATH_TYPE(myURL) (see above)
-       CFURLRef        _base;
-    CFRange *ranges;
     CFStringEncoding _encoding; // The encoding to use when asked to remove percent escapes; this is never consulted if IS_OLD_UTF8_STYLE is set.
-       struct _CFURLAdditionalData* extra;
+    CFStringRef _string; // Never NULL; the meaning of _string depends on URL_PATH_TYPE(myURL) (see above)
+    CFURLRef _base;
+    CFRange *ranges;
+    struct _CFURLAdditionalData* extra;
+    void *_resourceInfo;    // For use by CarbonCore to cache property values. Retained and released by CFURL.
 };
 
 
@@ -171,20 +176,30 @@ CF_INLINE CFMutableStringRef _getSanitizedString ( const struct __CFURL* url )
        return NULL;
 }
 
+static void* _getResourceInfo ( const struct __CFURL* url )
+{
+    if ( url ) {
+        return url->_resourceInfo;
+    }
+
+    return NULL;
+}
+
 static void _CFURLAllocateExtraDataspace( struct __CFURL* url )
 {      
-       if ( url && ! url->extra )
-       {       struct _CFURLAdditionalData* extra = (struct _CFURLAdditionalData*) CFAllocatorAllocate( CFGetAllocator( url), sizeof( struct _CFURLAdditionalData ), __kCFAllocatorGCScannedMemory);
+    if ( url && ! url->extra )
+    {  struct _CFURLAdditionalData* extra = (struct _CFURLAdditionalData*) CFAllocatorAllocate( CFGetAllocator( url), sizeof( struct _CFURLAdditionalData ), __kCFAllocatorGCScannedMemory);
        
-               extra->_reserved = _getReserved( url );
-               extra->_sanitizedString = _getSanitizedString( url );
-               
-               url->extra = extra;
-               
-               #if DEBUG_URL_MEMORY_USAGE
-               numExtraDataAllocated ++;
-               #endif
-       }
+       extra->_reserved = _getReserved( url );
+       extra->_sanitizedString = _getSanitizedString( url );
+       extra->hashValue = 0;
+       
+       url->extra = extra;
+       
+       #if DEBUG_URL_MEMORY_USAGE
+       numExtraDataAllocated ++;
+       #endif
+    }
 }
 
 CF_INLINE void _setReserved ( struct __CFURL* url, void* reserved )
@@ -196,7 +211,7 @@ CF_INLINE void _setReserved ( struct __CFURL* url, void* reserved )
                        _CFURLAllocateExtraDataspace( url );
                
                if ( url->extra )
-                       CF_WRITE_BARRIER_BASE_ASSIGN(CFGetAllocator(url), url->extra, url->extra->_reserved, reserved);
+                       __CFAssignWithWriteBarrier((void **)&url->extra->_reserved, reserved);
        }
 }
 
@@ -213,6 +228,15 @@ CF_INLINE void _setSanitizedString ( struct __CFURL* url, CFMutableStringRef san
        }
 }
 
+static void _setResourceInfo ( struct __CFURL* url, void* resourceInfo )
+{
+    // Must be atomic
+    // Never a GC object
+    if ( url && OSAtomicCompareAndSwapPtrBarrier( NULL, resourceInfo, &url->_resourceInfo )) {
+       CFRetain( resourceInfo );
+    }
+}
+
 static void _convertToURLRepresentation(struct __CFURL *url);
 static CFURLRef _CFURLCopyAbsoluteFileURL(CFURLRef relativeURL);
 static CFStringRef _resolveFileSystemPaths(CFStringRef relativePath, CFStringRef basePath, Boolean baseIsDir, CFURLPathStyle fsType, CFAllocatorRef alloc);
@@ -283,7 +307,7 @@ static const unsigned char sURLValidCharacters[] = {
        /* '='  61 */   VALID | PATHVALID ,
        /* '>'  62 */   0,
        /* '?'  63 */   VALID ,
-       /* '@'  64 */   VALID | PATHVALID ,
+       /* '@'  64 */   VALID ,
        /* 'A'  65 */   VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT ,
        /* 'B'  66 */   VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT ,
        /* 'C'  67 */   VALID | UNRESERVED | SCHEME | PATHVALID | HEXDIGIT ,
@@ -392,6 +416,7 @@ CF_INLINE Boolean _haveTestedOriginalString(CFURLRef url) {
 }
 
 typedef CFStringRef (*StringTransformation)(CFAllocatorRef, CFStringRef, CFIndex);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static CFArrayRef copyStringArrayWithTransformation(CFArrayRef array, StringTransformation transformation) {
     CFAllocatorRef alloc = CFGetAllocator(array);
     CFMutableArrayRef mArray = NULL;
@@ -420,6 +445,7 @@ static CFArrayRef copyStringArrayWithTransformation(CFArrayRef array, StringTran
         return array;
     }
 }
+#endif
 
 // Returns NULL if str cannot be converted for whatever reason, str if str contains no characters in need of escaping, or a newly-created string with the appropriate % escape codes in place.  Caller must always release the returned string.
 CF_INLINE CFStringRef _replacePathIllegalCharacters(CFStringRef str, CFAllocatorRef alloc, Boolean preserveSlashes) {
@@ -430,9 +456,11 @@ CF_INLINE CFStringRef _replacePathIllegalCharacters(CFStringRef str, CFAllocator
     }        
 }
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static CFStringRef escapePathComponent(CFAllocatorRef alloc, CFStringRef origComponent, CFIndex componentIndex) {
     return CFURLCreateStringByAddingPercentEscapes(alloc, origComponent, NULL, CFSTR(";?/"), kCFStringEncodingUTF8);
 }
+#endif
 
 // We have 2 UniChars of a surrogate; we must convert to the correct percent-encoded UTF8 string and append to str.  Added so that file system URLs can always be converted from POSIX to full URL representation.  -- REW, 8/20/2001
 static Boolean _hackToConvertSurrogates(UniChar highChar, UniChar lowChar, CFMutableStringRef str) {
@@ -838,6 +866,76 @@ CF_EXPORT CFStringRef CFURLCreateStringByAddingPercentEscapes(CFAllocatorRef all
     return _addPercentEscapesToString(allocator, originalString, _shouldPercentReplaceChar, NULL, encoding, strings);
 }
  
+
+#if 0
+static Boolean __CFURLCompare(CFTypeRef  cf1, CFTypeRef  cf2) {
+    CFURLRef  url1 = (CFURLRef)cf1;
+    CFURLRef  url2 = (CFURLRef)cf2;
+    UInt32 pathType1, pathType2;
+    
+    __CFGenericValidateType(cf1, CFURLGetTypeID());
+    __CFGenericValidateType(cf2, CFURLGetTypeID());
+    
+    if (url1 == url2) return kCFCompareEqualTo;
+    
+    if ( url1->_base ) {
+        if (! url2->_base) return kCFCompareEqualTo;
+        if (!CFEqual( url1->_base, url2->_base )) return false;
+    } else if ( url2->_base) {
+        return false;
+    }
+    
+    pathType1 = URL_PATH_TYPE(url1);
+    pathType2 = URL_PATH_TYPE(url2);
+    if (pathType1 == pathType2) {
+        if (pathType1 != FULL_URL_REPRESENTATION) {
+            return CFEqual(url1->_string, url2->_string);
+        } else {
+            // Do not compare the original strings; compare the sanatized strings.
+            return CFEqual(CFURLGetString(url1), CFURLGetString(url2));
+        }
+    } else {
+        // Try hard to avoid the expensive conversion from a file system representation to the canonical form
+        CFStringRef scheme1 = CFURLCopyScheme(url1);
+        CFStringRef scheme2 = CFURLCopyScheme(url2);
+        Boolean eq;
+        if (scheme1 && scheme2) {
+            eq = CFEqual(scheme1, scheme2);
+            CFRelease(scheme1);
+            CFRelease(scheme2);
+        } else if (!scheme1 && !scheme2) {
+            eq = TRUE;
+        } else {
+            eq = FALSE;
+            if (scheme1) CFRelease(scheme1);
+            else CFRelease(scheme2);
+        }
+        if (!eq) return false;
+       
+        if (pathType1 == FULL_URL_REPRESENTATION) {
+            if (!(url1->_flags & IS_PARSED)) {
+                _parseComponentsOfURL(url1);
+            }
+            if (url1->_flags & (HAS_USER | HAS_PORT | HAS_PASSWORD | HAS_QUERY | HAS_PARAMETERS | HAS_FRAGMENT )) {
+                return false;
+            }
+        }
+       
+        if (pathType2 == FULL_URL_REPRESENTATION) {
+            if (!(url2->_flags & IS_PARSED)) {
+                _parseComponentsOfURL(url2);
+            }
+            if (url2->_flags & (HAS_USER | HAS_PORT | HAS_PASSWORD | HAS_QUERY | HAS_PARAMETERS | HAS_FRAGMENT )) {
+                return false;
+            }
+        }
+       
+        // No help for it; we now must convert to the canonical representation and compare.
+        return CFEqual(CFURLGetString(url1), CFURLGetString(url2));
+    }
+}
+#endif
+
 static Boolean __CFURLEqual(CFTypeRef  cf1, CFTypeRef  cf2) {
     CFURLRef  url1 = (CFURLRef)cf1;
     CFURLRef  url2 = (CFURLRef)cf2;
@@ -907,27 +1005,46 @@ static Boolean __CFURLEqual(CFTypeRef  cf1, CFTypeRef  cf2) {
 
 static CFHashCode __CFURLHash(CFTypeRef  cf) {
     /* This is tricky, because we do not want the hash value to change as a file system URL is changed to its canonical representation, nor do we wish to force the conversion to the canonical representation. We choose instead to take the last path component (or "/" in the unlikely case that the path is empty), then hash on that. */
-    CFURLRef  url = (CFURLRef)cf;
-    UInt32 result;
-    if (CFURLCanBeDecomposed(url)) {
-        CFStringRef lastComp = CFURLCopyLastPathComponent(url);
-               CFStringRef     hostNameRef = CFURLCopyHostName(url );
-               
-               result = 0;
-               
-        if (lastComp) {
-            result = CFHash(lastComp);
-            CFRelease(lastComp);
-        }
-               
-               if ( hostNameRef )
-               {
+    struct __CFURL*  url = (struct __CFURL*)cf;
+    CFHashCode result = 0;
+    
+    if ( url )
+    {
+       //  Allocate our extra space if it isn't already allocated
+       if ( url && ! url->extra )
+           _CFURLAllocateExtraDataspace( url );
+       
+       if ( url->extra ) {
+           result = url->extra->hashValue;
+           
+           if ( ! result ) {
+               if (CFURLCanBeDecomposed(url)) {
+                   CFStringRef lastComp = CFURLCopyLastPathComponent(url);
+                   CFStringRef hostNameRef = CFURLCopyHostName(url );
+                   
+                   result = 0;
+                   
+                   if (lastComp) {
+                       result = CFHash(lastComp);
+                       CFRelease(lastComp);
+                   }
+                   
+                   if ( hostNameRef ) {
                        result ^= CFHash( hostNameRef );
                        CFRelease( hostNameRef );
+                   }
+               } else {
+                   result = CFHash(CFURLGetString(url));
                }
-    } else {
-        result = CFHash(CFURLGetString(url));
+               
+               if ( ! result )     //  never store a 0 value for the hashed value
+                   result = 1;
+               
+               url->extra->hashValue = result;
+           }
+       }
     }
+    
     return result;
 }
 
@@ -950,10 +1067,10 @@ static CFStringRef __CFURLCopyDescription(CFTypeRef cf) {
     CFAllocatorRef alloc = CFGetAllocator(url);
     if ( url->_base) {
         CFStringRef baseString = CFCopyDescription(url->_base);
-        result = CFStringCreateWithFormat(alloc, NULL, CFSTR("<CFURL %p [%p]>{type = %d, string = %@,\n\tbase = %@}"), cf, alloc, URL_PATH_TYPE(url), url->_string, baseString);
+        result = CFStringCreateWithFormat(alloc, NULL, CFSTR("<CFURL %p [%p]>{type = %d, string = %@, encoding = %d\n\tbase = %@}"), cf, alloc, URL_PATH_TYPE(url), url->_string, url->_encoding, baseString);
         CFRelease(baseString);
     } else {
-        result = CFStringCreateWithFormat(alloc, NULL, CFSTR("<CFURL %p [%p]>{type = %d, string = %@, base = (null)}"), cf, alloc, URL_PATH_TYPE(url), url->_string);
+        result = CFStringCreateWithFormat(alloc, NULL, CFSTR("<CFURL %p [%p]>{type = %d, string = %@, encoding = %d, base = (null)}"), cf, alloc, URL_PATH_TYPE(url), url->_string, url->_encoding);
     }
     return result;
 }
@@ -961,7 +1078,7 @@ static CFStringRef __CFURLCopyDescription(CFTypeRef cf) {
 #if DEBUG_URL_MEMORY_USAGE
 
 extern __attribute((used)) void __CFURLDumpMemRecord(void) {
-    CFStringRef str = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%d URLs created; %d destroyed\n%d file URLs created; %d converted; %d destroyed.  %d urls had 'extra' data allocated, %d had base urls\n"), numURLs, numDealloced, numFileURLsCreated, numFileURLsConverted, numFileURLsDealloced, numExtraDataAllocated, numURLsWithBaseURL );
+    CFStringRef str = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%d URLs created; %d destroyed\n%d file URLs created; %d converted; %d destroyed.  %d urls had 'extra' data allocated, %d had base urls, %d were not UTF8 encoded\n"), numURLs, numDealloced, numFileURLsCreated, numFileURLsConverted, numFileURLsDealloced, numExtraDataAllocated, numURLsWithBaseURL, numNonUTF8EncodedURLs );
     CFShow(str);
     CFRelease(str);
     // if (URLAllocator) CFCountingAllocatorPrintPointers(URLAllocator);
@@ -983,9 +1100,8 @@ static void __CFURLDeallocate(CFTypeRef  cf) {
     if (url->_base) CFRelease(url->_base);
     if (url->ranges) CFAllocatorDeallocate(alloc, url->ranges);
     if (_getSanitizedString(url)) CFRelease(_getSanitizedString(url));
-       
-       if ( url->extra != NULL )
-               CFAllocatorDeallocate( alloc, url->extra );
+    if ( url->extra != NULL ) CFAllocatorDeallocate( alloc, url->extra );
+    if (_getResourceInfo(url)) CFRelease(_getResourceInfo(url));
 }
 
 static CFTypeID __kCFURLTypeID = _kCFRuntimeNotATypeID;
@@ -1146,19 +1262,15 @@ static void _parseComponents(CFAllocatorRef alloc, CFStringRef string, CFURLRef
             ranges[0].location = base_idx;
             ranges[0].length = idx;
             numRanges ++;
-                       base_idx = idx + 1;
-                       // optimization for http urls
-                       if (idx == 4 && STRING_CHAR(0) == 'h' && STRING_CHAR(1) == 't' &&
-                               STRING_CHAR(2) == 't' && STRING_CHAR(3) == 'p')
-                       {
-                               flags |= HAS_HTTP_SCHEME;
-                       }
-                       // optimization for file urls
-                       if (idx == 4 && STRING_CHAR(0) == 'f' && STRING_CHAR(1) == 'i' &&
-                               STRING_CHAR(2) == 'l' && STRING_CHAR(3) == 'e')
-                       {
-                               flags |= HAS_FILE_SCHEME;
-                       }
+            base_idx = idx + 1;
+            // optimization for http urls
+            if (idx == 4 && STRING_CHAR(0) == 'h' && STRING_CHAR(1) == 't' && STRING_CHAR(2) == 't' && STRING_CHAR(3) == 'p') {
+               flags |= HAS_HTTP_SCHEME;
+            }
+            // optimization for file urls
+            if (idx == 4 && STRING_CHAR(0) == 'f' && STRING_CHAR(1) == 'i' && STRING_CHAR(2) == 'l' && STRING_CHAR(3) == 'e') {
+                flags |= HAS_FILE_SCHEME;
+            }
             break;
         } else if (!scheme_valid(ch)) {
             break;     // invalid scheme character -- no scheme
@@ -1310,9 +1422,19 @@ static void _parseComponents(CFAllocatorRef alloc, CFStringRef string, CFURLRef
                     break;
                 }
             }
+#if DEPLOYMENT_TARGET_MACOSX
+           if (pathRg.length > 6 && STRING_CHAR(pathRg.location) == '/' && STRING_CHAR(pathRg.location + 1) == '.' && STRING_CHAR(pathRg.location + 2) == 'f' && STRING_CHAR(pathRg.location + 3) == 'i' && STRING_CHAR(pathRg.location + 4) == 'l' && STRING_CHAR(pathRg.location + 5) == 'e' && STRING_CHAR(pathRg.location + 6) == '/') {
+               flags |= PATH_HAS_FILE_ID;
+           } else if (!sawPercent) {
+                flags |= POSIX_AND_URL_PATHS_MATCH;
+            }
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
             if (!sawPercent) {
                 flags |= POSIX_AND_URL_PATHS_MATCH;
             }
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 
             ch = STRING_CHAR(pathRg.location + pathRg.length - 1);
             if (ch == '/') {
@@ -1515,8 +1637,7 @@ CF_EXPORT CFURLRef _CFURLAlloc(CFAllocatorRef allocator) {
 
 // It is the caller's responsibility to guarantee that if URLString is absolute, base is NULL.  This is necessary to avoid duplicate processing for file system URLs, which had to decide whether to compute the cwd for the base; we don't want to duplicate that work.  This ALSO means it's the caller's responsibility to set the IS_ABSOLUTE bit, since we may have a degenerate URL whose string is relative, but lacks a base.
 static void _CFURLInit(struct __CFURL *url, CFStringRef URLString, UInt32 fsType, CFURLRef base) {
-    CFAssert1(URLString != NULL && CFGetTypeID(URLString) == CFStringGetTypeID() && CFStringGetLength(URLString) != 0, __kCFLogAssertion, "%s(): internal CF error; empty string encountered", __PRETTY_FUNCTION__);
-    CFAssert2((fsType == FULL_URL_REPRESENTATION) || (fsType == kCFURLPOSIXPathStyle) || (fsType == kCFURLWindowsPathStyle) || (fsType == kCFURLHFSPathStyle), __kCFLogAssertion, "%s(): Received bad fsType %d", __PRETTY_FUNCTION__, fsType);
+    CFAssert2((fsType == FULL_URL_REPRESENTATION) || (fsType == kCFURLPOSIXPathStyle) || (fsType == kCFURLWindowsPathStyle) || (fsType == kCFURLHFSPathStyle) || ASSERT_CHECK_PATHSTYLE(fsType), __kCFLogAssertion, "%s(): Received bad fsType %d", __PRETTY_FUNCTION__, fsType);
     
     // Coming in, the url has its allocator flag properly set, and its base initialized, and nothing else.    
     url->_string = (CFStringRef)CFStringCreateCopy(CFGetAllocator(url), URLString);
@@ -1533,7 +1654,7 @@ static void _CFURLInit(struct __CFURL *url, CFStringRef URLString, UInt32 fsType
        #endif
 }
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 CF_EXPORT void _CFURLInitFSPath(CFURLRef url, CFStringRef path) {
     CFIndex len = CFStringGetLength(path);
     if (len && CFStringGetCharacterAtIndex(path, 0) == '/') {
@@ -1548,32 +1669,17 @@ CF_EXPORT void _CFURLInitFSPath(CFURLRef url, CFStringRef path) {
     if (!len || '/' == CFStringGetCharacterAtIndex(path, len - 1))
         ((struct __CFURL *)url)->_flags |= IS_DIRECTORY;
 }
-#elif 0
-CF_EXPORT void _CFURLInitFSPath(CFURLRef url, CFStringRef path) {
-    CFIndex len = CFStringGetLength(path);
-    if (len > 2) {
-        char firstChar = CFStringGetCharacterAtIndex(path, 0);
-        char secondChar = CFStringGetCharacterAtIndex(path, 1);
-        if (((((firstChar >= 'A') && (firstChar <= 'Z')) || ((firstChar >= 'a') && (firstChar <= 'z'))) &&
-            ((secondChar == ':') || (secondChar == '|'))) ||
-        ((firstChar == '\\') && (secondChar == '\\')))
-        {
-            _CFURLInit((struct __CFURL *)url, path, kCFURLWindowsPathStyle, NULL);
-            ((struct __CFURL *)url)->_flags |= IS_ABSOLUTE;
-        } else {
-            CFURLRef cwdURL = _CFURLCreateCurrentDirectoryURL(CFGetAllocator(url));
-            _CFURLInit((struct __CFURL *)url, path, kCFURLPOSIXPathStyle, cwdURL);
-            if ( cwdURL )
-                CFRelease(cwdURL);
-        }
-    }
-    if (!len || '/' == CFStringGetCharacterAtIndex(path, len - 1))
-        ((struct __CFURL *)url)->_flags |= IS_DIRECTORY;
-}
-#elif 0
+#elif DEPLOYMENT_TARGET_WINDOWS
 CF_EXPORT void _CFURLInitFSPath(CFURLRef url, CFStringRef path) {
     CFIndex len = CFStringGetLength(path);
-    if (len && CFStringGetCharacterAtIndex(path, 0) == '/') {
+    UniChar firstChar = 0 < len ? CFStringGetCharacterAtIndex(path, 0) : 0;
+    UniChar secondChar = 1 < len ? CFStringGetCharacterAtIndex(path, 1) : 0;
+    Boolean isDrive = ('A' <= firstChar && firstChar <= 'Z') || ('a' <= firstChar && firstChar <= 'z');
+    isDrive = isDrive && (secondChar == ':' || secondChar == '|');
+    if (isDrive || (firstChar == '\\' && secondChar == '\\')) {
+        _CFURLInit((struct __CFURL *)url, path, kCFURLWindowsPathStyle, NULL);
+        ((struct __CFURL *)url)->_flags |= IS_ABSOLUTE;
+    } else if (firstChar == '/') {
         _CFURLInit((struct __CFURL *)url, path, kCFURLPOSIXPathStyle, NULL);
         ((struct __CFURL *)url)->_flags |= IS_ABSOLUTE;
     } else {
@@ -1783,6 +1889,11 @@ CFURLRef CFURLCreateWithBytes(CFAllocatorRef allocator, const uint8_t *URLBytes,
         _CFURLInitWithString(result, urlString, baseURL);
         if (encoding != kCFStringEncodingUTF8 && !createOldUTF8StyleURLs()) {
             ((struct __CFURL *)result)->_encoding = encoding;
+       #if DEBUG_URL_MEMORY_USAGE
+           if ( encoding != kCFStringEncodingUTF8 ) {
+               numNonUTF8EncodedURLs++;
+           }
+       #endif
         }
     }
     CFRelease(urlString); // it's retained by result, now.
@@ -1836,8 +1947,13 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela
         CFURLRef url = _CFURLCreateWithArbitraryString(alloc, relativeString, baseURL);
         CFRelease(relativeString);
         if (url) {
-                       ((struct __CFURL *)url)->_encoding = encoding;
+           ((struct __CFURL *)url)->_encoding = encoding;
             CFURLRef absURL = CFURLCopyAbsoluteURL(url);
+       #if DEBUG_URL_MEMORY_USAGE
+           if ( encoding != kCFStringEncodingUTF8 ) {
+               numNonUTF8EncodedURLs++;
+           }
+       #endif
             CFRelease(url);
             return absURL;
         } else {
@@ -1939,6 +2055,11 @@ CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *rela
         CFRelease(absString);
         if (absURL) {
             ((struct __CFURL *)absURL)->_encoding = encoding;
+       #if DEBUG_URL_MEMORY_USAGE
+           if ( encoding != kCFStringEncodingUTF8 ) {
+               numNonUTF8EncodedURLs++;
+           }
+       #endif
         }
         return absURL;
     }
@@ -2218,6 +2339,11 @@ CFURLRef CFURLCopyAbsoluteURL(CFURLRef  relativeURL) {
     anURL = _CFURLCreateWithArbitraryString(alloc, newString, NULL);
     CFRelease(newString);
     ((struct __CFURL *)anURL)->_encoding = relativeURL->_encoding;
+#if DEBUG_URL_MEMORY_USAGE
+    if ( relativeURL->_encoding != kCFStringEncodingUTF8 ) {
+       numNonUTF8EncodedURLs++;
+    }
+#endif
     return anURL;
 }
 
@@ -3022,6 +3148,13 @@ static CFStringRef schemeSpecificString(CFURLRef url) {
         } else {
             return POSIXPathToURLPath(url->_string, CFGetAllocator(url), isDir);
         }
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    case kCFURLHFSPathStyle:
+        return HFSPathToURLPath(url->_string, CFGetAllocator(url), isDir);
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
     case kCFURLWindowsPathStyle:
         return WindowsPathToURLPath(url->_string, CFGetAllocator(url), isDir);
     case FULL_URL_REPRESENTATION:
@@ -3114,6 +3247,14 @@ static Boolean decomposeToRFC1808(CFURLRef url, CFURLComponentsRFC1808 *componen
             CFRelease(pathStr);
             break;
         }
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+       case kCFURLHFSPathStyle:
+            components->pathComponents = HFSPathToURLComponents(url->_string, alloc, ((url->_flags & IS_DIRECTORY) != 0));
+            break;
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
         case kCFURLWindowsPathStyle:
             components->pathComponents = WindowsPathToURLComponents(url->_string, alloc, ((url->_flags & IS_DIRECTORY) != 0));
             break;
@@ -3168,7 +3309,7 @@ static CFURLRef composeFromRFC1808(CFAllocatorRef alloc, const CFURLComponentsRF
         hadPrePathComponent = true;
     }
 
-    if (hadPrePathComponent && (comp->pathComponents == NULL || CFStringGetLength((CFStringRef)CFArrayGetValueAtIndex(comp->pathComponents, 0)) != 0)) {
+    if (hadPrePathComponent && (comp->pathComponents == NULL || CFArrayGetCount( comp->pathComponents ) == 0 || CFStringGetLength((CFStringRef)CFArrayGetValueAtIndex(comp->pathComponents, 0)) != 0)) {
         CFStringAppend(urlString, CFSTR("/"));
     }
     if (comp->pathComponents) {
@@ -3312,9 +3453,16 @@ CF_EXPORT void *__CFURLReservedPtr(CFURLRef  url) {
 }
 
 CF_EXPORT void __CFURLSetReservedPtr(CFURLRef  url, void *ptr) {
-       _setReserved ( (struct __CFURL*) url, ptr );
+    _setReserved ( (struct __CFURL*) url, ptr );
 }
 
+CF_EXPORT void *__CFURLResourceInfoPtr(CFURLRef url) {
+    return _getResourceInfo(url);
+}
+
+CF_EXPORT void __CFURLSetResourceInfoPtr(CFURLRef url, void *ptr) {
+    _setResourceInfo ( (struct __CFURL*) url, ptr );
+}
 
 /* File system stuff */
 
@@ -3416,16 +3564,18 @@ static CFStringRef URLPathToWindowsPath(CFStringRef path, CFAllocatorRef allocat
         UniChar ch;
 
        {
-            if (CFStringGetLength(firstComponent) == 2 && ((ch = CFStringGetCharacterAtIndex(firstComponent, 1)) == '|' || ch == ':')) {
-                // Drive letter
-                CFArrayRemoveValueAtIndex(components, 0);
-                if (ch == '|') {
-                    CFStringRef driveStr = CFStringCreateWithFormat(allocator, NULL, CFSTR("%c:"), CFStringGetCharacterAtIndex(firstComponent, 0));
-                    CFArraySetValueAtIndex(components, 0, driveStr);
-                    CFRelease(driveStr);
-                }
-            }
-            CFRelease(firstComponent);
+            if (firstComponent) {
+               if (CFStringGetLength(firstComponent) == 2 && ((ch = CFStringGetCharacterAtIndex(firstComponent, 1)) == '|' || ch == ':')) {
+                   // Drive letter
+                   CFArrayRemoveValueAtIndex(components, 0);
+                   if (ch == '|') {
+                       CFStringRef driveStr = CFStringCreateWithFormat(allocator, NULL, CFSTR("%c:"), CFStringGetCharacterAtIndex(firstComponent, 0));
+                       CFArraySetValueAtIndex(components, 0, driveStr);
+                       CFRelease(driveStr);
+                   }
+               }
+               CFRelease(firstComponent);
+           }
         }
     }
     newPath = CFStringCreateByCombiningStrings(allocator, components, CFSTR("\\"));
@@ -3435,12 +3585,15 @@ static CFStringRef URLPathToWindowsPath(CFStringRef path, CFAllocatorRef allocat
     return result;
 }
 
+
+
 // converts url from a file system path representation to a standard representation
 static void _convertToURLRepresentation(struct __CFURL *url) {
     CFStringRef path = NULL;
     Boolean isDir = ((url->_flags & IS_DIRECTORY) != 0);
+    Boolean isFileReferencePath = false;
     CFAllocatorRef alloc = CFGetAllocator(url);
-
+    
 #if DEBUG_URL_MEMORY_USAGE
     numFileURLsConverted ++;
 #endif
@@ -3460,15 +3613,15 @@ static void _convertToURLRepresentation(struct __CFURL *url) {
     CFAssert2(path != NULL, __kCFLogAssertion, "%s(): Encountered malformed file system URL %@", __PRETTY_FUNCTION__, url);
     if (!url->_base) {
        CFMutableStringRef str = CFStringCreateMutable(alloc, 0);
-       CFStringAppend(str, CFSTR("file://localhost"));
+       CFStringAppend(str, isFileReferencePath ? CFSTR("file://") : CFSTR("file://localhost"));
        CFStringAppend(str, path);
-        url->_flags = (url->_flags & (IS_DIRECTORY)) | (FULL_URL_REPRESENTATION << 16) | IS_DECOMPOSABLE | IS_ABSOLUTE | IS_PARSED | HAS_SCHEME | HAS_FILE_SCHEME | HAS_HOST | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH;
+        url->_flags = (url->_flags & (IS_DIRECTORY)) | (FULL_URL_REPRESENTATION << 16) | IS_DECOMPOSABLE | IS_ABSOLUTE | IS_PARSED | HAS_SCHEME | HAS_FILE_SCHEME | HAS_HOST | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH | ( isFileReferencePath ? PATH_HAS_FILE_ID : 0 );
         CFRelease(url->_string);
         url->_string = str;
         url->ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange) * 3, 0);
         url->ranges[0] = CFRangeMake(0, 4);
-        url->ranges[1] = CFRangeMake(7, 9);
-        url->ranges[2] = CFRangeMake(16, CFStringGetLength(path));
+        url->ranges[1] = CFRangeMake(7, isFileReferencePath ? 0 : 9);
+        url->ranges[2] = CFRangeMake(url->ranges[1].location + url->ranges[1].length, CFStringGetLength(path));
         CFRelease(path);
     } else {
         CFRelease(url->_string);
@@ -3532,7 +3685,8 @@ CFURLRef CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef fil
     CFIndex len;
     CFURLRef baseURL, result;
 
-    CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType);
+    CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle || ASSERT_CHECK_PATHSTYLE(fsType), __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType);
+    
     CFAssert1(filePath != NULL, __kCFLogAssertion, "%s(): NULL filePath argument not permitted", __PRETTY_FUNCTION__);
 
        len = CFStringGetLength(filePath);
@@ -3569,7 +3723,7 @@ CF_EXPORT CFURLRef CFURLCreateWithFileSystemPathRelativeToBase(CFAllocatorRef al
     CFIndex len;
 
     CFAssert1(filePath != NULL, __kCFLogAssertion, "%s(): NULL path string not permitted", __PRETTY_FUNCTION__);
-    CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType);
+    CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle || ASSERT_CHECK_PATHSTYLE(fsType), __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType);
     
        len = CFStringGetLength(filePath);
 
@@ -3701,11 +3855,29 @@ CF_EXPORT CFURLRef CFURLCreateWithFileSystemPathRelativeToBase(CFAllocatorRef al
     return url;
 }
 
+static Boolean _pathHasFileIDPrefix( CFStringRef path )
+{
+    // path is not NULL, path has prefix "/.file/" and has at least one character following the prefix.
+    static const CFStringRef fileIDPrefix = CFSTR( "/" FILE_ID_PREFIX "/" );
+    return path && CFStringHasPrefix( path, fileIDPrefix ) && CFStringGetLength( path ) > CFStringGetLength( fileIDPrefix );
+}
+
+
+static Boolean _pathHasFileIDOnly( CFStringRef path )
+{
+    // Is file ID rooted and contains no additonal path segments
+    CFRange slashRange;
+    return _pathHasFileIDPrefix( path ) && ( !CFStringFindWithOptions( path, CFSTR("/"), CFRangeMake( sizeof(FILE_ID_PREFIX) + 1, CFStringGetLength( path ) - sizeof(FILE_ID_PREFIX) - 1), 0, &slashRange ) || slashRange.location == CFStringGetLength( path ) - 1 );
+}
+
+
 CF_EXPORT CFStringRef CFURLCopyFileSystemPath(CFURLRef anURL, CFURLPathStyle pathStyle) {
-    CFAssert2(pathStyle == kCFURLPOSIXPathStyle || pathStyle == kCFURLHFSPathStyle || pathStyle == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): Encountered unknown path style %d", __PRETTY_FUNCTION__, pathStyle);
+    CFAssert2(pathStyle == kCFURLPOSIXPathStyle || pathStyle == kCFURLHFSPathStyle || pathStyle == kCFURLWindowsPathStyle || ASSERT_CHECK_PATHSTYLE(pathStyle), __kCFLogAssertion, "%s(): Encountered unknown path style %d", __PRETTY_FUNCTION__, pathStyle);
+    
     return CFURLCreateStringWithFileSystemPath(CFGetAllocator(anURL), anURL, pathStyle, false);
 }
 
+
 // There is no matching ObjC method for this functionality; because this function sits on top of the CFURL primitives, it's o.k. not to check for the need to dispatch an ObjC method instead, but this means care must be taken that this function never call anything that will result in dereferencing anURL without first checking for an ObjC dispatch.  -- REW, 10/29/98
 CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLRef anURL, CFURLPathStyle fsType, Boolean resolveAgainstBase) {
     CFURLRef base = resolveAgainstBase ? CFURLGetBaseURL(anURL) : NULL;
@@ -3774,23 +3946,64 @@ Boolean CFURLGetFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBas
     CFAllocatorRef alloc = CFGetAllocator(url);
 
     if (!url) return false;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     path = CFURLCreateStringWithFileSystemPath(alloc, url, kCFURLPOSIXPathStyle, resolveAgainstBase);
     if (path) {
         Boolean convResult = _CFStringGetFileSystemRepresentation(path, buffer, bufLen);
         CFRelease(path);
         return convResult;
     }
+#elif DEPLOYMENT_TARGET_WINDOWS
+    path = CFURLCreateStringWithFileSystemPath(alloc, url, kCFURLWindowsPathStyle, resolveAgainstBase);
+    if (path) {
+        CFIndex usedLen;
+        CFIndex pathLen = CFStringGetLength(path);
+        CFIndex numConverted = CFStringGetBytes(path, CFRangeMake(0, pathLen), CFStringFileSystemEncoding(), 0, true, buffer, bufLen-1, &usedLen); // -1 because we need one byte to zero-terminate.
+        CFRelease(path);
+        if (numConverted == pathLen) {
+            buffer[usedLen] = '\0';
+            return true;
+        }
+    }
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     return false;
 }
 
+#if DEPLOYMENT_TARGET_WINDOWS
+CF_EXPORT Boolean _CFURLGetWideFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBase, wchar_t *buffer, CFIndex bufferLength) {
+       CFStringRef path = CFURLCreateStringWithFileSystemPath(CFGetAllocator(url), url, kCFURLWindowsPathStyle, resolveAgainstBase);
+       CFIndex pathLength, charsConverted, usedBufLen;
+       if (!path) return false;
+       pathLength = CFStringGetLength(path);
+       if (pathLength+1 > bufferLength) {
+               CFRelease(path);
+               return false;
+       }
+       charsConverted = CFStringGetBytes(path, CFRangeMake(0, pathLength), kCFStringEncodingUTF16, 0, false, (UInt8 *)buffer, bufferLength*sizeof(wchar_t), &usedBufLen);
+//     CFStringGetCharacters(path, CFRangeMake(0, pathLength), (UniChar *)buffer);
+       CFRelease(path);
+       if (charsConverted != pathLength || usedBufLen%sizeof(wchar_t) != 0) {
+               return false;
+       } else {
+               buffer[usedBufLen/sizeof(wchar_t)] = 0;
+//             buffer[pathLength] = 0;
+               return true;
+       }
+}
+#endif
+
 CFURLRef CFURLCreateFromFileSystemRepresentation(CFAllocatorRef allocator, const uint8_t *buffer, CFIndex bufLen, Boolean isDirectory) {
     CFStringRef path = CFStringCreateWithBytes(allocator, buffer, bufLen, CFStringFileSystemEncoding(), false);
     CFURLRef newURL;
     if (!path) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     newURL = CFURLCreateWithFileSystemPath(allocator, path, kCFURLPOSIXPathStyle, isDirectory);
+#elif DEPLOYMENT_TARGET_WINDOWS
+    newURL = CFURLCreateWithFileSystemPath(allocator, path, kCFURLWindowsPathStyle, isDirectory);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     CFRelease(path);
     return newURL;
@@ -3800,8 +4013,12 @@ CF_EXPORT CFURLRef CFURLCreateFromFileSystemRepresentationRelativeToBase(CFAlloc
     CFStringRef path = CFStringCreateWithBytes(allocator, buffer, bufLen, CFStringFileSystemEncoding(), false);
     CFURLRef newURL;
     if (!path) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     newURL = CFURLCreateWithFileSystemPathRelativeToBase(allocator, path, kCFURLPOSIXPathStyle, isDirectory, baseURL);
+#elif DEPLOYMENT_TARGET_WINDOWS
+    newURL = CFURLCreateWithFileSystemPathRelativeToBase(allocator, path, kCFURLWindowsPathStyle, isDirectory, baseURL);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     CFRelease(path);
     return newURL;
@@ -3853,11 +4070,18 @@ CFStringRef CFURLCopyLastPathComponent(CFURLRef url) {
         CFRange rg, compRg;
         if (!path) return NULL;
         rg = CFRangeMake(0, CFStringGetLength(path));
+       if ( rg.length == 0 ) return path;
         length = rg.length; // Remember this for comparison later
-        if (CFStringGetCharacterAtIndex(path, rg.length - 1) == '/') {
+        if (CFStringGetCharacterAtIndex(path, rg.length - 1) == '/' ) {
             rg.length --;
         }
-        if (CFStringFindWithOptions(path, CFSTR("/"), rg, kCFCompareBackwards, &compRg)) {
+       if ( rg.length == 0 )
+       {
+           //  If we have reduced the string to empty, then it's "/", and that's what we return as
+           //  the last path component.
+          return path;
+       }
+        else if (CFStringFindWithOptions(path, CFSTR("/"), rg, kCFCompareBackwards, &compRg)) {
             rg.length = rg.location + rg.length - (compRg.location+1);
             rg.location = compRg.location + 1;
         }
@@ -4095,6 +4319,86 @@ CFURLRef CFURLCreateCopyDeletingPathExtension(CFAllocatorRef allocator, CFURLRef
 }
 
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+static CFArrayRef HFSPathToURLComponents(CFStringRef path, CFAllocatorRef alloc, Boolean isDir) {
+    CFArrayRef components = CFStringCreateArrayBySeparatingStrings(alloc, path, CFSTR(":"));
+    CFMutableArrayRef newComponents = CFArrayCreateMutableCopy(alloc, 0, components);
+    Boolean doSpecialLeadingColon = false;
+    UniChar firstChar = CFStringGetCharacterAtIndex(path, 0);
+    UInt32 i, cnt;
+    CFRelease(components);
+
+
+    if (!doSpecialLeadingColon && firstChar != ':') {
+        CFArrayInsertValueAtIndex(newComponents, 0, CFSTR(""));
+    } else if (firstChar != ':') {
+        // see what we need to add at the beginning. Under MacOS, if the
+        // first character isn't a ':', then the first component is the
+        // volume name, and we need to find the mount point.  Bleah. If we
+        // don't find a mount point, we're going to have to lie, and make something up.
+        CFStringRef firstComp = (CFStringRef)CFArrayGetValueAtIndex(newComponents, 0);
+        if (CFStringGetLength(firstComp) == 1 && CFStringGetCharacterAtIndex(firstComp, 0) == '/') {
+            // "/" is the "magic" path for a UFS root directory
+            CFArrayRemoveValueAtIndex(newComponents, 0);
+            CFArrayInsertValueAtIndex(newComponents, 0, CFSTR(""));
+        } else {
+            // See if we can get a mount point.
+            Boolean foundMountPoint = false;
+            if (!foundMountPoint) {
+                // Fall back to treating the volume name as the top level directory
+                CFArrayInsertValueAtIndex(newComponents, 0, CFSTR(""));
+            }
+        }
+    } else {
+        CFArrayRemoveValueAtIndex(newComponents, 0);
+    }
+
+    cnt = CFArrayGetCount(newComponents);
+    for (i = 0; i < cnt; i ++) {
+        CFStringRef comp = (CFStringRef)CFArrayGetValueAtIndex(newComponents, i);
+        CFStringRef newComp = NULL;
+        CFRange searchRg, slashRg;
+        searchRg.location = 0;
+        searchRg.length = CFStringGetLength(comp);
+        while (CFStringFindWithOptions(comp, CFSTR("/"), searchRg, 0, &slashRg)) {
+            if (!newComp) {
+                newComp = CFStringCreateMutableCopy(alloc, searchRg.location + searchRg.length, comp);
+            }
+            CFStringReplace((CFMutableStringRef)newComp, slashRg, CFSTR(":"));
+            searchRg.length = searchRg.location + searchRg.length - slashRg.location - 1;
+            searchRg.location = slashRg.location + 1;
+        }
+        if (newComp) {
+            CFArraySetValueAtIndex(newComponents, i, newComp);
+            CFRelease(newComp);
+        }
+    }
+    if (isDir && CFStringGetLength((CFStringRef)CFArrayGetValueAtIndex(newComponents, cnt-1)) != 0) {
+            CFArrayAppendValue(newComponents, CFSTR(""));
+    }
+    return newComponents;
+}
+static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir) {
+    CFArrayRef components = HFSPathToURLComponents(path, alloc, isDir);
+    CFArrayRef newComponents = components ? copyStringArrayWithTransformation(components, escapePathComponent) : NULL;
+    CFIndex cnt;
+    CFStringRef result;
+    if (components) CFRelease(components);
+    if (!newComponents) return NULL;
+
+    cnt = CFArrayGetCount(newComponents);
+    if (cnt == 1 && CFStringGetLength((CFStringRef)CFArrayGetValueAtIndex(newComponents, 0)) == 0) {
+        result = (CFStringRef)CFRetain(CFSTR("/"));
+    } else {
+        result = CFStringCreateByCombiningStrings(alloc, newComponents, CFSTR("/"));
+    }
+    CFRelease(newComponents);
+    return result;
+}
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 
 
 
@@ -4213,4 +4517,3 @@ CFURLRef _CFURLCreateFromPropertyListRepresentation(CFAllocatorRef alloc, CFProp
     return url;
 }
 
-
diff --git a/CFURL.h b/CFURL.h
index 0f1d29457fce12ff567e6734e7307157fc822629..31ecc4411003be42577e29970ac23439698ad0fb 100644 (file)
--- a/CFURL.h
+++ b/CFURL.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFURL.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFURL__)
@@ -29,6 +29,7 @@
 
 #include <CoreFoundation/CFBase.h>
 #include <CoreFoundation/CFData.h>
+#include <CoreFoundation/CFError.h>
 #include <CoreFoundation/CFString.h>
 
 CF_EXTERN_C_BEGIN
@@ -104,6 +105,12 @@ CFURLRef CFURLCreateWithFileSystemPath(CFAllocatorRef allocator, CFStringRef fil
 CF_EXPORT
 CFURLRef CFURLCreateFromFileSystemRepresentation(CFAllocatorRef allocator, const UInt8 *buffer, CFIndex bufLen, Boolean isDirectory);
 
+/* The path style of the baseURL must match the path style of the relative */
+/* url or the results are undefined.  If the provided filePath looks like an */
+/* absolute path ( starting with '/' if pathStyle is kCFURLPosixPathStyle, */
+/* not starting with ':' for kCFURLHFSPathStyle, or starting with what looks */
+/* like a drive letter and colon for kCFURLWindowsPathStyle ) then the baseURL */
+/* is ignored. */
 CF_EXPORT
 CFURLRef CFURLCreateWithFileSystemPathRelativeToBase(CFAllocatorRef allocator, CFStringRef filePath, CFURLPathStyle pathStyle, Boolean isDirectory, CFURLRef baseURL); 
 
@@ -409,6 +416,392 @@ CF_EXPORT
 CFStringRef CFURLCreateStringByAddingPercentEscapes(CFAllocatorRef allocator, CFStringRef originalString, CFStringRef charactersToLeaveUnescaped, CFStringRef legalURLCharactersToBeEscaped, CFStringEncoding encoding);
 
 
+/* Returns a file reference URL, a path-idependent form of file URL. */
+/* Converts a file path URL if necessary. For non-file URLs, returns NULL. */
+/* Also returns NULL when the conversion fails because the target resource doesn't exist. */
+/* Optional output error: The error is set to a valid CFErrorRef when the function */
+/* result is NULL. A valid output error must be released by the caller. */
+CF_EXPORT
+CFURLRef CFURLCreateFileReferenceURL(CFAllocatorRef allocator, CFURLRef url, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Returns a file path URL, converting a file reference URL if necessary. */
+/* For non-file URLs, returns NULL. Also returns NULL when the conversion fails */
+/* because the target resource doesn't exist. */
+/* Optional output error: The error is set to a valid CFErrorRef when the function */
+/* result is NULL. A valid output error must be released by the caller. */
+CF_EXPORT
+CFURLRef CFURLCreateFilePathURL(CFAllocatorRef allocator, CFURLRef url, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+
+
+#if TARGET_OS_MAC
+
+/* The following APIs provide efficient access to resource properties. Properties 
+are identified by keys, and values are represented as Core Foundation objects. The 
+type of each value is fixed for each property, e.g. the modification date is a CFDateRef, 
+the file size is a CFNumberRef.
+
+Values are fetched on-demand, synchronously, from the resource's backing store. They
+are cached and reused when fetched again through the same URL instance, until the 
+client clears the value. The client has complete control over the cache lifetime.
+
+Some resource property values can be changed, given sufficient access permission to the resource. 
+When a resource property value is set, the change is written to backing store synchronously.
+*/
+
+/* Assigns the requested resource property value to the typeRefValuePtr output */
+/* argument. Returns true if the output value was set. Note that NULL is a valid output value. */
+/* The value is fetched synchronously from the resource backing store only if a value is not */
+/* already cached. The type of the output value type varies by property (see property key */
+/* definitions). Returns false if an error occurs. Optional output error: the error is set to */
+/* a valid CFErrorRef when the function returns false. A valid output error must be */
+/* released by the caller. */
+CF_EXPORT
+Boolean CFURLCopyResourcePropertyForKey(CFURLRef url, CFStringRef key, void *propertyValueTypeRefPtr, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Returns any number of resource property values as a dictionary of keyed values. */
+/* The requested values are specified as an array of keys to appear in */
+/* the result dictionary. Values are fetched synchronously from the resource backing store unless */
+/* already cached. The type of each value type varies (see key definitions, below). */
+/* Returns an empty dictionary if no values are found. Returns NULL when an error occurs. */
+/* Optional output error: the error is set to a valid CFErrorRef when the */
+/* function returns NULL. A valid output error must be released by the caller. */
+CF_EXPORT
+CFDictionaryRef CFURLCopyResourcePropertiesForKeys(CFURLRef url, CFArrayRef keys, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Changes a resource property value. Synchronously writes the value to the resource backing */
+/* store. The input value type must be a valid CFTypeRef, of the type required for the specified */
+/* key (see key definitions). Returns true upon success, false when an error occurs. */
+/* Optional output error: the error is set to a valid CFErrorRef when the function */
+/* returns false. A valid output error must be released by the caller. */
+/* Note that some values are read-only. Attempting to set a read-only property */
+/* results in an error. */
+CF_EXPORT
+Boolean CFURLSetResourcePropertyForKey(CFURLRef url, CFStringRef key, CFTypeRef propertValue, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Changes any number of resource property values, specified as a dictionary of keyed values. */
+/* Synchronously writes values to the resource backing store. The input dictionary's value types must conform */
+/* to the type required for its key (see key definitions). Returns true when all values are set successfully, */
+/* and false if an error occurs. Optional output error: the error is set to a valid CFErrorRef when the function returns */
+/* false. A valid output error must be released by the caller. When an error occurs after some properties have been */
+/* successfully changed, the user dictionary in the error contains an array of keys that */
+/* were not set. Note that some values are read-only. Attempting to set a read-only value */
+/* results in an error. */
+CF_EXPORT
+Boolean CFURLSetResourcePropertiesForKeys(CFURLRef url, CFDictionaryRef keyedPropertyValues, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Discards a cached property value for a specific key */
+CF_EXPORT
+void CFURLClearResourcePropertyCacheForKey(CFURLRef url, CFStringRef key) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Discards all cached property values */
+CF_EXPORT
+void CFURLClearResourcePropertyCache(CFURLRef url) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Sets a temporary property value. Temporary properties exist only in memory and are never */
+/* written to resource backing store. Once set, a temporary property value can be fetched */
+/* with CFURLCopyResourcePropertyForKey and CFURLCopyResourcePropertiesForKeys. Temporary property */
+/* values are for client use. Values must be valid Core Foundation types, and will be retained. */
+/* To remove a temporary property value, use CFURLClearResourcePropertyCacheForKey. */
+CF_EXPORT
+void CFURLSetTemporaryResourcePropertyForKey(CFURLRef url, CFStringRef key, CFTypeRef propertyValue) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Synchronously checks if the resource's backing store is reachable and the resource exists, */
+/* returning true if so. The optional output error can be used to determine the type of reachability */
+/* failure (e.g., file not found, network error, etc.). The error is set to a valid CFErrorRef if */
+/* and only if the function returns false. A valid output error must be released by */
+/* the caller. Checking for resource existence and reachability is appropriate when making decisions */
+/* that do not require other immediate operations on the resource. An example would be */
+/* periodic maintenance of UI state that depends on the existence of a particular document. */
+/* When performing an operation such as opening a file, it is more efficient to */
+/* simply try the operation and handle failures than to check first for reachability. */
+CF_EXPORT
+Boolean CFURLResourceIsReachable(CFURLRef url, CFErrorRef *error) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+
+/* Properties of File System Resources */
+
+CF_EXPORT 
+const CFStringRef kCFURLNameKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* The resource name provided by the file system (value type CFString) */
+
+CF_EXPORT
+const CFStringRef kCFURLLocalizedNameKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Localized or extension-hidden name as displayed to users (Read-only, value type CFString) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsRegularFileKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for regular files (Read-only, value type CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsDirectoryKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for directories (Read-only, CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsSymbolicLinkKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for symlinks (Read-only, value type CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsVolumeKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for the root directory of a volume (Read-only, value type CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsPackageKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for packaged directories (value type CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsSystemImmutableKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for system-immutable resources (value type CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsUserImmutableKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for user-immutable resources (value type CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsHiddenKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for resources normally hidden from users (value type CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLHasHiddenExtensionKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* True for resources whose filename extension is hiden (value type CFBoolean) */
+
+CF_EXPORT
+const CFStringRef kCFURLCreationDateKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Value type CFDate */
+
+CF_EXPORT
+const CFStringRef kCFURLContentAccessDateKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Value type CFDate */
+
+CF_EXPORT
+const CFStringRef kCFURLContentModificationDateKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Value type CFDate */
+
+CF_EXPORT
+const CFStringRef kCFURLAttributeModificationDateKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Value type CFDate */
+
+CF_EXPORT
+const CFStringRef kCFURLLinkCountKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Number of hard links to the resource (Read-only, CFNumber) */
+
+CF_EXPORT
+const CFStringRef kCFURLParentDirectoryURLKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* URL of the parent directory, if any (Read-only, value type CFURL) */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeURLKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* URL of the volume on which the resource is stored (Read-only, value type CFURL) */
+
+CF_EXPORT
+const CFStringRef kCFURLTypeIdentifierKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Uniform type identifier for the resource (Read-only, value type CFString) */
+
+CF_EXPORT
+const CFStringRef kCFURLLocalizedTypeDescriptionKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* User-visible type or "kind" descriptiopn (Read-only, value type CFString) */
+
+CF_EXPORT
+const CFStringRef kCFURLLabelNumberKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* The label number assigned to the resource (value type CFNumber) */
+
+CF_EXPORT
+const CFStringRef kCFURLLabelColorKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* The color of the assigned label (Read-only, value type CGColorRef, must link with Application Services) */
+
+CF_EXPORT
+const CFStringRef kCFURLLocalizedLabelKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* The user-visible label text (Read-only, value type CFString) */
+
+CF_EXPORT
+const CFStringRef kCFURLEffectiveIconKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* The icon normally displayed for the resource (Read-only, value type CGImageRef, must link with Application Services) */
+
+CF_EXPORT
+const CFStringRef kCFURLCustomIconKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* The custom icon assigned to the resource, if any (value type CGImageRef, must link with Application Services) */
+
+
+/* File Properties */
+
+CF_EXPORT
+const CFStringRef kCFURLFileSizeKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Total file size, in bytes (Read-only, value type CFNumber) */
+
+CF_EXPORT
+const CFStringRef kCFURLFileAllocatedSizeKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Total size of blocks allocated (Read-only, value type CFNumber) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsAliasFileKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+/*  true if the url is a Finder alias file, false otherwise ( Read-only, value type CFBooleanRef) */
+
+
+/* Volume Properties */
+
+/* For convenience, volume properties may be requested from any resource on a volume. */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeLocalizedFormatDescriptionKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* The user-visible volume format (Read-only, value type CFString) */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeTotalCapacityKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Total volume capacity in bytes (Read-only, value type CFNumber) */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeAvailableCapacityKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Total free space, in bytes (Read-only, value type CFNumber) */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeResourceCountKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Total number of resources on the volume (Read-only, value type CFNumber) */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeSupportsPersistentIDsKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeSupportsSymbolicLinksKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeSupportsHardLinksKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeSupportsJournalingKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeIsJournalingKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeSupportsSparseFilesKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeSupportsZeroRunsKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeSupportsCaseSensitiveNamesKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+CF_EXPORT
+const CFStringRef kCFURLVolumeSupportsCasePreservedNamesKey AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+    /* Read-only, value type CFBoolean */
+
+enum {
+    kCFURLBookmarkCreationPreferFileIDResolutionMask = ( 1UL << 8 ),  // At resolution time, this alias will prefer resolving by the embedded fileID to the path
+    kCFURLBookmarkCreationMinimalBookmarkMask = ( 1UL << 9 ), // Creates a bookmark with "less" information, which may be smaller but still be able to resolve in certain ways
+    kCFURLBookmarkCreationSuitableForBookmarkFile = ( 1UL << 10 ), // includes in the created bookmark those properties which are needed for a bookmark/alias file
+};
+typedef CFOptionFlags CFURLBookmarkCreationOptions;
+
+enum  {
+    kCFBookmarkResolutionWithoutUIMask = ( 1UL << 8 ),         // don't perform any UI during bookmark resolution
+    kCFBookmarkResolutionWithoutMountingMask = ( 1UL << 9 ),   // don't mount a volume during bookmark resolution
+};
+typedef CFOptionFlags CFURLBookmarkResolutionOptions;
+
+typedef CFOptionFlags CFURLBookmarkFileCreationOptions;
+
+/*     @function CFURLCreateBookmarkData
+       @discussion     Create a CFDataRef containing an externalizable representation from a CFURLRef, modified with the given options, including ( at the minimum ) any
+               properties in the propertiesToInclude array which are retrievable from the given url.
+       @param  allocator               the CFAllocator to use to create this object
+       @param  url     the CFURLRef to create a bookmark data from.
+       @param  options a set of options which control creation of the bookmark data
+       @param resourcePropertiesToInclude      If non-NULL, an CFArrayRef of additional properties copied from the url to include in the created bookmark data.
+       @param relativeToURL If non-NULL, the created bookmark will be relative to the given url
+       @param error    If non-NULL, on exit will be filled in with a CFErrorRef representing any error which occured during creation of the bookmark data
+       @result A CFDataRef containing an data, which can be later be passed to CFURLCreateByResolvingBookmarkData() or to CFURLCopyPropertiesForKeysFromBookmarkData() / CFURLCopyPropertyForKeyFromBookmarkData() */
+CFDataRef CFURLCreateBookmarkData ( CFAllocatorRef allocator, CFURLRef url, CFURLBookmarkCreationOptions options, CFArrayRef resourcePropertiesToInclude, CFURLRef relativeToURL, CFErrorRef* error ) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+/*     @function CFURLCreateByResolvingBookmarkData
+       @discussion Given a CFDataRef created with CFURLCreateBookmarkRepresentation(), return a CFURLRef of the item it was a bookmark to, and
+               attempt to pre-cache those properties in propertiesToInclude in the resulting url.  If in the process of resolving the bookmark into the CFURLRef
+               it points to this determines that  some properties in the bookmark are out of date or not correct for the item it resolves to, set *isStale to YES,
+               which the client may want to use to decide to make a new bookmark from the returned item and replace the saved bookmark it has.  If the bookmarked
+               item cannot be found, return NULL.  If an error ( other than "original item can not be found" ) occurs during the process, return NULL and fill in error )
+       @param  allocator        the CFAllocator to use to create this object
+       @param   bookmark a CFDataRef containing a bookmark data, created with CFURLCreateBookmarkData
+       @param  options options which affect the resolution
+       @param relativeToURL If non-NULL, and if the bookmark was created relative to another url, then resolve it relative to this url
+       @param resourcePropertiesToInclude If non-NULL, a CFArray containing those properties which the caller would like to already be cached on the given url
+       @param isStale If non-NULL, on exit will be set to true if during resolution any of the properties in the bookmark no longer seemed to match the
+               corresponding properties on the returned file.  Clients, upon seeing a stale representation, may want to replace whatever stored bookmark data they
+               have saved and create a new one.
+       @param error    If non-NULL, on exit will be filled in with a CFErrorRef representing any error which occured during resolution of the bookmark data
+       @result A CFURLRef of a file which is the closest match to the file the bookmark data */
+CFURLRef CFURLCreateByResolvingBookmarkData ( CFAllocatorRef allocator, CFDataRef bookmark, CFURLBookmarkResolutionOptions options, CFURLRef relativeToURL, CFArrayRef resourcePropertiesToInclude, Boolean* isStale, CFErrorRef* error ) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+/*     @function       CFURLCreatePropertiesForKeysFromBookmarkData
+       @discussion     Given a bookmark, return a dictionary of properties ( all properties if propertiesToReturn == NULL ).
+                               This returns only the properties stored within the bookmark and will not attempt to resolve the bookmark or do i/o.
+       @param  allocator        the CFAllocator to use to create this object
+       @param   bookmark a CFDataRef containing a bookmark data, created with CFURLCreateBookmarkData
+       @param  propertiesToReturn a CFArrayRef of the properties of the bookmark data which the client would like returned.
+       @result a CFDictionaryRef containing the values for the properties passed in obtained from the bookmark data ( not by attempting to resolve it or do i/o in any way ) */
+CFDictionaryRef CFURLCreateResourcePropertiesForKeysFromBookmarkData ( CFAllocatorRef allocator, CFArrayRef resourcePropertiesToReturn, CFDataRef bookmark ) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+/*     @function       CFURLCreatePropertyForKeyFromBookmarkData
+       @discussion     Given a bookmark, return the value for a given property from the bookmark data
+                               This returns only the properties stored within the bookmark and will not attempt to resolve the bookmark or do i/o.
+       @param  allocator        the CFAllocator to use to create this object
+       @param   bookmark a CFDataRef containing a bookmark data, created with CFURLCreateBookmarkData
+       @param  propertyKey the property key to return.
+       @result a CFTypeRef value for the property passed in obtained from the bookmark data ( not by attempting to resolve it or do i/o in any way ) */
+CFTypeRef  CFURLCreateResourcePropertyForKeyFromBookmarkData( CFAllocatorRef allocator, CFStringRef resourcePropertyKey, CFDataRef bookmark ) AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER;
+
+/*!    @function       CFURLCreateBookmarkDataFromFile
+       @description    Given a fileURL of a file which is a Finder "alias" file, return a CFDataRef with the bookmark data from the file.  If urlRef points to an alias file
+                       created before SnowLeopard which contains Alias Manager information and no bookmark data, then a CFDataRef will be synthesized which contains
+                       a approximation of the alias information in a format which can be used to resolve the bookmark.  If an error prevents reading the data or
+                       if it is corrupt, NULL will be returned and error will be filled in if errorRef is non-NULL.
+       @param  allocator the CFAllocator to use to create this object
+       @param  fileURL a CFURLRef to to the alias file to create the bookmark data from
+       @param  errorRef    if non-NULL, on exit will be filled in with a CFErrorRef representing any error which occurred during the creation of the bookmark data from the file
+       @result A CFDataRef containing bookmark data, or NULL if there was an error creating bookmark data from the file, such as if the file is not an alias file.
+ */
+CFDataRef CFURLCreateBookmarkDataFromFile(CFAllocatorRef allocator, CFURLRef fileURL, CFErrorRef *errorRef );
+
+/*!    @function       CFURLWriteBookmarkDataToFile
+       @description    Given a created bookmarkData object, create a new Finder "alias" file at fileURL which contains the bookmark data.  If fileURL is a url to a directory, an alias file
+                       will be created with the same name as the bookmarked item and a ".alias" extension.  If fileURL is a url for a file and it exists it will be overwritten.  If a
+                       .alias extension is not present it will be added.  In addition to the bookmark data, sufficient pre-SnowLeopard alias data will added to the file to allow
+                       systems running something before SnowLeopard to resolve this file using Alias Manager routines and get back the same file as the bookmark routines.
+                       The bookmark data must have been created with the kCFURLBookmarkCreationSuitableForBookmarkFile option and an error will be returned if not.
+       @param  allocator        the CFAllocator to use to create this object
+       @param   bookmark a CFDataRef containing a bookmark data, created with CFURLCreateBookmarkData
+       @param  options options flags 
+       @param  errorRef    if non-NULL, on exit will be filled in with a CFErrorRef representing any error which occurred during the creation of the alias file
+ */
+Boolean CFURLWriteBookmarkDataToFile( CFDataRef bookmarkRef, CFURLRef fileURL, CFURLBookmarkFileCreationOptions options, CFErrorRef *errorRef );
+
+/*!    @function       CFURLCreateBookmarkDataFromAliasRecord
+       @discussion     Create a CFDataRef containing bookmarkdata by converting the alias data in aliasRecordDataRef, which should be the contents of an AliasRecord copied into a CFDataRef object.
+               The created bookmarkdata can be passed into CFURLCreateByResolvingBookmarkData() to resolve the item into a CFURLRef, or a small set of information can be returned from
+               CFURLCreateResourcePropertiesForKeysFromBookmarkData() / CFURLCreateResourcePropertyForKeyFromBookmarkData().
+               @param  allocator               the CFAllocator to use to create this object
+               @param  aliasRecordDataRef      the contents of an AliasRecord to create bookmark data for
+               @result A CFDataRef containing an data, which can be later be passed to CFURLCreateByResolvingBookmarkData() or to CFURLCopyPropertiesForKeysFromBookmarkData() / CFURLCopyPropertyForKeyFromBookmarkData()
+ */
+CFDataRef CFURLCreateBookmarkDataFromAliasRecord ( CFAllocatorRef allocatorRef, CFDataRef aliasRecordDataRef );
+
+#endif /* TARGET_OS_MAC */
+
 CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFURL__ */
index e4fe10156d8927b8e8fd92d76c69ce8f99fd3ca6..2e0cae412b4d62fe990ce72ea31e9460b86ffb48 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,8 +21,8 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFURLAccess.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
-       Responsibility: Becky Willrich
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
+       Responsibility: Chris Linn
 */
 
 /*------
@@ -37,7 +37,8 @@ CFData read/write routines
 #include <CoreFoundation/CFDate.h>
 #include <CoreFoundation/CFNumber.h>
 #include <string.h>
-#if DEPLOYMENT_TARGET_MACOSX
+#include <ctype.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <stdlib.h>
 #include <unistd.h>
 #include <dirent.h>
@@ -46,17 +47,37 @@ CFData read/write routines
 #include <pwd.h>
 #include <fcntl.h>
 #include <dlfcn.h>
+#elif DEPLOYMENT_TARGET_WINDOWS
+//#include <winsock2.h>
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+
 
-DEFINE_WEAK_CFNETWORK_FUNC(Boolean, _CFURLCreateDataAndPropertiesFromResource, (CFAllocatorRef A, CFURLRef B, CFDataRef *C, CFDictionaryRef *D, CFArrayRef E, SInt32 *F), (A, B, C, D, E, F), false)
-DEFINE_WEAK_CFNETWORK_FUNC(Boolean, _CFURLWriteDataAndPropertiesToResource, (CFURLRef A, CFDataRef B, CFDictionaryRef C, SInt32 *D), (A, B, C, D), false)
-DEFINE_WEAK_CFNETWORK_FUNC(Boolean, _CFURLDestroyResource, (CFURLRef A, SInt32 *B), (A, B), false)
+DEFINE_WEAK_CFNETWORK_FUNC_FAIL(Boolean, _CFURLCreateDataAndPropertiesFromResource, (CFAllocatorRef A, CFURLRef B, CFDataRef *C, CFDictionaryRef *D, CFArrayRef E, SInt32 *F), (A, B, C, D, E, F), { if(C) *C=NULL; if (D) *D=NULL; if(F) *F=kCFURLImproperArgumentsError; }, false)
+DEFINE_WEAK_CFNETWORK_FUNC_FAIL(Boolean, _CFURLWriteDataAndPropertiesToResource, (CFURLRef A, CFDataRef B, CFDictionaryRef C, SInt32 *D), (A, B, C, D), if (D) *D = kCFURLImproperArgumentsError, false)
 
+DEFINE_WEAK_CFNETWORK_FUNC_FAIL(Boolean, _CFURLDestroyResource, (CFURLRef A, SInt32 *B), (A, B), if(B) *B = kCFURLImproperArgumentsError, false)
+
+#elif DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
 
+typedef struct __NSString__ *NSString;
+
+/*
+    Pre-10.6 property keys
+*/
 
 CONST_STRING_DECL(kCFURLFileExists, "kCFURLFileExists")
 CONST_STRING_DECL(kCFURLFilePOSIXMode, "kCFURLFilePOSIXMode")
@@ -131,7 +152,13 @@ static CFDictionaryRef _CFFileURLCreatePropertiesFromResource(CFAllocatorRef all
     }
 
     if (_CFGetFileProperties(alloc, url, &exists, &posixMode, &size, modTimePtr, &ownerID, contentsPtr) != 0) {
-        if (errorCode) {
+       
+       //  If all they've asked for is whether this file exists, then any error will just make
+       //  this return kCFURLFileExists = kCFBooleanFalse, which handles the case where the filename is invalid or too long or something.
+       if ( arrayRange.length == 1 && CFArrayContainsValue( desiredProperties, arrayRange, kCFURLFileExists ) ) {
+           CFDictionarySetValue(propertyDict, kCFURLFileExists, kCFBooleanFalse);
+       }
+       else if (errorCode) {
             *errorCode = kCFURLUnknownError;
         }
         return propertyDict;
@@ -224,8 +251,12 @@ static Boolean _CFFileURLWritePropertiesToResource(CFURLRef url, CFDictionaryRef
                 CFNumberRef modeNum = (CFNumberRef)value;
                 CFNumberGetValue(modeNum, kCFNumberSInt32Type, &mode);
             } else {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define MODE_TYPE mode_t
+#elif DEPLOYMENT_TARGET_WINDOWS
+#define MODE_TYPE uint16_t
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
                 const MODE_TYPE *modePtr = (const MODE_TYPE *)CFDataGetBytePtr((CFDataRef)value);
                 mode = *modePtr;
@@ -273,9 +304,15 @@ static Boolean _CFFileURLCreateDataAndPropertiesFromResource(CFAllocatorRef allo
 
     if (fetchedProperties) {
         *fetchedProperties = _CFFileURLCreatePropertiesFromResource(alloc, url, desiredProperties, errorCode);
-        if (!*fetchedProperties) success = false;
+        if (!*fetchedProperties)
+           success = false;
     }
 
+    if ( ! success && fetchedData && *fetchedData ) {
+       CFRelease( *fetchedData );
+       *fetchedData = NULL;
+    }
+    
     return success;
 }
 
@@ -518,15 +555,20 @@ done:
 
 static inline CFStringRef percentExpandAndTrimContentType(CFAllocatorRef alloc, CFStringRef str, CFRange range)
 {
-       CFStringRef contentTypeUnexpanded = CFStringCreateWithSubstring(alloc, str, range);
-       CFStringRef contentTypeExpanded = CFURLCreateStringByReplacingPercentEscapes(alloc, contentTypeUnexpanded, CFSTR(""));
-       CFRelease(contentTypeUnexpanded);
-       
-       CFMutableStringRef contentTypeHeader = CFStringCreateMutableCopy(alloc, 0, contentTypeExpanded);
+    CFMutableStringRef contentTypeHeader = NULL;
+    CFStringRef contentTypeUnexpanded = CFStringCreateWithSubstring(alloc, str, range);
+    CFStringRef contentTypeExpanded = CFURLCreateStringByReplacingPercentEscapes(alloc, contentTypeUnexpanded, CFSTR(""));
+    
+    if (NULL == contentTypeExpanded) {
+       contentTypeHeader = CFStringCreateMutableCopy(alloc, 0, contentTypeUnexpanded);
+    } else {
+       contentTypeHeader = CFStringCreateMutableCopy(alloc, 0, contentTypeExpanded);
        CFRelease(contentTypeExpanded);
-       CFStringTrimWhitespace(contentTypeHeader);
-       
-       return contentTypeHeader;
+    }
+    CFRelease(contentTypeUnexpanded);
+    CFStringTrimWhitespace(contentTypeHeader);
+    
+    return contentTypeHeader;
 }
 
 static Boolean parseDataRequestURL(CFURLRef url, CFDataRef* outData, CFStringRef* outMimeType, CFStringRef* outTextEncodingName)
@@ -548,10 +590,6 @@ static Boolean parseDataRequestURL(CFURLRef url, CFDataRef* outData, CFStringRef
                                mimeType = (CFStringRef) CFRetain(CFSTR("text/plain"));
                        }
                        
-                       if (textEncodingName == NULL) {
-                               textEncodingName = (CFStringRef) CFRetain(CFSTR("us-ascii"));
-                       }
-
                        CFIndex bufferSize = CFURLGetBytes(url, NULL, 0);
                        UInt8* srcBuffer = (UInt8*) malloc(bufferSize);
                        CFURLGetBytes(url, srcBuffer, bufferSize);
@@ -690,15 +728,17 @@ Boolean CFURLCreateDataAndPropertiesFromResource(CFAllocatorRef alloc, CFURLRef
         if (CFStringCompare(scheme, CFSTR("file"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
             result = _CFFileURLCreateDataAndPropertiesFromResource(alloc, url, fetchedData, desiredProperties, fetchedProperties, errorCode);
         } else if (CFStringCompare(scheme, CFSTR("data"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
-                       result = _CFDataURLCreateDataAndPropertiesFromResource(alloc, url, fetchedData, desiredProperties, fetchedProperties, errorCode);
-               } else {
-#if DEPLOYMENT_TARGET_MACOSX
+           result = _CFDataURLCreateDataAndPropertiesFromResource(alloc, url, fetchedData, desiredProperties, fetchedProperties, errorCode);
+       } else {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
             result = __CFNetwork__CFURLCreateDataAndPropertiesFromResource(alloc, url, fetchedData, fetchedProperties, desiredProperties, errorCode);
-           if (!result) {
-               if (fetchedData) *fetchedData = NULL;
-               if (fetchedProperties) *fetchedProperties = NULL;
-               if (errorCode) *errorCode = kCFURLUnknownSchemeError;
-           }
+#elif DEPLOYMENT_TARGET_WINDOWS
+            if (fetchedData) *fetchedData = NULL;
+            if (fetchedProperties) *fetchedProperties = NULL;
+            if (errorCode) *errorCode = kCFURLUnknownSchemeError;
+            result = false;
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
         }
         CFRelease(scheme);
@@ -735,12 +775,22 @@ Boolean CFURLWriteDataAndPropertiesToResource(CFURLRef url, CFDataRef data, CFDi
         if (data) {
             if (CFURLHasDirectoryPath(url)) {
                 // Create a directory
+#if DEPLOYMENT_TARGET_WINDOWS
+               wchar_t cPath[CFMaxPathSize];
+                if (!_CFURLGetWideFileSystemRepresentation(url, true, cPath, CFMaxPathSize))
+#else
                 char cPath[CFMaxPathSize];
-                if (!CFURLGetFileSystemRepresentation(url, true, (unsigned char *)cPath, CFMaxPathSize)) {
+                if (!CFURLGetFileSystemRepresentation(url, true, (unsigned char *)cPath, CFMaxPathSize))
+#endif
+                {
                     if (errorCode) *errorCode = kCFURLImproperArgumentsError;
                     success = false;
                 } else {
+#if DEPLOYMENT_TARGET_WINDOWS
+                    success = _CFCreateDirectoryWide(cPath);
+#else
                     success = _CFCreateDirectory(cPath);
+#endif
                     if (!success && errorCode) *errorCode = kCFURLUnknownError;
                 }
             } else {
@@ -758,12 +808,17 @@ Boolean CFURLWriteDataAndPropertiesToResource(CFURLRef url, CFDataRef data, CFDi
         return success;
     } else {
         CFRelease(scheme);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
         Boolean result = __CFNetwork__CFURLWriteDataAndPropertiesToResource(url, data, propertyDict, errorCode);
        if (!result) {
            if (errorCode) *errorCode = kCFURLUnknownSchemeError;
        }
        return result;
+#elif DEPLOYMENT_TARGET_WINDOWS
+        if (errorCode) *errorCode = kCFURLUnknownSchemeError;
+        return false;
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     }
 }
@@ -801,13 +856,19 @@ Boolean CFURLDestroyResource(CFURLRef url, SInt32 *errorCode) {
         }
     } else {
         CFRelease(scheme);
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
         Boolean result = __CFNetwork__CFURLDestroyResource(url, errorCode);
        if (!result) {
            if (errorCode) *errorCode = kCFURLUnknownSchemeError;
        }
        return result;
+#elif DEPLOYMENT_TARGET_WINDOWS
+        if (errorCode) *errorCode = kCFURLUnknownSchemeError;
+        return false;
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
     }
 }
 
+
index ab55127bd212681b837d3849f69b656646bb7c15..32100c616d28f817a1449248d21f0be767fb86a5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFURLAccess.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFURLACCESS__)
 #include <CoreFoundation/CFArray.h>
 #include <CoreFoundation/CFData.h>
 #include <CoreFoundation/CFDictionary.h>
+#include <CoreFoundation/CFError.h>
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFURL.h>
 
 CF_EXTERN_C_BEGIN
 
+
+
 /* Attempts to read the data and properties for the given URL.  If
 only interested in one of the resourceData and properties, pass NULL
 for the other.  If properties is non-NULL and desiredProperties is
@@ -59,7 +62,7 @@ large files.
 
 */
 CF_EXPORT
-Boolean CFURLCreateDataAndPropertiesFromResource(CFAllocatorRef alloc, CFURLRef url, CFDataRef *resourceData, CFDictionaryRef *properties, CFArrayRef desiredProperties, SInt32 *errorCode);
+Boolean CFURLCreateDataAndPropertiesFromResource(CFAllocatorRef alloc, CFURLRef url, CFDataRef *resourceData, CFDictionaryRef *properties, CFArrayRef desiredProperties, SInt32 *errorCode) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 
 /* Attempts to write the given data and properties to the given URL.
 If dataToWrite is NULL, only properties are written out (use
@@ -70,19 +73,20 @@ Returns success or failure; errorCode is set as for
 CFURLCreateDataAndPropertiesFromResource(), above.
 */
 CF_EXPORT
-Boolean CFURLWriteDataAndPropertiesToResource(CFURLRef url, CFDataRef dataToWrite, CFDictionaryRef propertiesToWrite, SInt32 *errorCode);
+Boolean CFURLWriteDataAndPropertiesToResource(CFURLRef url, CFDataRef dataToWrite, CFDictionaryRef propertiesToWrite, SInt32 *errorCode) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 
 /* Destroys the resource indicated by url. */
 /* Returns success or failure; errorCode set as above. */
 CF_EXPORT
-Boolean CFURLDestroyResource(CFURLRef url, SInt32 *errorCode);
+Boolean CFURLDestroyResource(CFURLRef url, SInt32 *errorCode) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 
 /* Convenience method which calls through to CFURLCreateDataAndPropertiesFromResource(). */
 /* Returns NULL on error and sets errorCode accordingly. */
 CF_EXPORT
-CFTypeRef CFURLCreatePropertyFromResource(CFAllocatorRef alloc, CFURLRef url, CFStringRef property, SInt32 *errorCode);
+CFTypeRef CFURLCreatePropertyFromResource(CFAllocatorRef alloc, CFURLRef url, CFStringRef property, SInt32 *errorCode) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
+
 
-/* Common error codes; this list is expected to grow */
+/* Common error codes (returned only by the older APIs that predate CFError) */
 enum {
     kCFURLUnknownError = -10,
     kCFURLUnknownSchemeError = -11,
@@ -96,24 +100,24 @@ enum {
 };
 typedef CFIndex CFURLError;
 
-/* Property keys */
+/* Older property keys */
 
 CF_EXPORT
-const CFStringRef kCFURLFileExists;
+const CFStringRef kCFURLFileExists AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 CF_EXPORT
-const CFStringRef kCFURLFileDirectoryContents;
+const CFStringRef kCFURLFileDirectoryContents AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 CF_EXPORT
-const CFStringRef kCFURLFileLength;
+const CFStringRef kCFURLFileLength AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 CF_EXPORT 
-const CFStringRef kCFURLFileLastModificationTime;
+const CFStringRef kCFURLFileLastModificationTime AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 CF_EXPORT
-const CFStringRef kCFURLFilePOSIXMode;
+const CFStringRef kCFURLFilePOSIXMode AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 CF_EXPORT
-const CFStringRef kCFURLFileOwnerID;
+const CFStringRef kCFURLFileOwnerID AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 CF_EXPORT
-const CFStringRef kCFURLHTTPStatusCode;
+const CFStringRef kCFURLHTTPStatusCode AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 CF_EXPORT
-const CFStringRef kCFURLHTTPStatusLine;
+const CFStringRef kCFURLHTTPStatusLine AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
 
 /* The value of kCFURLFileExists is a CFBoolean */
 /* The value of kCFURLFileDirectoryContents is a CFArray containing CFURLs.  An empty array means the directory exists, but is empty */
index ad8d89e09588a90b02626b68a28ec671cfcc3b30..31ea3e2e1dd7f73a14252618283ba19a35ce4b3d 100644 (file)
--- a/CFUUID.c
+++ b/CFUUID.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUUID.c
-       Copyright (c) 1999-2007 Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
        Responsibility: Doug Davidson
 */
 
 #include <CoreFoundation/CFUUID.h>
 #include "CFInternal.h"
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <uuid/uuid.h>
 #endif
 
@@ -50,8 +50,10 @@ static CFHashCode __CFhashUUIDBytes(const void *ptr) {
     return CFHashBytes((uint8_t *)ptr, 16);
 }
 
-#import "auto_stubs.h"
-
+/*
+ * GC implementation of a weak set specifically designed for UUID
+ */
 #define LOCK() __CFSpinLock(&CFUUIDGlobalDataLock)
 #define UNLOCK() __CFSpinUnlock(&CFUUIDGlobalDataLock)
 
@@ -59,41 +61,134 @@ static CFHashCode __CFhashUUIDBytes(const void *ptr) {
 #define FREE(x) CFAllocatorDeallocate(kCFAllocatorSystemDefault, x)
 #define HASH(x) CFHashBytes((uint8_t *)x, 16)
 
+#define READWEAK(location) auto_read_weak_reference(auto_zone(), (void**)location)
+#define WRITEWEAK(location, value) auto_assign_weak_reference(auto_zone(), value, (void **)location, NULL)
+
+typedef struct {
+    unsigned long count, size;
+    struct __CFUUID **weakPtrs;
+} _UUIDWeakSet_t;
+
+static _UUIDWeakSet_t _UUIDWeakSet;
+
+static void grow_has_lock(void);
+
+// enter if not already present
+static void enter_has_lock(struct __CFUUID *candidate) {
+    if (!candidate) return;
+    _UUIDWeakSet_t *table = &_UUIDWeakSet;
+    if (!table->size) grow_has_lock();
+    unsigned long int hashValue = HASH(&candidate->_bytes) & (table->size-1);
+    struct __CFUUID *result = table->weakPtrs[hashValue];
+    while (1) {
+        if (result == (void *)0x1 || result == NULL) {
+            table->weakPtrs[hashValue] = NULL;  // so that we don't try to unregister 0x1
+            WRITEWEAK(&table->weakPtrs[hashValue], (void *)candidate);
+            ++table->count;
+            break;
+        }
+        if (result) result = (struct __CFUUID *)READWEAK(&table->weakPtrs[hashValue]);
+        if (result) {
+            // see if it is equal to candidate
+            if (__CFisEqualUUIDBytes(&result->_bytes, &candidate->_bytes)) {
+                // keep first one.  There is a race if two threads both fail to find
+                // a candidate uuid then both try decide to create and enter one.
+                // Under non-GC one of them simply leaks.
+                break;
+            }
+        } else {
+            // was zeroed by collector.  Use this slot.
+            continue;
+        }
+        // move on
+        if (++hashValue >= table->size) hashValue = 0;
+        result = table->weakPtrs[hashValue];
+    }
+}
+
+static void *find_has_lock(CFUUIDBytes *bytes) {
+    if (!bytes) return NULL;
+    _UUIDWeakSet_t *table = &_UUIDWeakSet;
+    if (!table->size) return NULL;  // no entries
+    unsigned long int hashValue = HASH(bytes) & (table->size-1);
+    struct __CFUUID *result = table->weakPtrs[hashValue];
+    while (1) {
+        if (result == (void *)0x1) break;
+        if (result) result = (struct __CFUUID *)READWEAK(&table->weakPtrs[hashValue]);
+        if (result) {
+            // see if it is equal to bytes
+            if (__CFisEqualUUIDBytes(&result->_bytes, bytes)) return result;
+        }
+        // move on
+        if (++hashValue >= table->size) hashValue = 0;
+        result = table->weakPtrs[hashValue];
+    }
+    return NULL;
+}
+
+
+static void grow_has_lock() {
+    _UUIDWeakSet_t *table = &_UUIDWeakSet;
+    if (table->size == 0) {
+        table->size = 16;
+        table->weakPtrs = (struct __CFUUID **)MALLOC(sizeof(struct __CFUUID *)*table->size);
+        for (int i = 0; i < table->size; ++i) table->weakPtrs[i] = (struct __CFUUID *)0x1;
+        table->count = 0;
+        return;
+    }
+    table->count = 0;
+    table->size = table->size*2;
+    struct __CFUUID **oldPtrs = table->weakPtrs;
+    table->weakPtrs = (struct __CFUUID **)MALLOC(sizeof(struct __CFUUID *)*table->size);
+    for (int i = 0; i < table->size; ++i) table->weakPtrs[i] = (struct __CFUUID *)0x1;
+    for (int i = 0; i < table->size / 2; ++i) {
+        if (oldPtrs[i] == (struct __CFUUID *)0x1) continue; // available field, ignore
+        if (oldPtrs[i] == NULL) continue;  // zero'ed by collector, ignore
+        enter_has_lock((struct __CFUUID *)READWEAK(&oldPtrs[i]));  // read, then enter (but enter must check for NULL)
+        WRITEWEAK(&oldPtrs[i], NULL);  // unregister
+    }
+    FREE(oldPtrs);
+}
 
 /***** end of weak set */
 
 static void __CFUUIDAddUniqueUUID(CFUUIDRef uuid) {
-    __CFSpinLock(&CFUUIDGlobalDataLock);
-        
     CFDictionaryKeyCallBacks __CFUUIDBytesDictionaryKeyCallBacks = {0, NULL, NULL, NULL, __CFisEqualUUIDBytes, __CFhashUUIDBytes};
     CFDictionaryValueCallBacks __CFnonRetainedUUIDDictionaryValueCallBacks = {0, NULL, NULL, CFCopyDescription, CFEqual};
 
-    if (_uniquedUUIDs == NULL) {
-        _uniquedUUIDs = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &__CFUUIDBytesDictionaryKeyCallBacks, &__CFnonRetainedUUIDDictionaryValueCallBacks);
+    __CFSpinLock(&CFUUIDGlobalDataLock);
+    if (kCFUseCollectableAllocator) {
+        enter_has_lock((struct __CFUUID *)uuid);
+        if (_UUIDWeakSet.count > (3 * _UUIDWeakSet.size / 4)) grow_has_lock();
+        __CFSpinUnlock(&CFUUIDGlobalDataLock);
+        return;
     }
+    if (!_uniquedUUIDs) _uniquedUUIDs = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &__CFUUIDBytesDictionaryKeyCallBacks, &__CFnonRetainedUUIDDictionaryValueCallBacks);
     CFDictionarySetValue(_uniquedUUIDs, &(uuid->_bytes), uuid);
     __CFSpinUnlock(&CFUUIDGlobalDataLock);
 }
 
 static void __CFUUIDRemoveUniqueUUID(CFUUIDRef uuid) {
     __CFSpinLock(&CFUUIDGlobalDataLock);
-    if (_uniquedUUIDs != NULL) {
-        CFDictionaryRemoveValue(_uniquedUUIDs, &(uuid->_bytes));
-    }
+    if (_uniquedUUIDs) CFDictionaryRemoveValue(_uniquedUUIDs, &(uuid->_bytes));
     __CFSpinUnlock(&CFUUIDGlobalDataLock);
 }
 
 static CFUUIDRef __CFUUIDGetUniquedUUID(CFUUIDBytes *bytes) {
     CFUUIDRef uuid = NULL;
     __CFSpinLock(&CFUUIDGlobalDataLock);
-    if (_uniquedUUIDs != NULL) {
+    if (kCFUseCollectableAllocator) {
+        uuid = (CFUUIDRef)find_has_lock(bytes);
+    } else if (_uniquedUUIDs) {
         uuid = (CFUUIDRef)CFDictionaryGetValue(_uniquedUUIDs, bytes);
     }
     __CFSpinUnlock(&CFUUIDGlobalDataLock);
     return uuid;
 }
 
-static void __CFUUIDDeallocate(CFTypeRef cf) {    
+static void __CFUUIDDeallocate(CFTypeRef cf) {
+    if (kCFUseCollectableAllocator) return;
+    
     struct __CFUUID *uuid = (struct __CFUUID *)cf;
     __CFUUIDRemoveUniqueUUID(uuid);
 }
@@ -133,35 +228,41 @@ CFTypeID CFUUIDGetTypeID(void) {
 
 static CFUUIDRef __CFUUIDCreateWithBytesPrimitive(CFAllocatorRef allocator, CFUUIDBytes bytes, Boolean isConst) {
     struct __CFUUID *uuid = (struct __CFUUID *)__CFUUIDGetUniquedUUID(&bytes);
-
-    if (uuid == NULL) {
+    if (!uuid) {
         size_t size;
         size = sizeof(struct __CFUUID) - sizeof(CFRuntimeBase);
-        uuid = (struct __CFUUID *)_CFRuntimeCreateInstance(allocator, __kCFUUIDTypeID, size, NULL);
+        uuid = (struct __CFUUID *)_CFRuntimeCreateInstance(kCFUseCollectableAllocator ? kCFAllocatorSystemDefault : allocator, __kCFUUIDTypeID, size, NULL);
 
-        if (NULL == uuid) return NULL;
+        if (!uuid) return NULL;
 
         uuid->_bytes = bytes;
-
         __CFUUIDAddUniqueUUID(uuid);
     } else if (!isConst) {
         CFRetain(uuid);
     }
-    
     return (CFUUIDRef)uuid;
 }
 
+#if DEPLOYMENT_TARGET_WINDOWS
+#include <Rpc.h>
+#endif
+
 CFUUIDRef CFUUIDCreate(CFAllocatorRef alloc) {
     /* Create a new bytes struct and then call the primitive. */
     CFUUIDBytes bytes;
     uint32_t retval = 0;
     
     __CFSpinLock(&CFUUIDGlobalDataLock);
-#if (DEPLOYMENT_TARGET_MACOSX)
+#if DEPLOYMENT_TARGET_WINDOWS
+    UUID u;
+    long rStatus = UuidCreate(&u);
+    if (RPC_S_OK != rStatus && RPC_S_UUID_LOCAL_ONLY != rStatus) retval = 1;
+    memmove(&bytes, &u, sizeof(bytes));
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     static Boolean useV1UUIDs = false, checked = false;
     uuid_t uuid;
     if (!checked) {
-        const char *value = getenv("CFUUIDVersionNumber");
+        const char *value = __CFgetenv("CFUUIDVersionNumber");
         if (value) {
             if (1 == strtoul_l(value, NULL, 0, NULL)) useV1UUIDs = true;
         } else {
@@ -268,30 +369,24 @@ CFUUIDRef CFUUIDCreateFromString(CFAllocatorRef alloc, CFStringRef uuidStr) {
     memset((void *)&bytes, 0, sizeof(bytes));
 
     /* Skip initial random stuff */
-    while (!_isHexChar(chars[i]) && (i < len)) {
-        i++;
-    }
+    while (!_isHexChar(chars[i]) && i < len) i++;
 
     READ_A_BYTE(bytes.byte0);
     READ_A_BYTE(bytes.byte1);
     READ_A_BYTE(bytes.byte2);
     READ_A_BYTE(bytes.byte3);
-
     i++;
 
     READ_A_BYTE(bytes.byte4);
     READ_A_BYTE(bytes.byte5);
-
     i++;
 
     READ_A_BYTE(bytes.byte6);
     READ_A_BYTE(bytes.byte7);
-
     i++;
 
     READ_A_BYTE(bytes.byte8);
     READ_A_BYTE(bytes.byte9);
-
     i++;
 
     READ_A_BYTE(bytes.byte10);
index d98ec21fc9d6193904b5c3be770f4957c838dee4..acf726b6d3528159008bcca899e7b854527df935 100644 (file)
--- a/CFUUID.h
+++ b/CFUUID.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUUID.h
-       Copyright (c) 1999-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFUUID__)
index 7f4105636bc57e9f1f74dc06eb3f7cec7160949d..e76b309e15092deb3422b7539ce7a3f8c73cde3a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUniChar.c
-       Copyright 2001-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 2001-2009, Apple Inc. All rights reserved.
        Responsibility: Aki Inoue
 */
 
@@ -32,7 +32,7 @@
 #include "CFStringEncodingConverterExt.h"
 #include "CFUnicodeDecomposition.h"
 #include "CFUniCharPriv.h"
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <zlib.h>
 #endif
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <mach/mach.h>
 #endif
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+extern void _CFGetFrameworkPath(wchar_t *path, int maxLength);
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define __kCFCharacterSetDir "/System/Library/CoreServices"
 #elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
 #define __kCFCharacterSetDir "/usr/local/share/CoreFoundation"
-#elif defined(__WIN32__)
+#elif DEPLOYMENT_TARGET_WINDOWS
 #define __kCFCharacterSetDir "\\Windows\\CoreFoundation"
 #endif
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #define USE_MACHO_SEGMENT 1
-#endif //__MACH__
+#endif
 
 enum {
     kCFUniCharLastExternalSet = kCFUniCharNewlineCharacterSet,
@@ -67,8 +72,7 @@ enum {
 CF_INLINE uint32_t __CFUniCharMapExternalSetToInternalIndex(uint32_t cset) { return ((kCFUniCharFirstInternalSet <= cset) ? ((cset - kCFUniCharFirstInternalSet) + kCFUniCharLastExternalSet) : cset) - kCFUniCharFirstBitmapSet; }
 CF_INLINE uint32_t __CFUniCharMapCompatibilitySetID(uint32_t cset) { return ((cset == kCFUniCharControlCharacterSet) ? kCFUniCharControlAndFormatterCharacterSet : (((cset > kCFUniCharLastExternalSet) && (cset < kCFUniCharFirstInternalSet)) ? ((cset - kCFUniCharLastExternalSet) + kCFUniCharFirstInternalSet) : cset)); }
 
-#if (DEPLOYMENT_TARGET_MACOSX) && USE_MACHO_SEGMENT
-
+#if (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED) && USE_MACHO_SEGMENT
 #include <mach-o/getsect.h>
 #include <mach-o/dyld.h>
 #include <mach-o/ldsyms.h>
@@ -90,32 +94,33 @@ static const void *__CFGetSectDataPtr(const char *segname, const char *sectname,
     if (sizep) *sizep = 0ULL;
     return NULL;
 }
-
 #endif
 
 #if !USE_MACHO_SEGMENT
 
 // Memory map the file
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 CF_INLINE void __CFUniCharCharacterSetPath(char *cpath) {
-#if DEPLOYMENT_TARGET_MACOSX
-    strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
-#else
-    strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
-#endif
-
-#if 0 || 0
-#if 0
-    strncat(cpath, "\\Resources\\", MAXPATHLEN - strlen(cpath));
+#elif DEPLOYMENT_TARGET_WINDOWS
+CF_INLINE void __CFUniCharCharacterSetPath(wchar_t *wpath) {
 #else
-    strncat(cpath, "\\CoreFoundation.resources\\CharacterSets\\", MAXPATHLEN - strlen(cpath));
+#error Unknown or unspecified DEPLOYMENT_TARGET
 #endif
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
+#elif DEPLOYMENT_TARGET_WINDOWS
+    wchar_t frameworkPath[MAXPATHLEN];
+    _CFGetFrameworkPath(frameworkPath, MAXPATHLEN);
+    wcsncpy(wpath, frameworkPath, MAXPATHLEN);
+    wcsncat(wpath, L"\\CoreFoundation.resources\\", MAXPATHLEN - wcslen(wpath));
 #else
+    strlcpy(cpath, __kCFCharacterSetDir, MAXPATHLEN);
     strlcat(cpath, "/CharacterSets/", MAXPATHLEN);
 #endif
 }
 
-#if defined (__WIN32__)
+#if DEPLOYMENT_TARGET_WINDOWS
 #define MAX_BITMAP_STATE 512
 //
 //  If a string is placed into this array, then it has been previously 
@@ -127,17 +132,17 @@ CF_INLINE void __CFUniCharCharacterSetPath(char *cpath) {
 //
 //  We should probably re-visit this.
 //
-static char *mappedBitmapState[MAX_BITMAP_STATE];
+static wchar_t *mappedBitmapState[MAX_BITMAP_STATE];
 static int __nNumStateEntries = -1;
 CRITICAL_SECTION __bitmapStateLock = {0};
 
-bool __GetBitmapStateForName(char *bitmapName) {
+bool __GetBitmapStateForName(const wchar_t *bitmapName) {
     if (NULL == __bitmapStateLock.DebugInfo)
         InitializeCriticalSection(&__bitmapStateLock);
     EnterCriticalSection(&__bitmapStateLock);
     if (__nNumStateEntries >= 0) {
         for (int i = 0; i < __nNumStateEntries; i++) {
-            if (strcmp(mappedBitmapState[i], bitmapName) == 0) {
+            if (wcscmp(mappedBitmapState[i], bitmapName) == 0) {
                 LeaveCriticalSection(&__bitmapStateLock);
                 return true;
             }
@@ -146,37 +151,43 @@ bool __GetBitmapStateForName(char *bitmapName) {
     LeaveCriticalSection(&__bitmapStateLock);
     return false;
 }
-void __AddBitmapStateForName(char *bitmapName) {
+void __AddBitmapStateForName(const wchar_t *bitmapName) {
     if (NULL == __bitmapStateLock.DebugInfo)
         InitializeCriticalSection(&__bitmapStateLock);
     EnterCriticalSection(&__bitmapStateLock);
     __nNumStateEntries++;
-    mappedBitmapState[__nNumStateEntries] = (char *)malloc((strlen(bitmapName)+1) * sizeof(char));
-    strcpy(mappedBitmapState[__nNumStateEntries], bitmapName);
+    mappedBitmapState[__nNumStateEntries] = (wchar_t *)malloc((lstrlenW(bitmapName)+1) * sizeof(wchar_t));
+    lstrcpyW(mappedBitmapState[__nNumStateEntries], bitmapName);
     LeaveCriticalSection(&__bitmapStateLock);
 }
-#endif //__WIN32__
+#endif
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static bool __CFUniCharLoadBytesFromFile(const char *fileName, const void **bytes) {
-#if 0 || 0
+#elif DEPLOYMENT_TARGET_WINDOWS
+static bool __CFUniCharLoadBytesFromFile(const wchar_t *fileName, const void **bytes) {
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
+#if DEPLOYMENT_TARGET_WINDOWS
     HANDLE bitmapFileHandle = NULL;
     HANDLE mappingHandle = NULL;
     
-    if (__GetBitmapStateForName((char *)fileName)) {
+    if (__GetBitmapStateForName(fileName)) {
         // The fileName has been tried in the past, so just return false
         // and move on.
         *bytes = NULL;
         return false;
     }
-    mappingHandle = OpenFileMappingA(FILE_MAP_READ, TRUE, fileName);
+    mappingHandle = OpenFileMappingW(FILE_MAP_READ, TRUE, fileName);
     if (NULL == mappingHandle) {
-        if ((bitmapFileHandle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
+        if ((bitmapFileHandle = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
             // We tried to get the bitmap file for mapping, but it's not there.  Add to list of non-existant bitmap-files so
             // we don't have to try this again in the future.
-            __AddBitmapStateForName((char *)fileName);
+            __AddBitmapStateForName(fileName);
             return false;
         }
-        mappingHandle = CreateFileMappingA(bitmapFileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
+        mappingHandle = CreateFileMapping(bitmapFileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
         CloseHandle(bitmapFileHandle);
         if (!mappingHandle) return false;
 
@@ -192,9 +203,7 @@ static bool __CFUniCharLoadBytesFromFile(const char *fileName, const void **byte
     struct stat statBuf;
     int fd = -1;
 
-    int no_hang_fd = open("/dev/autofs_nowait", 0);
     if ((fd = open(fileName, O_RDONLY, 0)) < 0) {
-       close(no_hang_fd);
        return false;
     }
     if (fstat(fd, &statBuf) < 0 || (*bytes = mmap(0, statBuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1) {
@@ -202,7 +211,6 @@ static bool __CFUniCharLoadBytesFromFile(const char *fileName, const void **byte
         return false;
     }
     close(fd);
-    close(no_hang_fd);
 
     return true;
 #endif
@@ -210,15 +218,30 @@ static bool __CFUniCharLoadBytesFromFile(const char *fileName, const void **byte
 
 #endif // USE_MACHO_SEGMENT
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static bool __CFUniCharLoadFile(const char *bitmapName, const void **bytes) {
+#elif DEPLOYMENT_TARGET_WINDOWS
+static bool __CFUniCharLoadFile(const wchar_t *bitmapName, const void **bytes) {
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 #if USE_MACHO_SEGMENT
        *bytes = __CFGetSectDataPtr("__UNICODE", bitmapName, NULL);
     return *bytes ? true : false;
 #else
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     char cpath[MAXPATHLEN];
     __CFUniCharCharacterSetPath(cpath);
        strlcat(cpath, bitmapName, MAXPATHLEN);
     return __CFUniCharLoadBytesFromFile(cpath, bytes);
+#elif DEPLOYMENT_TARGET_WINDOWS
+    wchar_t wpath[MAXPATHLEN];
+    __CFUniCharCharacterSetPath(wpath);
+       wcsncat(wpath, bitmapName, MAXPATHLEN);
+    return __CFUniCharLoadBytesFromFile(wpath, bytes);
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 #endif
 }
 
@@ -251,6 +274,7 @@ static __CFUniCharBitmapData *__CFUniCharBitmapDataArray = NULL;
 
 static CFSpinLock_t __CFUniCharBitmapLock = CFSpinLockInit;
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #if !defined(CF_UNICHAR_BITMAP_FILE)
 #if USE_MACHO_SEGMENT
 #define CF_UNICHAR_BITMAP_FILE "__csbitmaps"
@@ -258,6 +282,13 @@ static CFSpinLock_t __CFUniCharBitmapLock = CFSpinLockInit;
 #define CF_UNICHAR_BITMAP_FILE "CFCharacterSetBitmaps.bitmap"
 #endif
 #endif
+#elif DEPLOYMENT_TARGET_WINDOWS
+#if !defined(CF_UNICHAR_BITMAP_FILE)
+#define CF_UNICHAR_BITMAP_FILE L"CFCharacterSetBitmaps.bitmap"
+#endif
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 
 static bool __CFUniCharLoadBitmapData(void) {
     __CFUniCharBitmapData *array;
@@ -311,7 +342,7 @@ static bool __CFUniCharLoadBitmapData(void) {
                                currentPlane = *(((const uint8_t*&)bitmap)++);
 #else
                                currentPlane = *((const uint8_t *)bitmap++);
-#endif //C++
+#endif
 
             } else {
                 array[idx]._planes[bitmapIndex] = NULL;
@@ -406,13 +437,13 @@ __private_extern__ uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t
                        while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = ~(*(src++));
 #else
                        while (numBytes-- > 0) *((uint8_t *)bitmap++) = ~(*(src++));
-#endif //C++
+#endif
         } else {
 #if defined (__cplusplus)
             while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = *(src++);
 #else
                        while (numBytes-- > 0) *((uint8_t *)bitmap++) = *(src++);
-#endif //C++
+#endif
         }
         return kCFUniCharBitmapFilled;
     } else if (charset == kCFUniCharIllegalCharacterSet) {
@@ -424,13 +455,13 @@ __private_extern__ uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t
                                while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = *(src++);
 #else
                                while (numBytes-- > 0) *((uint8_t *)bitmap++) = *(src++);
-#endif //C++
+#endif
             } else {
 #if defined (__cplusplus)                
                 while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = ~(*(src++));
 #else
                                while (numBytes-- > 0) *((uint8_t *)bitmap++) = ~(*(src++));
-#endif //C++
+#endif
             }
             return kCFUniCharBitmapFilled;
         } else if (plane == 0x0E) { // Plane 14
@@ -442,13 +473,13 @@ __private_extern__ uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t
                        *(((uint8_t *&)bitmap)++) = 0x02; // UE0001 LANGUAGE TAG
 #else
                        *((uint8_t *)bitmap++) = 0x02; // UE0001 LANGUAGE TAG
-#endif //C++
+#endif
             for (idx = 1;idx < numBytes;idx++) {
 #if defined (__cplusplus)                
                                *(((uint8_t *&)bitmap)++) = ((idx >= (0x20 / 8) && (idx < (0x80 / 8))) ? asciiRange : otherRange);
 #else
                                *((uint8_t *)bitmap++) = ((idx >= (0x20 / 8) && (idx < (0x80 / 8))) ? asciiRange : otherRange);
-#endif //C++
+#endif
             }
             return kCFUniCharBitmapFilled;
         } else if (plane == 0x0F || plane == 0x10) { // Plane 15 & 16
@@ -461,7 +492,7 @@ __private_extern__ uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t
                                bitmap = (uint8_t *)bitmap + sizeof(uint32_t);                          
 #else
                                bitmap += sizeof(uint32_t);
-#endif //C++
+#endif
             }
             *(((uint8_t *)bitmap) - 5) = (isInverted ? 0x3F : 0xC0); // 0xFFFE & 0xFFFF
             return kCFUniCharBitmapFilled;
@@ -478,7 +509,7 @@ __private_extern__ uint8_t CFUniCharGetBitmapForPlane(uint32_t charset, uint32_t
                     while (numBytes-- > 0) *(((uint8_t *&)bitmap)++) = nonFillValue;
 #else
                     while (numBytes-- > 0) *((uint8_t *)bitmap++) = nonFillValue;
-#endif //C++
+#endif
 
         if ((charset == kCFUniCharWhitespaceAndNewlineCharacterSet) || (charset == kCFUniCharNewlineCharacterSet)) {
             const UniChar newlines[] = {0x000A, 0x000B, 0x000C, 0x000D, 0x0085, 0x2028, 0x2029};
@@ -547,6 +578,7 @@ static const void **__CFUniCharMappingTables = NULL;
 
 static CFSpinLock_t __CFUniCharMappingTableLock = CFSpinLockInit;
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #if __CF_BIG_ENDIAN__
 #if USE_MACHO_SEGMENT
 #define MAPPING_TABLE_FILE "__data"
@@ -560,6 +592,23 @@ static CFSpinLock_t __CFUniCharMappingTableLock = CFSpinLockInit;
 #define MAPPING_TABLE_FILE "CFUnicodeData-L.mapping"
 #endif
 #endif
+#elif DEPLOYMENT_TARGET_WINDOWS
+#if __CF_BIG_ENDIAN__
+#if USE_MACHO_SEGMENT
+#define MAPPING_TABLE_FILE "__data"
+#else
+#define MAPPING_TABLE_FILE L"CFUnicodeData-B.mapping"
+#endif
+#else
+#if USE_MACHO_SEGMENT
+#define MAPPING_TABLE_FILE "__data"
+#else
+#define MAPPING_TABLE_FILE L"CFUnicodeData-L.mapping"
+#endif
+#endif
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 
 __private_extern__ const void *CFUniCharGetMappingData(uint32_t type) {
 
@@ -582,7 +631,7 @@ __private_extern__ const void *CFUniCharGetMappingData(uint32_t type) {
 #else
                bytes += 4; // Skip Unicode version
                headerSize = *((uint32_t *)bytes); bytes += sizeof(uint32_t);
-#endif //C++        
+#endif    
         headerSize -= (sizeof(uint32_t) * 2);
         bodyBase = (char *)bytes + headerSize;
 
@@ -595,7 +644,7 @@ __private_extern__ const void *CFUniCharGetMappingData(uint32_t type) {
                        __CFUniCharMappingTables[idx] = (char *)bodyBase + *((uint32_t *)bytes); bytes = (uint8_t *)bytes + sizeof(uint32_t);
 #else
                        __CFUniCharMappingTables[idx] = (char *)bodyBase + *((uint32_t *)bytes); bytes += sizeof(uint32_t);
-#endif //C++
+#endif
         }
     }
 
@@ -979,11 +1028,21 @@ static int __CFUniCharUnicodePropertyTableCount = 0;
 
 static CFSpinLock_t __CFUniCharPropTableLock = CFSpinLockInit;
 
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #if USE_MACHO_SEGMENT
 #define PROP_DB_FILE "__properties"
 #else
 #define PROP_DB_FILE "CFUniCharPropertyDatabase.data"
 #endif
+#elif DEPLOYMENT_TARGET_WINDOWS
+#if USE_MACHO_SEGMENT
+#define PROP_DB_FILE "__properties"
+#else
+#define PROP_DB_FILE L"CFUniCharPropertyDatabase.data"
+#endif
+#else
+#error Unknown or unspecified DEPLOYMENT_TARGET
+#endif
 
 const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint32_t plane) {
 
@@ -1010,7 +1069,7 @@ const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint3
 #else
                bytes += 4; // Skip Unicode version
                headerSize = CFSwapInt32BigToHost(*((uint32_t *)bytes)); bytes += sizeof(uint32_t);
-#endif //C++
+#endif
                
         headerSize -= (sizeof(uint32_t) * 2);
         bodyBase = (char *)bytes + headerSize;
@@ -1032,7 +1091,7 @@ const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint3
                                        planeBase = (char*)planeBase + (planeSize * 256);
 #else
                                        planeBase += (planeSize * 256);
-#endif //C++
+#endif
                 } else {
                     table[idx]._planes[planeIndex] = NULL;
                 }
@@ -1044,7 +1103,7 @@ const void *CFUniCharGetUnicodePropertyDataForPlane(uint32_t propertyType, uint3
                        ((uint32_t *&)bytes) ++;
 #else
                        bodyBase += (CFSwapInt32BigToHost(*((uint32_t *)bytes++)));
-#endif //C++
+#endif
         }
 
         __CFUniCharUnicodePropertyTable = table;
@@ -1188,7 +1247,7 @@ bool CFUniCharFillDestinationBuffer(const UTF32Char *src, CFIndex srcLength, voi
     return true;
 }
 
-#if 0 || 0
+#if DEPLOYMENT_TARGET_WINDOWS
 void __CFUniCharCleanup(void)
 {
     int        idx;
@@ -1244,7 +1303,7 @@ void __CFUniCharCleanup(void)
     
     __CFSpinUnlock(&__CFUniCharPropTableLock);
 }
-#endif // __WIN32__
+#endif
 
 #undef USE_MACHO_SEGMENT
 
index b9b8c39ef8d6694cb0c76033fecb46328a26d072..382d842bc441c183ffcd77ba9bd3f3bdcaf9d3f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUniChar.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFUNICHAR__)
@@ -121,9 +121,9 @@ enum {
 };
 
 enum {
-    kCFUniCharCaseMapFinalSigma = (1),
-    kCFUniCharCaseMapAfter_i = (1 << 1),
-    kCFUniCharCaseMapMoreAbove = (1 << 2)
+    kCFUniCharCaseMapFinalSigma = (1UL << 0),
+    kCFUniCharCaseMapAfter_i = (1UL << 1),
+    kCFUniCharCaseMapMoreAbove = (1UL << 2)
 };
 
 CF_EXPORT CFIndex CFUniCharMapCaseTo(UTF32Char theChar, UTF16Char *convertedChar, CFIndex maxLength, uint32_t ctype, uint32_t flags, const uint8_t *langCode);
index f9667fa14985543aab11822e0f887fa93e49f4b8..c9ca7f6fef5ece118197404d6447ad61e4b1aa6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUniCharPriv.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFUNICHARPRIV__)
@@ -30,8 +30,8 @@
 #include <CoreFoundation/CFBase.h>
 #include <CoreFoundation/CFUniChar.h>
 
-#define kCFUniCharRecursiveDecompositionFlag   (1 << 30)
-#define kCFUniCharNonBmpFlag                   (1 << 31)
+#define kCFUniCharRecursiveDecompositionFlag   (1UL << 30)
+#define kCFUniCharNonBmpFlag                   (1UL << 31)
 #define CFUniCharConvertCountToFlag(count)     ((count & 0x1F) << 24)
 #define CFUniCharConvertFlagToCount(flag)      ((flag >> 24) & 0x1F)
 
index 6898045aa88a56d403a64ab6493289d404c108a3..785058ebb4efecea122992cc5575dc539ada1fff 100644 (file)
Binary files a/CFUniCharPropertyDatabase.data and b/CFUniCharPropertyDatabase.data differ
index 75e8f3a0538ec0246b9f61943dcd57bd8f65e4eb..3212a19ea8876adc63104d89782ef309e8fcb20b 100644 (file)
Binary files a/CFUnicodeData-B.mapping and b/CFUnicodeData-B.mapping differ
index a41d4db07ef4aacc3ca3a09dbbcf6295187a3e38..ea75386dc8d6eef780a15a4d86bcb46142efb9b6 100644 (file)
Binary files a/CFUnicodeData-L.mapping and b/CFUnicodeData-L.mapping differ
index f32f3dbf2a4ee45b3d76b9e45cec487fdcc6f8a5..46bcc4c9bd0f236c4aaaed223e86e8a6de462736 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*    CFUnicodeDecomposition.c
-    Copyright 1999-2002, Apple, Inc. All rights reserved.
+    Copyright (c) 1999-2009, Apple Inc. All rights reserved.
     Responsibility: Aki Inoue
 */
 
index 78463444bafbdc1895422899e75303892e6597cd..67166fbf525be801991b9665ddb66e10fa3ab742 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -25,7 +25,7 @@
  *  CoreFoundation
  *
  *  Created by aki on Wed Oct 03 2001.
- *  Copyright (c) 2001-2007, Apple Inc. All rights reserved.
+ *  Copyright (c) 2001-2009, Apple Inc. All rights reserved.
  *
  */
 
index 9dac3e3296345348cbaf0e1f3b7676a359392dd1..8a02e81fb057e92d87b435dd37fc0f7d0f8d6cc7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUnicodePrecomposition.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Aki Inoue
 */
 
index efa0428ab356d222b6c403a048085373e75e94bb..65d4e363e1491307e9d583bea77960f570bafda6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -25,7 +25,7 @@
  *  CoreFoundation
  *
  *  Created by aki on Wed Oct 03 2001.
- *  Copyright (c) 2001-2007, Apple Inc. All rights reserved.
+ *  Copyright (c) 2001-2009, Apple Inc. All rights reserved.
  *
  */
 
index 68f86c33082dc4d10a93d65d18bc6ed1be1f2a3a..ee63e859fca5dfc93e5172da4a063fc9c70660ab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUserNotification.c
-       Copyright (c) 2000-2007 Apple Inc.  All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc.  All rights reserved.
        Responsibility: Doug Davidson
 */
 
@@ -74,6 +74,8 @@ CONST_STRING_DECL(kCFUserNotificationCheckBoxTitlesKey, "CheckBoxTitles")
 CONST_STRING_DECL(kCFUserNotificationTextFieldValuesKey, "TextFieldValues")
 CONST_STRING_DECL(kCFUserNotificationPopUpSelectionKey, "PopUpSelection")
 CONST_STRING_DECL(kCFUserNotificationKeyboardTypesKey, "KeyboardTypes")
+CONST_STRING_DECL(kCFUserNotificationAlertTopMostKey, "AlertTopMost") // boolean value
+
 
 static CFTypeID __kCFUserNotificationTypeID = _kCFRuntimeNotATypeID;
 
@@ -104,7 +106,7 @@ static CFStringRef __CFUserNotificationCopyDescription(CFTypeRef cf) {
 #define MESSAGE_TIMEOUT 100
 #if DEPLOYMENT_TARGET_MACOSX
 #define NOTIFICATION_PORT_NAME "com.apple.UNCUserNotification"
-#elif 0
+#elif DEPLOYMENT_TARGET_EMBEDDED
 #define NOTIFICATION_PORT_NAME "com.apple.SBUserNotification"
 #else
 #error Unknown or unspecified DEPLOYMENT_TARGET
@@ -206,14 +208,15 @@ static SInt32 _CFUserNotificationSendRequest(CFAllocatorRef allocator, CFStringR
     mach_port_t bootstrapPort = MACH_PORT_NULL, serverPort = MACH_PORT_NULL;
     CFIndex size;
     char namebuffer[MAX_PORT_NAME_LENGTH + 1];
+    
     strlcpy(namebuffer, NOTIFICATION_PORT_NAME, sizeof(namebuffer));
     if (sessionID) {
-       char sessionid[MAX_PORT_NAME_LENGTH + 1];
-       CFIndex len = MAX_PORT_NAME_LENGTH - sizeof(NOTIFICATION_PORT_NAME) - sizeof(NOTIFICATION_PORT_NAME_SUFFIX);
+        char sessionid[MAX_PORT_NAME_LENGTH + 1];
+        CFIndex len = MAX_PORT_NAME_LENGTH - sizeof(NOTIFICATION_PORT_NAME) - sizeof(NOTIFICATION_PORT_NAME_SUFFIX);
         CFStringGetBytes(sessionID, CFRangeMake(0, CFStringGetLength(sessionID)), kCFStringEncodingUTF8, 0, false, (uint8_t *)sessionid, len, &size);
-       sessionid[len - 1] = '\0';
-       strlcat(namebuffer, NOTIFICATION_PORT_NAME_SUFFIX, sizeof(namebuffer));
-       strlcat(namebuffer, sessionid, sizeof(namebuffer));
+        sessionid[len - 1] = '\0';
+        strlcat(namebuffer, NOTIFICATION_PORT_NAME_SUFFIX, sizeof(namebuffer));
+        strlcat(namebuffer, sessionid, sizeof(namebuffer));
     }
 
     retval = task_get_bootstrap_port(mach_task_self(), &bootstrapPort);
@@ -258,12 +261,11 @@ CFUserNotificationRef CFUserNotificationCreate(CFAllocatorRef allocator, CFTimeI
     CFUserNotificationRef userNotification = NULL;
     SInt32 retval = ERR_SUCCESS;
     static uint16_t tokenCounter = 0;
-    SInt32 token = ((getpid()<<16) | (tokenCounter++));
+    SInt32 token = ((getpid() << 16) | (tokenCounter++));
     CFStringRef sessionID = (dictionary ? CFDictionaryGetValue(dictionary, kCFUserNotificationSessionIDKey) : NULL);
     mach_port_t replyPort = MACH_PORT_NULL;
 
     if (!allocator) allocator = __CFGetDefaultAllocator();
-
     retval = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &replyPort);
     if (ERR_SUCCESS == retval && MACH_PORT_NULL != replyPort) retval = _CFUserNotificationSendRequest(allocator, sessionID, replyPort, token, timeout, flags, dictionary);
     if (ERR_SUCCESS == retval) {
@@ -319,7 +321,7 @@ SInt32 CFUserNotificationReceiveResponse(CFUserNotificationRef userNotification,
     
     if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) {
         msg = (mach_msg_base_t *)CFAllocatorAllocate(CFGetAllocator(userNotification), size, 0);
-       if (__CFOASafe) __CFSetLastAllocationEventName(msg, "CFUserNotification (temp)");
+        if (__CFOASafe) __CFSetLastAllocationEventName(msg, "CFUserNotification (temp)");
         if (msg) {
             memset(msg, 0, size);
             msg->header.msgh_size = size;
@@ -360,13 +362,9 @@ CFStringRef CFUserNotificationGetResponseValue(CFUserNotificationRef userNotific
     if (userNotification && userNotification->_responseDictionary) {
         value = CFDictionaryGetValue(userNotification->_responseDictionary, key);
         if (CFGetTypeID(value) == CFStringGetTypeID()) {
-            if (0 == idx) {
-                retval = (CFStringRef)value;
-            }
+            if (0 == idx) retval = (CFStringRef)value;
         } else if (CFGetTypeID(value) == CFArrayGetTypeID()) {
-            if (0 <= idx && idx < CFArrayGetCount((CFArrayRef)value)) {
-                retval = (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)value, idx);
-            }
+            if (0 <= idx && idx < CFArrayGetCount((CFArrayRef)value)) retval = (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)value, idx);
         }
     }
     return retval;
@@ -380,18 +378,14 @@ CFDictionaryRef CFUserNotificationGetResponseDictionary(CFUserNotificationRef us
 SInt32 CFUserNotificationUpdate(CFUserNotificationRef userNotification, CFTimeInterval timeout, CFOptionFlags flags, CFDictionaryRef dictionary) {
     CHECK_FOR_FORK();
     SInt32 retval = ERR_SUCCESS;
-    if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) {
-        retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, userNotification->_replyPort, userNotification->_token, timeout, flags|kCFUserNotificationUpdateFlag, dictionary);
-    }
+    if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, userNotification->_replyPort, userNotification->_token, timeout, flags|kCFUserNotificationUpdateFlag, dictionary);
     return retval;
 }
 
 SInt32 CFUserNotificationCancel(CFUserNotificationRef userNotification) {
     CHECK_FOR_FORK();
     SInt32 retval = ERR_SUCCESS;
-    if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) {
-        retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, userNotification->_replyPort, userNotification->_token, 0, kCFUserNotificationCancelFlag, NULL);
-    }
+    if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, userNotification->_replyPort, userNotification->_token, 0, kCFUserNotificationCancelFlag, NULL);
     return retval;
 }
 
@@ -400,7 +394,7 @@ CFRunLoopSourceRef CFUserNotificationCreateRunLoopSource(CFAllocatorRef allocato
     CFRunLoopSourceRef source = NULL;
     if (userNotification && callout && !userNotification->_machPort && MACH_PORT_NULL != userNotification->_replyPort) {
         CFMachPortContext context = {0, userNotification, NULL, NULL, NULL};
-        userNotification->_machPort = CFMachPortCreateWithPort(CFGetAllocator(userNotification), (mach_port_t)userNotification->_replyPort, _CFUserNotificationMachPortCallBack, &context, false);
+        userNotification->_machPort = CFMachPortCreateWithPort(CFGetAllocator(userNotification), (mach_port_t)userNotification->_replyPort, _CFUserNotificationMachPortCallBack, &context, NULL);
     }
     if (userNotification && userNotification->_machPort) {
         source = CFMachPortCreateRunLoopSource(allocator, userNotification->_machPort, order);
index e3a8d552862880ac85e306d8cfd4698acfd71bc4..aac876cc4bb2e2a11dce68bdbacb9a94c4c88323 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUserNotification.h
-       Copyright (c) 2000-2007, Apple Inc.  All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc.  All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFUSERNOTIFICATION__)
@@ -135,12 +135,12 @@ enum {
 };
 
 enum {
-    kCFUserNotificationNoDefaultButtonFlag     = (1 << 5),
-    kCFUserNotificationUseRadioButtonsFlag     = (1 << 6)
+    kCFUserNotificationNoDefaultButtonFlag     = (1UL << 5),
+    kCFUserNotificationUseRadioButtonsFlag     = (1UL << 6)
 };
 
-CF_INLINE CFOptionFlags CFUserNotificationCheckBoxChecked(CFIndex i) {return ((CFOptionFlags)(1 << (8 + i)));}
-CF_INLINE CFOptionFlags CFUserNotificationSecureTextField(CFIndex i) {return ((CFOptionFlags)(1 << (16 + i)));}
+CF_INLINE CFOptionFlags CFUserNotificationCheckBoxChecked(CFIndex i) {return ((CFOptionFlags)(1UL << (8 + i)));}
+CF_INLINE CFOptionFlags CFUserNotificationSecureTextField(CFIndex i) {return ((CFOptionFlags)(1UL << (16 + i)));}
 CF_INLINE CFOptionFlags CFUserNotificationPopUpSelection(CFIndex n) {return ((CFOptionFlags)(n << 24));}
 
 
@@ -190,6 +190,14 @@ CF_EXPORT
 const CFStringRef kCFUserNotificationPopUpSelectionKey AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
 #endif
 
+#if (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+CF_EXPORT
+const CFStringRef kCFUserNotificationAlertTopMostKey;
+        
+CF_EXPORT
+const CFStringRef kCFUserNotificationKeyboardTypesKey;
+#endif
+
 CF_EXTERN_C_END
 
 #endif /* ! __COREFOUNDATION_CFUSERNOTIFICATION__ */
index 5131e68a3973d70626f4a00f9d3e2348f7ff7c8f..3c6a7f51930cee9a707a2e0107b83d312cc5e168 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFUtilities.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
-#include "CFPriv.h"
+#include <CoreFoundation/CFPriv.h>
 #include "CFInternal.h"
-#include "CFPriv.h"
+#include "CFLocaleInternal.h"
+#include <CoreFoundation/CFPriv.h>
 #include <CoreFoundation/CFBundle.h>
 #include <CoreFoundation/CFURLAccess.h>
 #include <CoreFoundation/CFPropertyList.h>
 #include <CoreFoundation/CFTimeZone.h>
 #include <CoreFoundation/CFCalendar.h>
-#if (DEPLOYMENT_TARGET_MACOSX) 
-#include <CoreFoundation/CFLogUtilities.h>
-#include <asl.h>
-#include <sys/uio.h>
-#endif
 #include <math.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
-#if DEPLOYMENT_TARGET_MACOSX
-    #include <mach/mach.h>
-    #include <pthread.h>
-    #include <mach-o/loader.h>
-    #include <mach-o/dyld.h>
-    #include <crt_externs.h>
-    #include <dlfcn.h>
-    #include <vproc.h>
-    #include <vproc_priv.h>
-    #include <sys/stat.h>
+#include <asl.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <unistd.h>
+#include <sys/uio.h>
+#include <mach/mach.h>
+#include <pthread.h>
+#include <mach-o/loader.h>
+#include <mach-o/dyld.h>
+#include <crt_externs.h>
+#include <dlfcn.h>
+#include <vproc.h>
+#include <vproc_priv.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
 #include <mach/mach.h>
 #include <mach/mach_vm.h>
+#include <sys/mman.h>
 #include <stdio.h>
+#include <sys/errno.h>
+#include <mach/mach_time.h>
+#include <libkern/OSAtomic.h>
+#include <Block.h>
 #endif
 #if DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
     #include <string.h>
     #include <pthread.h>
 #endif
 
-
 /* Comparator is passed the address of the values. */
 /* Binary searches a sorted-increasing array of some type.
    Return value is either 1) the index of the element desired,
@@ -129,7 +132,7 @@ CFHashCode CFHashBytes(uint8_t *bytes, CFIndex length) {
 #undef ELF_STEP
 
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 __private_extern__ uintptr_t __CFFindPointer(uintptr_t ptr, uintptr_t start) {
     vm_map_t task = mach_task_self();
     mach_vm_address_t address = start;
@@ -157,9 +160,24 @@ __private_extern__ uintptr_t __CFFindPointer(uintptr_t ptr, uintptr_t start) {
 }
 #endif
 
+#if DEPLOYMENT_TARGET_WINDOWS
+struct _args {
+    void *func;
+    void *arg;
+    HANDLE handle;
+};
+static unsigned __stdcall __CFWinThreadFunc(void *arg) {
+    struct _args *args = (struct _args*)arg; 
+    ((void (*)(void *))args->func)(args->arg);
+    CloseHandle(args->handle);
+    CFAllocatorDeallocate(kCFAllocatorSystemDefault, arg);
+    _endthreadex(0);
+    return 0; 
+}
+#endif
 
 __private_extern__ void *__CFStartSimpleThread(void *func, void *arg) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
     pthread_attr_t attr;
     pthread_t tid = 0;
     pthread_attr_init(&attr);
@@ -171,7 +189,7 @@ __private_extern__ void *__CFStartSimpleThread(void *func, void *arg) {
     pthread_attr_destroy(&attr);
 //warning CF: we dont actually know that a pthread_t is the same size as void *
     return (void *)tid;
-#else
+#elif DEPLOYMENT_TARGET_WINDOWS
     unsigned tid;
     struct _args *args = (struct _args*)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(struct _args), 0);
     if (__CFOASafe) __CFSetLastAllocationEventName(args, "CFUtilities (thread-args)");
@@ -186,18 +204,11 @@ __private_extern__ void *__CFStartSimpleThread(void *func, void *arg) {
 #endif
 }
 
-__private_extern__ CFStringRef _CFCreateLimitedUniqueString() {
-    /* this unique string is only unique to the current host during the current boot */
-    uint64_t tsr = __CFReadTSR();
-    UInt32 tsrh = (UInt32)(tsr >> 32), tsrl = (UInt32)(tsr & (int64_t)0xFFFFFFFF);
-    return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFUniqueString-%lu%lu$"), tsrh, tsrl);
-}
-
 
 // Looks for localized version of "nonLocalized" in the SystemVersion bundle
 // If not found, and returnNonLocalizedFlag == true, will return the non localized string (retained of course), otherwise NULL
 // If bundlePtr != NULL, will use *bundlePtr and will return the bundle in there; otherwise bundle is created and released
-
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 static CFStringRef _CFCopyLocalizedVersionKey(CFBundleRef *bundlePtr, CFStringRef nonLocalized) {
     CFStringRef localized = NULL;
     CFBundleRef locBundle = bundlePtr ? *bundlePtr : NULL;
@@ -214,6 +225,7 @@ static CFStringRef _CFCopyLocalizedVersionKey(CFBundleRef *bundlePtr, CFStringRe
     }
     return localized ? localized : (CFStringRef)CFRetain(nonLocalized);
 }
+#endif
 
 static CFDictionaryRef _CFCopyVersionDictionary(CFStringRef path) {
     CFPropertyListRef plist = NULL;
@@ -228,7 +240,7 @@ static CFDictionaryRef _CFCopyVersionDictionary(CFStringRef path) {
     if (url) CFRelease(url);
     
     if (plist) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
        CFBundleRef locBundle = NULL;
        CFStringRef fullVersion, vers, versExtra, build;
        CFStringRef versionString = _CFCopyLocalizedVersionKey(&locBundle, _kCFSystemVersionProductVersionStringKey);
@@ -260,12 +272,12 @@ static CFDictionaryRef _CFCopyVersionDictionary(CFStringRef path) {
     return (CFDictionaryRef)plist;
 }
 
-#if defined (__MACH__) || 0
 CFStringRef CFCopySystemVersionString(void) {
     CFStringRef versionString;
     CFDictionaryRef dict = _CFCopyServerVersionDictionary();
     if (!dict) dict = _CFCopySystemVersionDictionary();
-    versionString = CFDictionaryGetValue(dict, CFSTR("FullVersionString"));
+    if (!dict) return NULL;
+    versionString = (CFStringRef)CFDictionaryGetValue(dict, CFSTR("FullVersionString"));
     if (versionString) CFRetain(versionString);
     CFRelease(dict);
     return versionString;
@@ -280,13 +292,13 @@ CFStringRef CFCopySystemVersionString(void) {
 CFDictionaryRef _CFCopySystemVersionDictionary(void) {
     CFPropertyListRef plist = NULL;
        plist = _CFCopyVersionDictionary(CFSTR("/System/Library/CoreServices/SystemVersion.plist"));
-    return plist;
+    return (CFDictionaryRef)plist;
 }
 
 CFDictionaryRef _CFCopyServerVersionDictionary(void) {
     CFPropertyListRef plist = NULL;
        plist = _CFCopyVersionDictionary(CFSTR("/System/Library/CoreServices/ServerVersion.plist"));
-    return plist;
+    return (CFDictionaryRef)plist;
 }
 
 CONST_STRING_DECL(_kCFSystemVersionProductNameKey, "ProductName")
@@ -297,22 +309,187 @@ CONST_STRING_DECL(_kCFSystemVersionProductUserVisibleVersionKey, "ProductUserVis
 CONST_STRING_DECL(_kCFSystemVersionBuildVersionKey, "ProductBuildVersion")
 CONST_STRING_DECL(_kCFSystemVersionProductVersionStringKey, "Version")
 CONST_STRING_DECL(_kCFSystemVersionBuildStringKey, "Build")
-#endif //__MACH__
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || TARGET_IPHONE_SIMULATOR
+
+typedef struct {
+    uint16_t    primaryVersion;
+    uint8_t     secondaryVersion;
+    uint8_t     tertiaryVersion;
+} CFLibraryVersion;
+
+CFLibraryVersion CFGetExecutableLinkedLibraryVersion(CFStringRef libraryName) {
+    CFLibraryVersion ret = {0xFFFF, 0xFF, 0xFF};
+    char library[CFMaxPathSize];       // search specs larger than this are pointless
+    if (!CFStringGetCString(libraryName, library, sizeof(library), kCFStringEncodingUTF8)) return ret;
+    int32_t version = NSVersionOfLinkTimeLibrary(library);
+    if (-1 != version) {
+       ret.primaryVersion = version >> 16;
+       ret.secondaryVersion = (version >> 8) & 0xff;
+       ret.tertiaryVersion = version & 0xff;
+    }
+    return ret;
+}
+
+CFLibraryVersion CFGetExecutingLibraryVersion(CFStringRef libraryName) {
+    CFLibraryVersion ret = {0xFFFF, 0xFF, 0xFF};
+    char library[CFMaxPathSize];       // search specs larger than this are pointless
+    if (!CFStringGetCString(libraryName, library, sizeof(library), kCFStringEncodingUTF8)) return ret;
+    int32_t version = NSVersionOfRunTimeLibrary(library);
+    if (-1 != version) {
+       ret.primaryVersion = version >> 16;
+       ret.secondaryVersion = (version >> 8) & 0xff;
+       ret.tertiaryVersion = version & 0xff;
+    }
+    return ret;
+}
+
+static inline Boolean _CFLibraryVersionLessThan(CFLibraryVersion vers1, CFLibraryVersion vers2) {
+    if (vers1.primaryVersion < vers2.primaryVersion) {
+       return true;
+    } else if (vers1.primaryVersion == vers2.primaryVersion) {
+       if (vers1.secondaryVersion < vers2.secondaryVersion) {
+           return true;
+       } else if (vers1.secondaryVersion == vers2.secondaryVersion) {
+           return vers1.tertiaryVersion < vers2.tertiaryVersion;
+       }
+    }
+    return false;
+}
+
+/*
+If
+   (vers != 0xFFFF): We know the version number of the library this app was linked against
+   and (versionInfo[version].VERSIONFIELD != 0xFFFF): And we know what version number started the specified release
+   and ((version == 0) || (versionInfo[version-1].VERSIONFIELD < versionInfo[version].VERSIONFIELD)): And it's distinct from the prev release
+Then
+   If the version the app is linked against is less than the version recorded for the specified release
+   Then stop checking and return false
+   Else stop checking and return YES
+Else
+   Continue checking (the next library)
+*/
+
+#define resultIndex(VERSION) (VERSION)
+
+#define checkLibrary(LIBNAME, VERSIONFIELD) { \
+    uint16_t vers = (NSVersionOfLinkTimeLibrary(LIBNAME) >> 16); \
+    if ((vers != 0xFFFF) && (versionInfo[version].VERSIONFIELD != 0xFFFF) && \
+        ((version == 0) || (versionInfo[version-1].VERSIONFIELD < versionInfo[version].VERSIONFIELD))) \
+        return (results[resultIndex(version)] = ((vers < versionInfo[version].VERSIONFIELD) ? false : true)); \
+}
+
 
+CF_EXPORT Boolean _CFExecutableLinkedOnOrAfter(CFSystemVersion version) {
+    // The numbers in the below tables should be the numbers for any version of the framework in the release.
+    // When adding new entries to these tables for a new build train, it's simplest to use the versions of the
+    // first new versions of projects submitted to the new train. These can later be updated. One thing to watch for is that software updates
+    // for the previous release do not increase numbers beyond the number used for the next release!
+    // For a given train, don't ever use the last versions submitted to the previous train! (This to assure room for software updates.)
+    // If versions are the same as previous release, use 0xFFFF; this will assure the answer is a conservative NO.
+    // NOTE: Also update the CFM check below, perhaps to the previous release... (???)
+    static const struct {
+        uint16_t libSystemVersion;
+        uint16_t cocoaVersion;
+        uint16_t appkitVersion;
+        uint16_t fouVersion;
+        uint16_t cfVersion;
+        uint16_t carbonVersion;
+        uint16_t applicationServicesVersion;
+        uint16_t coreServicesVersion;
+        uint16_t iokitVersion;
+    } versionInfo[] = {
+       {50, 5, 577, 397, 196, 113, 16, 9, 52},         /* CFSystemVersionCheetah (used the last versions) */
+       {55, 7, 620, 425, 226, 122, 16, 10, 67},        /* CFSystemVersionPuma (used the last versions) */
+        {56, 8, 631, 431, 232, 122, 17, 11, 73},       /* CFSystemVersionJaguar */
+        {67, 9, 704, 481, 281, 126, 19, 16, 159},      /* CFSystemVersionPanther */
+        {73, 10, 750, 505, 305, 128, 22, 18, 271},     /* CFSystemVersionTiger */
+        {89, 12, 840, 575, 375, 136, 34, 32, 0xFFFF},                  /* CFSystemVersionLeopard */
+        {112, 13, 960, 680, 480, 0xFFFF, 0xFFFF, 33, 0xFFFF},  /* CFSystemVersionSnowLeopard */
+    };
+    
+    
+    // !!! When a new release is added to the array, don't forget to bump the size of this array!
+    static char results[CFSystemVersionMax] = {-2, -2, -2, -2, -2, -2};        /* We cache the results per-release; there are only a few of these... */
+    if (version >= CFSystemVersionMax) return false;   /* Actually, we don't know the answer, and something scary is going on */
+    
+    int versionIndex = resultIndex(version);
+    if (results[versionIndex] != -2) return results[versionIndex];
+
+#if DEPLOYMENT_TARGET_MACOSX
+    if (_CFIsCFM()) {
+        results[versionIndex] = (version <= CFSystemVersionJaguar) ? true : false;
+        return results[versionIndex];
+    }
+#endif
+    
+    // Do a sanity check, since sometimes System framework is screwed up, which confuses everything. 
+    // If the currently executing System framework has a version less than that of Leopard, warn.
+    static Boolean called = false;
+    if (!called) {     // We do a check here in case CFLog() recursively calls this function.
+       called = true;
+       int32_t vers = NSVersionOfRunTimeLibrary("System");
+       if ((vers != -1) && (((unsigned int)vers) >> 16) < 89) {    // 89 is the version of libSystem for first version of Leopard
+           CFLog(__kCFLogAssertion, CFSTR("System.framework version (%x) is wrong, this will break CF and up"), vers);
+       }
+       if (results[versionIndex] != -2) return results[versionIndex];  // If there was a recursive call that figured this out, return
+    }
+    
+#if DEPLOYMENT_TARGET_MACOSX
+    if (version < CFSystemVersionMax) {
+       // Compare the linked library versions of a Mac OS X app to framework versions found on Mac OS X.
+       checkLibrary("System", libSystemVersion);       // Pretty much everyone links with this
+       checkLibrary("Cocoa", cocoaVersion);
+       checkLibrary("AppKit", appkitVersion);
+       checkLibrary("Foundation", fouVersion);
+       checkLibrary("CoreFoundation", cfVersion);
+       checkLibrary("Carbon", carbonVersion);
+       checkLibrary("ApplicationServices", applicationServicesVersion);
+       checkLibrary("CoreServices", coreServicesVersion);
+       checkLibrary("IOKit", iokitVersion);
+    } else {
+    }
+#else 
+#endif
+    
+    /* If not found, then simply return NO to indicate earlier --- compatibility by default, unfortunately */
+    return false;
+}
+#else
 CF_EXPORT Boolean _CFExecutableLinkedOnOrAfter(CFSystemVersion version) {
     return true;
 }
+#endif
+
 
 #if DEPLOYMENT_TARGET_MACOSX
+__private_extern__ void *__CFLookupCarbonCoreFunction(const char *name) {
+    static void *image = NULL;
+    if (NULL == image) {
+       image = dlopen("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore", RTLD_LAZY | RTLD_LOCAL);
+    }
+    void *dyfunc = NULL;
+    if (image) {
+       dyfunc = dlsym(image, name);
+    }
+    return dyfunc;
+}
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 __private_extern__ void *__CFLookupCFNetworkFunction(const char *name) {
     static void *image = NULL;
     if (NULL == image) {
        const char *path = NULL;
        if (!issetugid()) {
-           path = getenv("CFNETWORK_LIBRARY_PATH");
+           path = __CFgetenv("CFNETWORK_LIBRARY_PATH");
        }
        if (!path) {
+#if DEPLOYMENT_TARGET_MACOSX
            path = "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/Versions/A/CFNetwork";
+#else
+           path = "/System/Library/Frameworks/CFNetwork.framework/CFNetwork";
+#endif
        }
        image = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
     }
@@ -322,7 +499,7 @@ __private_extern__ void *__CFLookupCFNetworkFunction(const char *name) {
     }
     return dyfunc;
 }
-#endif //__MACH__
+#endif
 
 
 #ifndef __CFGetSessionID_defined
@@ -333,6 +510,29 @@ __private_extern__ uint32_t __CFGetSessionID(void) {
 
 #endif
 
+__private_extern__ CFIndex __CFActiveProcessorCount() {
+    int32_t pcnt;
+#if DEPLOYMENT_TARGET_WINDOWS
+    SYSTEM_INFO sysInfo;
+    GetSystemInfo(&sysInfo);
+    DWORD_PTR activeProcessorMask = sysInfo.dwActiveProcessorMask;
+    // assumes sizeof(DWORD_PTR) is 64 bits or less
+    uint64_t v = activeProcessorMask;
+    v = v - ((v >> 1) & 0x5555555555555555ULL);
+    v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
+    v = (v + (v >> 4)) & 0xf0f0f0f0f0f0f0fULL;
+    pcnt = (v * 0x0101010101010101ULL) >> ((sizeof(v) - 1) * 8);
+#else
+    int32_t mib[] = {CTL_HW, HW_AVAILCPU};
+    size_t len = sizeof(pcnt);
+    int32_t result = sysctl(mib, sizeof(mib) / sizeof(int32_t), &pcnt, &len, NULL, 0);
+    if (result != 0) {
+        pcnt = 0;
+    }
+#endif
+    return pcnt;
+}
+
 const char *_CFPrintForDebugger(const void *obj) {
        static char *result = NULL;
        CFStringRef str;
@@ -387,20 +587,31 @@ static void _CFShowToFile(FILE *file, Boolean flush, const void *obj) {
      // iTunes used OutputDebugStringW(theString);
 
      CFStringInitInlineBuffer(str, &buffer, CFRangeMake(0, cnt));
-#if defined (__WIN32__)
-    TCHAR *accumulatedBuffer = (TCHAR *)malloc((cnt+1) * sizeof(TCHAR));
+#if DEPLOYMENT_TARGET_WINDOWS
+    wchar_t *accumulatedBuffer = (wchar_t *)malloc((cnt+1) * sizeof(wchar_t));
 #endif
      for (idx = 0; idx < cnt; idx++) {
          UniChar ch = __CFStringGetCharacterFromInlineBufferQuick(&buffer, idx);
+#if DEPLOYMENT_TARGET_WINDOWS
+         if (file == stderr || file == stdout) {
+             accumulatedBuffer[idx] = ch;
+                lastNL = (ch == L'\n');
+             if (idx == (cnt - 1)) {
+                accumulatedBuffer[idx+1] = L'\0'; 
+                OutputDebugStringW(accumulatedBuffer);
+                free(accumulatedBuffer);
+             }
+         } else {
+#endif
 
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
                 if (ch < 128) {
              fprintf_l(file, NULL, "%c", ch);
             lastNL = (ch == '\n');
          } else {
              fprintf_l(file, NULL, "\\u%04x", ch);
          }
-#elif defined (__WIN32__)
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
                 if (ch < 128) {
              _fprintf_l(file, "%c", NULL, ch);
             lastNL = (ch == '\n');
@@ -409,12 +620,23 @@ static void _CFShowToFile(FILE *file, Boolean flush, const void *obj) {
          }
 #endif
      }
-#if  defined(__WIN32__)
+#if  DEPLOYMENT_TARGET_WINDOWS
      }
 #endif
      if (!lastNL) {
-#if DEPLOYMENT_TARGET_MACOSX
+#if DEPLOYMENT_TARGET_WINDOWS
+         if (file == stderr || file == stdout) {
+             char outStr[2];
+             outStr[0] = '\n';
+             outStr[1] = '\0';
+             OutputDebugStringA(outStr);
+         } else {
+                _fprintf_l(file, "\n", NULL);
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
          fprintf_l(file, NULL, "\n");
+#endif
+#if DEPLOYMENT_TARGET_WINDOWS
+         }
 #endif
          if (flush) fflush(file);
      }
@@ -427,27 +649,402 @@ void CFShow(const void *obj) {
 }
 
 
+// message must be a UTF8-encoded, null-terminated, byte buffer with at least length bytes
+typedef void (*CFLogFunc)(int32_t lev, const char *message, size_t length, char withBanner);
+
+static Boolean also_do_stderr() {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    if (!issetugid() && __CFgetenv("CFLOG_FORCE_STDERR")) {
+       return true;
+    }
+    struct stat sb;
+    int ret = fstat(STDERR_FILENO, &sb);
+    if (ret < 0) return false;
+    mode_t m = sb.st_mode & S_IFMT;
+    if (S_IFREG == m || S_IFSOCK == m) return true;
+    if (!(S_IFIFO == m || S_IFCHR == m)) return false; // disallow any whacky stuff
+    // if it could be a pipe back to launchd, fail
+    int64_t val = 0;
+    // assumes val is not written to on error
+    vproc_swap_integer(NULL, VPROC_GSK_IS_MANAGED, NULL, &val);
+    if (val) return false;
+#endif
+    return true;
+}
+
+static void __CFLogCString(int32_t lev, const char *message, size_t length, char withBanner) {
+    char *banner = NULL;
+    char *time = NULL;
+    char *thread = NULL;
+    char *uid = NULL;
+#if !(DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
+    int bannerLen = 0;
+#endif
+    if (withBanner) {
+       CFAbsoluteTime at = CFAbsoluteTimeGetCurrent();
+       CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFCalendarIdentifierGregorian);
+       if (!calendar) goto after_banner;
+       CFTimeZoneRef tz = CFTimeZoneCopySystem();
+       if (!tz) {
+           CFRelease(calendar);
+           goto after_banner;
+       }
+       CFCalendarSetTimeZone(calendar, tz);
+       CFRelease(tz);
+       int32_t year, month, day, hour, minute, second;
+       Boolean dec = CFCalendarDecomposeAbsoluteTime(calendar, at, "yMdHms", &year, &month, &day, &hour, &minute, &second);
+       CFRelease(calendar);
+       if (!dec) goto after_banner;
+       double atf;
+       int32_t ms = (int32_t)floor(1000.0 * modf(at, &atf));
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+        asprintf(&banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year, month, day, hour, minute, second, ms, *_CFGetProgname(), getpid(), pthread_mach_thread_np(pthread_self()));
+       asprintf(&thread, "%x", pthread_mach_thread_np(pthread_self()));
+#else
+       bannerLen = asprintf(&banner, "%04d-%02d-%02d %02d:%02d:%02d.%03d %s[%d:%x] ", year, month, day, hour, minute, second, ms, *_CFGetProgname(), getpid(), GetCurrentThreadId());
+       asprintf(&thread, "%x", GetCurrentThreadId());
+#endif
+       asprintf(&time, "%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, minute, second, ms);
+
+    }
+    after_banner:;
+    asprintf(&uid, "%d", geteuid());
+    aslclient asl = asl_open(NULL, "com.apple.console", ASL_OPT_NO_DELAY);
+    aslmsg msg = asl_new(ASL_TYPE_MSG);
+    asl_set(msg, "CFLog Local Time", time); // not to be documented, not public API
+    asl_set(msg, "CFLog Thread", thread);   // not to be documented, not public API
+    asl_set(msg, "ReadUID", uid);
+    static const char *levstr[] = {"0", "1", "2", "3", "4", "5", "6", "7"};
+    asl_set(msg, ASL_KEY_LEVEL, levstr[lev]);
+    asl_set(msg, ASL_KEY_MSG, message);
+    asl_send(asl, msg);
+    asl_free(msg);
+    asl_close(asl);
+
+    if (also_do_stderr()) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+       struct iovec v[3];
+       v[0].iov_base = banner;
+       v[0].iov_len = banner ? strlen(banner) : 0;
+       v[1].iov_base = (char *)message;
+       v[1].iov_len = length;
+       v[2].iov_base = "\n";
+       v[2].iov_len = (message[length - 1] != '\n') ? 1 : 0;
+       int nv = (v[0].iov_base ? 1 : 0) + 1 + (v[2].iov_len ? 1 : 0);
+       static CFSpinLock_t lock = CFSpinLockInit;
+       __CFSpinLock(&lock);
+       writev(STDERR_FILENO, v[0].iov_base ? v : v + 1, nv);
+       __CFSpinUnlock(&lock);
+#else
+        size_t bufLen = bannerLen + length + 1;
+        char *buf = (char *)malloc(sizeof(char) * bufLen);
+        if (banner) {
+            // Copy the banner into the debug string
+            memmove_s(buf, bufLen, banner, bannerLen);
+            
+            // Copy the message into the debug string
+            strcpy_s(buf + bannerLen, bufLen - bannerLen, message);
+        } else {
+            strcpy_s(buf, bufLen, message);
+        }
+        buf[bufLen - 1] = '\0';
+       fprintf_s(stderr, "%s\n", buf);
+       // This Win32 API call only prints when a debugger is active
+       // OutputDebugStringA(buf);
+        free(buf);
+#endif
+    }
+    
+    if (thread) free(thread);
+    if (time) free(time);
+    if (banner) free(banner);
+    if (uid) free(uid);
+}
+
+CF_EXPORT void _CFLogvEx(CFLogFunc logit, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, int32_t lev, CFStringRef format, va_list args) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    if (pthread_getspecific(__CFTSDKeyIsInCFLog)) return;
+    pthread_setspecific(__CFTSDKeyIsInCFLog, (void *)1);
+#endif
+    CFStringRef str = format ? _CFStringCreateWithFormatAndArgumentsAux(kCFAllocatorSystemDefault, copyDescFunc, formatOptions, (CFStringRef)format, args) : 0;
+    CFIndex blen = str ? CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1 : 0;
+    char *buf = str ? (char *)malloc(blen) : 0;
+    if (str && buf) {
+       Boolean converted = CFStringGetCString(str, buf, blen, kCFStringEncodingUTF8);
+       size_t len = strlen(buf);
+       // silently ignore 0-length or really large messages, and levels outside the valid range
+       if (converted && !(len <= 0 || (1 << 24) < len) && !(lev < ASL_LEVEL_EMERG || ASL_LEVEL_DEBUG < lev)) {
+           (logit ? logit : __CFLogCString)(lev, buf, len, 1);
+       }
+    }
+    if (buf) free(buf);
+    if (str) CFRelease(str);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+    pthread_setspecific(__CFTSDKeyIsInCFLog, 0);
+#endif
+}
 
 void CFLog(int32_t lev, CFStringRef format, ...) {
-    CFStringRef result;
-    va_list argList;
-    static CFSpinLock_t lock = CFSpinLockInit;
+    va_list args;
+    va_start(args, format); 
+    _CFLogvEx(NULL, NULL, NULL, lev, format, args);
+    va_end(args);
+}
+
 
-    va_start(argList, format);
-    result = CFStringCreateWithFormatAndArguments(kCFAllocatorSystemDefault, NULL, format, argList);
-    va_end(argList);
 
-    __CFSpinLock(&lock); 
-    CFTimeZoneRef tz = CFTimeZoneCopySystem(); // specifically choose system time zone for logs
-    CFGregorianDate gdate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), tz);
-    CFRelease(tz);
-    gdate.second = gdate.second + 0.0005;
-    // Date format: YYYY '-' MM '-' DD ' ' hh ':' mm ':' ss.fff
-    fprintf_l(stderr, NULL, "%04d-%02d-%02d %02d:%02d:%06.3f %s[%d:%x] CFLog: ", (int)gdate.year, gdate.month, gdate.day, gdate.hour, gdate.minute, gdate.second, *_CFGetProgname(), getpid(), pthread_mach_thread_np(pthread_self()));
-    CFShow(result);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 
-    __CFSpinUnlock(&lock); 
-    CFRelease(result);
+kern_return_t _CFDiscorporateMemoryAllocate(CFDiscorporateMemory *hm, size_t size, bool purgeable) {
+    kern_return_t ret = KERN_SUCCESS;
+    size = round_page(size);
+    if (0 == size) size = vm_page_size;
+    memset(hm, 0, sizeof(CFDiscorporateMemory));
+    void *addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, VM_MAKE_TAG(0) | (purgeable ? VM_FLAGS_PURGABLE : 0), 0);
+    if ((uintptr_t)addr == -1) {
+        ret = KERN_NO_SPACE;
+    }
+    if (KERN_SUCCESS == ret) {
+        hm->address = (mach_vm_address_t)(uintptr_t)addr;
+        hm->size = (mach_vm_size_t)size;
+        hm->port = MACH_PORT_NULL;
+        hm->corporeal = true;
+        hm->purgeable = purgeable;
+    }
+    if (KERN_SUCCESS == ret) ret = mach_make_memory_entry_64(mach_task_self(), &hm->size, hm->address, VM_PROT_DEFAULT, &hm->port, MACH_PORT_NULL);
+    if (KERN_SUCCESS == ret) hm->corporeal = true;
+    return ret;
 }
 
+kern_return_t _CFDiscorporateMemoryDeallocate(CFDiscorporateMemory *hm) {
+    kern_return_t ret1 = KERN_SUCCESS, ret2 = KERN_SUCCESS;
+    if (hm->corporeal) ret1 = mach_vm_deallocate(mach_task_self(), hm->address, hm->size);
+    hm->address = MACH_VM_MIN_ADDRESS;
+    hm->corporeal = false;
+    ret2 = mach_port_deallocate(mach_task_self(), hm->port);
+    hm->port = MACH_PORT_NULL;
+    return ret1 != KERN_SUCCESS ? ret1 : ret2;
+}
+
+kern_return_t _CFDiscorporateMemoryDematerialize(CFDiscorporateMemory *hm) {
+    kern_return_t ret = KERN_SUCCESS;
+    if (!hm->corporeal) ret = KERN_INVALID_MEMORY_CONTROL;
+    int state = VM_PURGABLE_VOLATILE;
+    if (KERN_SUCCESS == ret) vm_purgable_control(mach_task_self(), (vm_address_t)hm->address, VM_PURGABLE_SET_STATE, &state);
+    if (KERN_SUCCESS == ret) ret = mach_vm_deallocate(mach_task_self(), hm->address, hm->size);
+    if (KERN_SUCCESS == ret) hm->address = MACH_VM_MIN_ADDRESS;
+    if (KERN_SUCCESS == ret) hm->corporeal = false;
+    return ret;
+}
+
+kern_return_t _CFDiscorporateMemoryMaterialize(CFDiscorporateMemory *hm) {
+    kern_return_t ret = KERN_SUCCESS;
+    if (hm->corporeal) ret = KERN_INVALID_MEMORY_CONTROL;
+    if (KERN_SUCCESS == ret) ret = mach_vm_map(mach_task_self(), &hm->address, hm->size, 0, VM_FLAGS_ANYWHERE, hm->port, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
+    if (KERN_SUCCESS == ret) hm->corporeal = true;
+    int state = VM_PURGABLE_NONVOLATILE;
+    if (KERN_SUCCESS == ret) ret = vm_purgable_control(mach_task_self(), (vm_address_t)hm->address, VM_PURGABLE_SET_STATE, &state);
+    if (KERN_SUCCESS == ret) if (VM_PURGABLE_EMPTY == state) ret = KERN_PROTECTION_FAILURE; // same as VM_PURGABLE_EMPTY
+    return ret;
+}
+
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX
+
+#define SUDDEN_TERMINATION_ENABLE_VPROC 1
+
+#if SUDDEN_TERMINATION_ENABLE_VPROC
+
+static CFSpinLock_t __CFProcessKillingLock = CFSpinLockInit;
+static CFIndex __CFProcessKillingDisablingCount = 1;
+static Boolean __CFProcessKillingWasTurnedOn = false;
+
+void _CFSuddenTerminationDisable(void) {
+    __CFSpinLock(&__CFProcessKillingLock);
+    __CFProcessKillingDisablingCount++;
+    _vproc_transaction_begin();
+    __CFSpinUnlock(&__CFProcessKillingLock);
+}
+
+void _CFSuddenTerminationEnable(void) {
+    // In our model the first call of _CFSuddenTerminationEnable() that does not balance a previous call of _CFSuddenTerminationDisable() actually enables sudden termination so we have to keep a count that's almost redundant with vproc's.
+    __CFSpinLock(&__CFProcessKillingLock);
+    __CFProcessKillingDisablingCount--;
+    if (__CFProcessKillingDisablingCount==0 && !__CFProcessKillingWasTurnedOn) {
+       int64_t transactionsAreToBeEnabled = 1;
+       int64_t transactionsWereAlreadyEnabled = 0;
+       vproc_err_t verr = vproc_swap_integer(NULL, VPROC_GSK_TRANSACTIONS_ENABLED, &transactionsAreToBeEnabled, &transactionsWereAlreadyEnabled);
+       if (!verr) {
+           if (!transactionsWereAlreadyEnabled) {
+               // We set __CFProcessKillingWasTurnedOn below regardless of success because there's no point in retrying.
+           } // else this process was launched by launchd with transactions already enabled because EnableTransactions was set to true in the launchd .plist file.
+       } // else this process was not launched by launchd and the fix for 6416724 is not in the build yet.
+       __CFProcessKillingWasTurnedOn = true;
+    } else {
+       // Mail seems to have sudden termination disabling/enabling imbalance bugs that make _vproc_transaction_end() kill the app but we don't want that to prevent our submission of the fix 6382488.
+       if (__CFProcessKillingDisablingCount>=0) {
+           _vproc_transaction_end();
+       } else {
+           CFLog(kCFLogLevelError, CFSTR("-[NSProcessInfo enableSuddenTermination] has been invoked more times than necessary to balance invocations of -[NSProcessInfo disableSuddenTermination]. Ignoring."));
+       }
+    }
+    __CFSpinUnlock(&__CFProcessKillingLock);
+}
+
+void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus) {
+    // This is for when the caller wants to try to exit quickly if possible but not automatically exit the process when it next becomes clean, because quitting might still be cancelled by the user.
+    __CFSpinLock(&__CFProcessKillingLock);
+    // Check _vproc_transaction_count() because other code in the process might go straight to the vproc APIs but also check __CFProcessKillingWasTurnedOn because  _vproc_transaction_count() can return 0 when transactions didn't even get enabled.
+    if (_vproc_transaction_count()==0 && __CFProcessKillingWasTurnedOn) {
+        _exit(exitStatus);
+    }
+    __CFSpinUnlock(&__CFProcessKillingLock);
+}
+
+void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus) {
+    // The user has had their final opportunity to cancel quitting. Exit as soon as the process is clean. Same carefulness as in _CFSuddenTerminationExitIfTerminationEnabled().
+    __CFSpinLock(&__CFProcessKillingLock);
+    if (__CFProcessKillingWasTurnedOn) {
+       _vproc_transaction_try_exit(exitStatus);
+    }
+    __CFSpinUnlock(&__CFProcessKillingLock);
+}
+
+size_t _CFSuddenTerminationDisablingCount(void) {
+    // Until sudden termination has been really enabled vproc's notion of the count is off by one but we can't just return __CFProcessKillingDisablingCount() because that doesn't take into account stuff that calls the vproc_transaction functions behind our back.
+    return _vproc_transaction_count() + (__CFProcessKillingWasTurnedOn ? 0 : 1);
+}
+
+#else
+
+#warning Building with vproc sudden termination API disabled.
+
+static CFSpinLock_t __CFProcessKillingLock = CFSpinLockInit;
+static size_t __CFProcessKillingDisablingCount = 1;
+static Boolean __CFProcessExitNextTimeKillingIsEnabled = false;
+static int32_t __CFProcessExitStatus = 0;
+static int __CFProcessIsKillableNotifyToken;
+static Boolean __CFProcessIsKillableNotifyTokenIsFigured = false;
+
+__private_extern__ void _CFSetSuddenTerminationEnabled(Boolean isEnabled) {
+    if (!__CFProcessIsKillableNotifyTokenIsFigured) {
+        char *notificationName = NULL;
+        asprintf(&notificationName, "com.apple.isKillable.%i", getpid());
+        uint32_t notifyResult = notify_register_check(notificationName, &__CFProcessIsKillableNotifyToken);
+        if (notifyResult != NOTIFY_STATUS_OK) {
+            CFLog(kCFLogLevelError, CFSTR("%s: notify_register_check() returned %i."), __PRETTY_FUNCTION__, notifyResult);
+        }
+        free(notificationName);
+        __CFProcessIsKillableNotifyTokenIsFigured = true;
+    }
+    uint32_t notifyResult = notify_set_state(__CFProcessIsKillableNotifyToken, isEnabled);
+    if (notifyResult != NOTIFY_STATUS_OK) {
+        CFLog(kCFLogLevelError, CFSTR("%s: notify_set_state() returned %i"), __PRETTY_FUNCTION__, notifyResult);
+    }
+}
+
+void _CFSuddenTerminationDisable(void) {
+    __CFSpinLock(&__CFProcessKillingLock);
+    if (__CFProcessKillingDisablingCount == 0) {
+        _CFSetSuddenTerminationEnabled(false);
+    }
+    __CFProcessKillingDisablingCount++;
+    __CFSpinUnlock(&__CFProcessKillingLock);
+}
+
+void _CFSuddenTerminationEnable(void) {
+    __CFSpinLock(&__CFProcessKillingLock);
+    __CFProcessKillingDisablingCount--;
+    if (__CFProcessKillingDisablingCount == 0) {
+        if (__CFProcessExitNextTimeKillingIsEnabled) {
+            _exit(__CFProcessExitStatus);
+        } else {
+            _CFSetSuddenTerminationEnabled(true);
+        }
+    }
+    __CFSpinUnlock(&__CFProcessKillingLock);
+}
+
+void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus) {
+    __CFSpinLock(&__CFProcessKillingLock);
+    if (__CFProcessKillingDisablingCount == 0) {
+        _exit(exitStatus);
+    }
+    __CFSpinUnlock(&__CFProcessKillingLock);
+}
+
+void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus) {
+    __CFSpinLock(&__CFProcessKillingLock);
+    if (__CFProcessKillingDisablingCount == 0) {
+        _exit(exitStatus);
+    } else {
+        __CFProcessExitNextTimeKillingIsEnabled = YES;
+        __CFProcessExitStatus = exitStatus;
+    }
+    __CFSpinUnlock(&__CFProcessKillingLock);
+}
+
+size_t _CFSuddenTerminationDisablingCount(void) {
+    return __CFProcessKillingDisablingCount;
+}
+
+#endif
+
+#endif
+
+#if 0
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+
+typedef void (^ThrottleTypeA)(void);           // allows calls per nanoseconds
+typedef void (^ThrottleTypeB)(uint64_t amt);   // allows amount per nanoseconds
+
+__private_extern__ ThrottleTypeA __CFCreateThrottleTypeA(uint16_t calls, uint64_t nanoseconds) {
+   struct mach_timebase_info info;
+   mach_timebase_info(&info);
+   uint64_t period = nanoseconds / info.numer * info.denom;
+
+   if (0 == calls || 0 == period) return NULL;
+
+   __block OSSpinLock b_lock = OS_SPINLOCK_INIT;
+   __block uint64_t b_values[calls];
+   __block uint64_t *b_oldest = b_values;
+   memset(b_values, 0, sizeof(b_values));
+
+   return Block_copy(^{
+               uint64_t curr_time = mach_absolute_time();
+               OSSpinLockLock(&b_lock);
+               uint64_t next_time = *b_oldest + period;
+               *b_oldest = (curr_time < next_time) ? next_time : curr_time;
+               b_oldest++;
+               if (b_values + calls <= b_oldest) b_oldest = b_values;
+               OSSpinLockUnlock(&b_lock);
+               if (curr_time < next_time) {
+                   mach_wait_until(next_time);
+               }
+           });
+}
+
+__private_extern__ ThrottleTypeB __CFCreateThrottleTypeB(uint64_t amount, uint64_t nanoseconds) {
+   struct mach_timebase_info info;
+   mach_timebase_info(&info);
+   uint64_t period = nanoseconds / info.numer * info.denom;
+
+   if (0 == amount || 0 == period) return NULL;
+
+   __block OSSpinLock b_lock = OS_SPINLOCK_INIT;
+   __block uint64_t b_sum = 0ULL;
+   __block uint16_t b_num_values = 8;
+   __block uint64_t *b_values = calloc(b_num_values, 2 * sizeof(uint64_t));
+   __block uint64_t *b_oldest = b_values;
+
+   return Block_copy(^(uint64_t amt){
+               OSSpinLockLock(&b_lock);
+// unimplemented
+               OSSpinLockUnlock(&b_lock);
+           });
+}
+
+#endif
+#endif
 
index d9154f677c1c0b99a753e0fee4d0e1e129ef7e54..7ebe03f962fdb005bebf6bd8cbe81a90426608b6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -20,5 +20,5 @@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
-const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation  PROJECT:CoreFoundation-476  SYSTEM:Darwin  DEVELOPER:unknown  BUILT:" __DATE__ " " __TIME__ "\n";
-const double kCFCoreFoundationVersionNumber = (double)476.17;
+const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation  PROJECT:CoreFoundation-550  SYSTEM:Darwin  DEVELOPER:unknown  BUILT:" __DATE__ " " __TIME__ "\n";
+double kCFCoreFoundationVersionNumber = (double)550;
index 77eece09cd8abfa2d6252275edea0f1bb93e549f..9b0ac8c6a217e1439cfa18bc387a0b1d27fc10c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFWindowsMessageQueue.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Christopher Kane
 */
 
-#if defined(__WIN32__)
+#if DEPLOYMENT_TARGET_WINDOWS
 
 #include "CFWindowsMessageQueue.h"
 #include "CFInternal.h"
@@ -91,7 +91,7 @@ static CFStringRef __CFWindowsMessageQueueCopyDescription(CFTypeRef cf) {
 #warning CF: and you cannot call description if the object is locked;
 #warning CF: probably should not lock description, and call it unsafe
 */
-    CFStringAppendFormat(result, NULL, CFSTR("<CFWindowsMessageQueue %p [%p]>{locked = %s, valid = %s, mask = 0x%x,\n    run loops = %@}"), cf, CFGetAllocator(wmq), (wmq->_lock.LockCount ? "Yes" : "No"), (__CFWindowsMessageQueueIsValid(wmq) ? "Yes" : "No"), (UInt32)wmq->_mask, wmq->_runLoops);
+    CFStringAppendFormat(result, NULL, CFSTR("<CFWindowsMessageQueue %p [%p]>{locked = %s, valid = %s, mask = 0x%x,\n    run loops = %@}"), cf, CFGetAllocator(wmq), "unknown", (__CFWindowsMessageQueueIsValid(wmq) ? "Yes" : "No"), (UInt32)wmq->_mask, wmq->_runLoops);
     __CFWindowsMessageQueueUnlock(wmq);
     return result;
 }
@@ -106,7 +106,6 @@ static void __CFWindowsMessageQueueDeallocate(CFTypeRef cf) {
     CFAllocatorRef allocator = CFGetAllocator(wmq);
     CFAllocatorDeallocate(allocator, wmq);
     CFRelease(allocator);
-    DeleteCriticalSection(&(wmq->_lock));
 }
 
 static CFTypeID __kCFWindowsMessageQueueTypeID = _kCFRuntimeNotATypeID;
@@ -131,7 +130,7 @@ CFTypeID CFWindowsMessageQueueGetTypeID(void) {
     return __kCFWindowsMessageQueueTypeID;
 }
 
-CFWindowsMessageQueueRef CFWindowsMessageQueueCreate(CFAllocatorRef allocator, DWORD mask) {
+CFWindowsMessageQueueRef CFWindowsMessageQueueCreate(CFAllocatorRef allocator, uint32_t mask) {
     CFWindowsMessageQueueRef memory;
     UInt32 size = sizeof(struct __CFWindowsMessageQueue) - sizeof(CFRuntimeBase);
     memory = (CFWindowsMessageQueueRef)_CFRuntimeCreateInstance(allocator, __kCFWindowsMessageQueueTypeID, size, NULL);
@@ -141,7 +140,7 @@ CFWindowsMessageQueueRef CFWindowsMessageQueueCreate(CFAllocatorRef allocator, D
     __CFWindowsMessageQueueSetValid(memory);
 
     CF_SPINLOCK_INIT_FOR_STRUCTS(memory->_lock);
-    memory->_mask = mask;   
+    memory->_mask = (DWORD)mask;   
     memory->_source = NULL;
     memory->_runLoops = CFArrayCreateMutable(allocator, 0, NULL);
     return memory;
@@ -174,7 +173,7 @@ Boolean CFWindowsMessageQueueIsValid(CFWindowsMessageQueueRef wmq) {
     return __CFWindowsMessageQueueIsValid(wmq);
 }
 
-DWORD CFWindowsMessageQueueGetMask(CFWindowsMessageQueueRef wmq) {
+uint32_t CFWindowsMessageQueueGetMask(CFWindowsMessageQueueRef wmq) {
     __CFGenericValidateType(wmq, __kCFWindowsMessageQueueTypeID);
     return wmq->_mask;
 }
@@ -195,15 +194,9 @@ static void __CFWindowsMessageQueueSchedule(void *info, CFRunLoopRef rl, CFStrin
 static void __CFWindowsMessageQueueCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
     CFWindowsMessageQueueRef wmq = (CFWindowsMessageQueueRef)info;
     __CFWindowsMessageQueueLock(wmq);
-#if defined (__WIN32__)
 //#warning CF: should fix up run loop modes mask here, if not done
 //#warning CF: previously by the invalidation, where it should also
 //#warning CF: be done
-#else
-#warning CF: should fix up run loop modes mask here, if not done
-#warning CF: previously by the invalidation, where it should also
-#warning CF: be done
-#endif //__WIN32__
     if (NULL != wmq->_runLoops) {
        SInt32 idx = CFArrayGetFirstIndexOfValue(wmq->_runLoops, CFRangeMake(0, CFArrayGetCount(wmq->_runLoops)), rl);
        if (0 <= idx) CFArrayRemoveValueAtIndex(wmq->_runLoops, idx);
@@ -213,17 +206,14 @@ static void __CFWindowsMessageQueueCancel(void *info, CFRunLoopRef rl, CFStringR
 
 static void __CFWindowsMessageQueuePerform(void *info) {
     CFWindowsMessageQueueRef wmq = (CFWindowsMessageQueueRef)info;
-    MSG msg;
     __CFWindowsMessageQueueLock(wmq);
     if (!__CFWindowsMessageQueueIsValid(wmq)) {
        __CFWindowsMessageQueueUnlock(wmq);
        return;
     }
     __CFWindowsMessageQueueUnlock(wmq);
-    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD)) {
-       TranslateMessage(&msg);
-       DispatchMessage(&msg);
-    }
+    extern void do_WIN32_MSG();
+    do_WIN32_MSG();
 }
 
 CFRunLoopSourceRef CFWindowsMessageQueueCreateRunLoopSource(CFAllocatorRef allocator, CFWindowsMessageQueueRef wmq, CFIndex order) {
index d0c2e0834ec14c2d6e1ccbe54f9030a280add5b6..b7ac82f3dfc1bb471400994054851208233d289e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFWindowsMessageQueue.h
-       Copyright (c) 1999-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFWINDOWSMESSAGEQUEUE__)
 #define __COREFOUNDATION_CFWINDOWSMESSAGEQUEUE__ 1
 
-#if defined(__WIN32__)
+#if DEPLOYMENT_TARGET_WINDOWS
 
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFRunLoop.h>
-#include <windows.h>
 
 
-CF_EXTERN_C_BEGIN
-
 typedef struct __CFWindowsMessageQueue * CFWindowsMessageQueueRef;
 
 CF_EXPORT CFTypeID     CFWindowsMessageQueueGetTypeID(void);
 
-CF_EXPORT CFWindowsMessageQueueRef     CFWindowsMessageQueueCreate(CFAllocatorRef allocator, DWORD mask);
+CF_EXPORT CFWindowsMessageQueueRef     CFWindowsMessageQueueCreate(CFAllocatorRef allocator, uint32_t /* DWORD */ mask);
 
-CF_EXPORT DWORD                CFWindowsMessageQueueGetMask(CFWindowsMessageQueueRef wmq);
+CF_EXPORT uint32_t     CFWindowsMessageQueueGetMask(CFWindowsMessageQueueRef wmq);
 CF_EXPORT void         CFWindowsMessageQueueInvalidate(CFWindowsMessageQueueRef wmq);
 CF_EXPORT Boolean      CFWindowsMessageQueueIsValid(CFWindowsMessageQueueRef wmq);
 
 CF_EXPORT CFRunLoopSourceRef   CFWindowsMessageQueueCreateRunLoopSource(CFAllocatorRef allocator, CFWindowsMessageQueueRef wmq, CFIndex order);
 
-CF_EXTERN_C_END
-
-#endif /* __WIN32__ */
+#endif
 
 #endif /* ! __COREFOUNDATION_CFWINDOWSMESSAGEQUEUE__ */
 
index c5997229ae526a1494cfbfb999e332bd01f726ef..88e12404e0a02724808003de8f223e403802a592 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFXMLInputStream.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Chris Parker
 */
 
index b18b70c1dd09b42054845f82ca86ff7ff299ef54..b0d6da737edd53cf25d8eba9426b77ed40f478b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFXMLInputStream.h
-       Copyright (c) 2000-2007, Apple Inc. All rights reserved.
+       Copyright (c) 2000-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_CFXMLINPUTSTREAM__)
index 6a69614249884a66ed5bd01f871990befe1fd6c3..85d7a965aeefe59b3f21432d5953f7bcf3052234 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFXMLNode.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Chris Parker
 */
 
index d927a583ec3aa3e3674d249cba85e1efcd130b76..0e8717c395475839b8223d1ca29459f5125a6df1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFXMLNode.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
+/*  CFXMLParser (and thus CFXMLNode) will be officially deprecated in a future release of Mac OS X.
+    Clients should be aware of the fact that CFXMLParser has some serious deficiencies in terms of both
+    performance and standards compliance and should migrate their XML parsing to NSXMLParser, NSXMLDocument, or
+    other XML parsing technologies that will suit their needs better than CFXMLParser.
+ */
+
 #if !defined(__COREFOUNDATION_CFXMLNODE__)
 #define __COREFOUNDATION_CFXMLNODE__ 1
 
index 7e97ba066aff8225f6b84dda0fe7c097f6c78462..2920da7879a36e903a5361c3e9820b9b7678cc30 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFXMLParser.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Chris Parker
 */
 
index 6f494bac4c4ad99fe44ad5a7a925c8497f991f05..ea55ff73029ceaa12e6cd14d88bb218ace28cc4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFXMLParser.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
+/*  CFXMLParser will be officially deprecated in a future release of Mac OS X. Clients should be
+    aware of the fact that CFXMLParser has some serious deficiencies in terms of both performance
+    and standards compliance and should migrate their XML parsing to NSXMLParser, NSXMLDocument, or
+    other XML parsing technologies that will suit their needs better than CFXMLParser.
+ */
+
 #if !defined(__COREFOUNDATION_CFXMLPARSER__)
 #define __COREFOUNDATION_CFXMLPARSER__ 1
 
@@ -70,12 +76,12 @@ kCFXMLParserAddImpliedAttributes -
 */
 
 enum {
-    kCFXMLParserValidateDocument = (1 << 0),
-    kCFXMLParserSkipMetaData = (1 << 1),
-    kCFXMLParserReplacePhysicalEntities = (1 << 2),
-    kCFXMLParserSkipWhitespace = (1 << 3),
-    kCFXMLParserResolveExternalEntities = (1 << 4),
-    kCFXMLParserAddImpliedAttributes = (1 << 5),
+    kCFXMLParserValidateDocument = (1UL << 0),
+    kCFXMLParserSkipMetaData = (1UL << 1),
+    kCFXMLParserReplacePhysicalEntities = (1UL << 2),
+    kCFXMLParserSkipWhitespace = (1UL << 3),
+    kCFXMLParserResolveExternalEntities = (1UL << 4),
+    kCFXMLParserAddImpliedAttributes = (1UL << 5),
     kCFXMLParserAllOptions = 0x00FFFFFF,
     kCFXMLParserNoOptions = 0
 };
index 7878668a5c892bd111b522503f847e328654141c..43b52494b0de4fb009ebb53a6cb7ec2d9bcf8862 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFXMLPreferencesDomain.c
-       Copyright 1998-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
        Responsibility: Chris Parker
 */
 
@@ -64,7 +64,9 @@ __private_extern__ const _CFPreferencesDomainCallBacks __kCFXMLPropertyListDomai
 
 // Directly ripped from Foundation....
 static void __CFMilliSleep(uint32_t msecs) {
-#if defined(__svr4__) || defined(__hpux__)
+#if DEPLOYMENT_TARGET_WINDOWS
+    SleepEx(msecs, false);
+#elif defined(__svr4__) || defined(__hpux__)
     sleep((msecs + 900) / 1000);
 #elif DEPLOYMENT_TARGET_MACOSX
     struct timespec input;
index 75fbcae238a23b9c5d263940514b7266d2771cfd..36666c94dce053e79a5ef745423733dc10ff6de3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CFXMLTree.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
+       Copyright (c) 1999-2009, Apple Inc. All rights reserved.
        Responsibility: Chris Parker
 */
 
index 6f95a987ee3f27fc2e0575ceffc4f111137fca90..3421db054c455b461ef00e0d8c48a7e143d1bfd2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     CoreFoundation.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !defined(__COREFOUNDATION_COREFOUNDATION__)
@@ -72,8 +72,6 @@
 #include <CoreFoundation/CFDictionary.h>
 #include <CoreFoundation/CFError.h>
 #include <CoreFoundation/CFLocale.h>
-#include <CoreFoundation/CFLogUtilities.h>
-#include <CoreFoundation/CFMachPort.h>
 #include <CoreFoundation/CFMessagePort.h>
 #include <CoreFoundation/CFNumber.h>
 #include <CoreFoundation/CFNumberFormatter.h>
 #include <CoreFoundation/CFURL.h>
 #include <CoreFoundation/CFURLAccess.h>
 #include <CoreFoundation/CFUUID.h>
+
+
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+#include <CoreFoundation/CFMachPort.h>
+#endif
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
+#include <CoreFoundation/CFUserNotification.h>
 #include <CoreFoundation/CFXMLNode.h>
 #include <CoreFoundation/CFXMLParser.h>
-
+#endif
 
 #endif /* ! __COREFOUNDATION_COREFOUNDATION__ */
 
diff --git a/CoreFoundation_Prefix.h b/CoreFoundation_Prefix.h
new file mode 100644 (file)
index 0000000..b879ff3
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2009 Apple 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@
+ */
+/*     CoreFoundation_Prefix.h
+       Copyright (c) 2005-2009, Apple Inc. All rights reserved.
+*/
+
+
+#define _DARWIN_UNLIMITED_SELECT 1
+
+#include <CoreFoundation/CFBase.h>
+
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#if DEPLOYMENT_TARGET_WINDOWS && defined(__cplusplus)
+extern "C" {
+#endif
+    
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#include <objc/objc.h>
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#define DISPATCH_HELPER_FUNCTIONS(PREFIX, QNAME)                        
+#endif
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+
+#import <dispatch/dispatch.h>
+#import <libkern/OSAtomic.h>
+#import <pthread.h>
+
+/* This macro creates 3 helper functions which are useful in dealing with libdispatch:
+ *  __ PREFIX SyncDispatchIsSafe  -- returns bool indicating whether calling dispatch_sync() would be safe from self-deadlock
+ *  __ PREFIX Queue -- manages and returns a singleton serial queue
+ *
+ * Use the macro like this:
+ *   DISPATCH_HELPER_FUNCTIONS(fh, NSFileHandle)
+ */
+
+#define DISPATCH_HELPER_FUNCTIONS(PREFIX, QNAME)                       \
+static Boolean __ ## PREFIX ## SyncDispatchIsSafe(dispatch_queue_t Q) {        \
+    dispatch_queue_t C = dispatch_get_current_queue();                 \
+    return (!C || Q != C) ? true : false;                              \
+}                                                                      \
+                                                                       \
+static dispatch_queue_t __ ## PREFIX ## Queue(void) {                  \
+    static volatile dispatch_queue_t __ ## PREFIX ## dq = NULL;                \
+    if (!__ ## PREFIX ## dq) {                                         \
+        dispatch_queue_t dq = dispatch_queue_create(# QNAME, NULL);    \
+        void * volatile *loc = (void * volatile *)&__ ## PREFIX ## dq; \
+        if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dq, loc)) {                \
+            dispatch_release(dq);                                      \
+        }                                                              \
+    }                                                                  \
+    return __ ## PREFIX ## dq;                                         \
+}                                                                      \
+
+#endif
+
+#define LIBAUTO_STUB   1
+
+#ifndef LIBAUTO_STUB
+
+#if DEPLOYMENT_TARGET_MACOSX
+#include <auto_zone.h>
+#endif
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#include <objc/objc-auto.h>
+#endif
+
+#endif // LIBAUTO_STUB
+
+#if DEPLOYMENT_TARGET_WINDOWS
+// Compatibility with boolean.h
+#if defined(__x86_64__)
+typedef unsigned int   boolean_t;
+#else
+typedef int            boolean_t;
+#endif
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+
+#define MAXPATHLEN MAX_PATH
+#undef MAX_PATH
+#undef INVALID_HANDLE_VALUE
+
+// Define MIN/MAX macros from NSObjCRuntime.h, which are only defined for GNUC
+#if !defined(__GNUC__)
+    
+#if !defined(MIN)
+#define MIN(A,B)       ((A) < (B) ? (A) : (B))
+#endif
+    
+#if !defined(MAX)
+#define MAX(A,B)       ((A) > (B) ? (A) : (B))
+#endif
+    
+#if !defined(ABS)
+#define ABS(A) ((A) < 0 ? (-(A)) : (A))
+#endif
+    
+#endif
+
+// Defined for source compatibility
+#define ino_t _ino_t
+#define off_t _off_t
+#define mode_t uint16_t
+        
+// This works because things aren't actually exported from the DLL unless they have a __declspec(dllexport) on them... so extern by itself is closest to __private_extern__ on Mac OS
+#define __private_extern__ extern
+    
+#define __builtin_expect(P1,P2) P1
+    
+// These are replacements for POSIX calls on Windows, ensuring that the UTF8 parameters are converted to UTF16 before being passed to Windows
+CF_EXPORT int _NS_stat(const char *name, struct _stat *st);
+CF_EXPORT int _NS_mkdir(const char *name);
+CF_EXPORT int _NS_rmdir(const char *name);
+CF_EXPORT int _NS_chmod(const char *name, int mode);
+CF_EXPORT int _NS_unlink(const char *name);
+CF_EXPORT char *_NS_getcwd(char *dstbuf, size_t size);     // Warning: this doesn't support dstbuf as null even though 'getcwd' does
+CF_EXPORT char *_NS_getenv(const char *name);
+CF_EXPORT int _NS_rename(const char *oldName, const char *newName);
+CF_EXPORT int _NS_open(const char *name, int oflag, int pmode = 0);
+CF_EXPORT int _NS_chdir(const char *name);
+CF_EXPORT int _NS_mkstemp(char *name, int bufSize);
+CF_EXPORT int _NS_access(const char *name, int amode);
+
+#define BOOL WINDOWS_BOOL
+
+#define WIN32_LEAN_AND_MEAN
+
+#ifndef WINVER
+#define WINVER  0x0501
+#endif
+    
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
+// The order of these includes is important
+#include <winsock2.h>
+#include <windows.h>
+
+#undef BOOL
+
+#ifndef HAVE_STRUCT_TIMESPEC
+#define HAVE_STRUCT_TIMESPEC 1
+struct timespec {
+        long tv_sec;
+        long tv_nsec;
+};
+#endif /* HAVE_STRUCT_TIMESPEC */
+
+#define __PRETTY_FUNCTION__ __FUNCTION__
+
+#define malloc_default_zone() (void *)0
+#define malloc_zone_from_ptr(a) (void *)0
+#define malloc_zone_malloc(zone,size) malloc(size)
+#define malloc_zone_calloc(zone,count,size) calloc(count,size)
+#define bcopy(b1,b2,len) memmove(b2, b1, (size_t)(len))
+typedef int malloc_zone_t;
+typedef int uid_t;
+typedef int gid_t;
+#define geteuid() 0
+#define getuid() 0
+#define getegid() 0
+
+#define fsync(a) _commit(a)
+#define malloc_create_zone(a,b) 123
+#define malloc_set_zone_name(zone,name)
+#define malloc_zone_realloc(zone,ptr,size) realloc(ptr,size)
+#define malloc_zone_free(zone,ptr) free(ptr)
+
+// implemented in CFInternal.h
+#define OSSpinLockLock(A) __CFSpinLock(A)
+#define OSSpinLockUnlock(A) __CFSpinUnlock(A)
+    
+typedef int32_t OSSpinLock;
+
+#define OS_SPINLOCK_INIT       0
+
+#include <stdint.h>
+#include <stdbool.h>
+//#include <search.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <malloc.h>
+CF_INLINE size_t malloc_size(void *memblock) {
+    return _msize(memblock);
+}
+
+#define mach_absolute_time() ((uint64_t)(CFAbsoluteTimeGetCurrent() * 1000000000.0))
+
+extern int pthread_main_np();
+
+#define strtod_l(a,b,locale) strtod(a,b)
+#define strtoul_l(a,b,c,locale) strtoul(a,b,c)
+#define strtol_l(a,b,c,locale) strtol(a,b,c)
+
+#define _fprintf_l(a,b,locale,...) fprintf(a, b, __VA_ARGS__)
+
+#define strlcat(a,b,c) strncat(a,b,c)
+
+#define issetugid() 0
+
+// CF exports these useful atomic operation functions on Windows
+CF_EXPORT bool OSAtomicCompareAndSwapPtr(void *oldp, void *newp, void *volatile *dst);
+CF_EXPORT bool OSAtomicCompareAndSwapLong(long oldl, long newl, long volatile *dst);
+CF_EXPORT bool OSAtomicCompareAndSwapPtrBarrier(void *oldp, void *newp, void *volatile *dst);
+
+CF_EXPORT int32_t OSAtomicDecrement32Barrier(volatile int32_t *dst);
+CF_EXPORT int32_t OSAtomicIncrement32Barrier(volatile int32_t *dst);
+CF_EXPORT int32_t OSAtomicIncrement32(volatile int32_t *theValue);
+CF_EXPORT int32_t OSAtomicDecrement32(volatile int32_t *theValue);
+    
+CF_EXPORT int32_t OSAtomicAdd32Barrier( int32_t theAmount, volatile int32_t *theValue );
+CF_EXPORT bool OSAtomicCompareAndSwap32Barrier( int32_t oldValue, int32_t newValue, volatile int32_t *theValue );
+
+/*
+CF_EXPORT bool OSAtomicCompareAndSwap64( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
+CF_EXPORT bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue );
+    
+CF_EXPORT int64_t OSAtomicAdd64( int64_t __theAmount, volatile int64_t *__theValue );
+CF_EXPORT int64_t OSAtomicAdd64Barrier( int64_t __theAmount, volatile int64_t *__theValue );
+*/
+    
+#define sleep(x) Sleep(1000*x)
+#define strlcpy strncpy
+    
+//#ifndef NTDDI_VERSION
+//#define NTDDI_VERSION NTDDI_WINXP
+//#endif
+
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static __inline int flsl( long mask ) {
+    int idx = 0;
+       while (mask != 0) mask = (unsigned long)mask >> 1, idx++;
+       return idx;
+}
+
+static __inline int asprintf(char **ret, const char *format, ...) {
+    va_list args;
+    size_t sz = 1024;
+    *ret = (char *) malloc(sz * sizeof(char));
+    if (!*ret) return -1;
+    va_start(args, format);
+    int cnt = vsnprintf(*ret, sz, format, args);
+    va_end(args);
+    if (cnt < sz - 1) return cnt;
+    sz = cnt + 8;
+    char *oldret = *ret;
+    *ret = (char *) realloc(*ret, sz * sizeof(char));
+    if (!*ret && oldret) free(oldret);
+    if (!*ret) return -1;
+    va_start(args, format);
+    cnt = vsnprintf(*ret, sz, format, args);
+    va_end(args);
+    if (cnt < sz - 1) return cnt;
+    free(*ret);
+    *ret = NULL;
+    return -1;
+}
+
+#define __unused
+
+#define __weak
+#define __strong
+    
+#endif
+
+#ifdef LIBAUTO_STUB
+
+/* Stubs for functions in libauto. */
+
+enum {OBJC_GENERATIONAL = (1 << 0)};
+
+enum {
+    OBJC_RATIO_COLLECTION        = (0 << 0), 
+    OBJC_GENERATIONAL_COLLECTION = (1 << 0),
+    OBJC_FULL_COLLECTION         = (2 << 0),
+    OBJC_EXHAUSTIVE_COLLECTION   = (3 << 0),
+    OBJC_COLLECT_IF_NEEDED       = (1 << 3),
+    OBJC_WAIT_UNTIL_DONE         = (1 << 4),
+};
+
+    
+enum { AUTO_TYPE_UNKNOWN = -1, AUTO_UNSCANNED = 1, AUTO_OBJECT = 2, AUTO_MEMORY_SCANNED = 0, AUTO_MEMORY_UNSCANNED = AUTO_UNSCANNED, AUTO_OBJECT_SCANNED = AUTO_OBJECT, AUTO_OBJECT_UNSCANNED = AUTO_OBJECT | AUTO_UNSCANNED };
+typedef unsigned long auto_memory_type_t;
+typedef struct _auto_zone_t auto_zone_t;
+typedef struct auto_weak_callback_block {
+    struct auto_weak_callback_block *next;
+    void (*callback_function)(void *arg1, void *arg2);
+    void *arg1;
+    void *arg2;
+} auto_weak_callback_block_t;
+
+CF_INLINE void *objc_memmove_collectable(void *a, const void *b, size_t c) { return memmove(a, b, c); }
+
+CF_INLINE auto_zone_t *auto_zone(void) { return 0; }
+CF_INLINE void *auto_zone_allocate_object(void *zone, size_t size, auto_memory_type_t type, int rc, int clear) { return 0; }
+CF_INLINE const void *auto_zone_base_pointer(void *zone, const void *ptr) { return 0; }
+CF_INLINE void auto_zone_retain(void *zone, void *ptr) {}
+CF_INLINE unsigned int auto_zone_release(void *zone, void *ptr) { return 0; }
+CF_INLINE unsigned int auto_zone_retain_count(void *zone, const void *ptr) { return 0; }
+CF_INLINE void auto_zone_set_unscanned(auto_zone_t *zone, void *ptr) {}
+CF_INLINE void auto_zone_set_nofinalize(auto_zone_t *zone, void *ptr) {}
+CF_INLINE int auto_zone_is_finalized(void *zone, const void *ptr) { return 0; }
+CF_INLINE size_t auto_zone_size(void *zone, const void *ptr) { return 0; }
+CF_INLINE void auto_register_weak_reference(void *zone, const void *referent, void **referrer, uintptr_t *counter, void **listHead, void **listElement) {}
+CF_INLINE void auto_unregister_weak_reference(void *zone, const void *referent, void **referrer) {}
+CF_INLINE void auto_zone_register_thread(void *zone) {}
+CF_INLINE void auto_zone_unregister_thread(void *zone) {}
+CF_INLINE int auto_zone_is_valid_pointer(void *zone, const void *ptr) { return 0; }
+CF_INLINE BOOL objc_isAuto(id object) { return 0; }
+CF_INLINE void* auto_read_weak_reference(void *zone, void **referrer) { void *result = *referrer; return result; }
+CF_INLINE void auto_assign_weak_reference(void *zone, const void *referent, void **referrer, auto_weak_callback_block_t *block) { *referrer = (void *)referent; }
+CF_INLINE auto_memory_type_t auto_zone_get_layout_type(void *zone, void *ptr) { return AUTO_UNSCANNED; }
+CF_INLINE boolean_t auto_zone_set_write_barrier(auto_zone_t *zone, const void *dest, const void *new_value) { return false; }
+
+CF_INLINE void objc_assertRegisteredThreadWithCollector(void) {}
+
+// from objc-auto.h
+
+static OBJC_INLINE BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation) 
+{ return OSAtomicCompareAndSwapPtr((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
+
+static OBJC_INLINE BOOL objc_atomicCompareAndSwapPtrBarrier(id predicate, id replacement, volatile id *objectLocation) 
+{ return OSAtomicCompareAndSwapPtrBarrier((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
+
+static OBJC_INLINE BOOL objc_atomicCompareAndSwapGlobal(id predicate, id replacement, volatile id *objectLocation) 
+{ return OSAtomicCompareAndSwapPtr((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
+
+static OBJC_INLINE BOOL objc_atomicCompareAndSwapGlobalBarrier(id predicate, id replacement, volatile id *objectLocation) 
+{ return OSAtomicCompareAndSwapPtrBarrier((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
+
+static OBJC_INLINE BOOL objc_atomicCompareAndSwapInstanceVariable(id predicate, id replacement, volatile id *objectLocation) 
+{ return OSAtomicCompareAndSwapPtr((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
+
+static OBJC_INLINE BOOL objc_atomicCompareAndSwapInstanceVariableBarrier(id predicate, id replacement, volatile id *objectLocation) 
+{ return OSAtomicCompareAndSwapPtrBarrier((void *)predicate, (void *)replacement, (void * volatile *)objectLocation); }
+
+static OBJC_INLINE id objc_assign_strongCast(id val, id *dest) 
+{ return (*dest = val); }
+
+static OBJC_INLINE id objc_assign_global(id val, id *dest) 
+{ return (*dest = val); }
+
+static OBJC_INLINE id objc_assign_ivar(id val, id dest, ptrdiff_t offset) 
+{ return (*(id*)((char *)dest+offset) = val); }
+
+//static OBJC_INLINE void *objc_memmove_collectable(void *dst, const void *src, size_t size) { return memmove(dst, src, size); }
+
+static OBJC_INLINE id objc_read_weak(id *location) 
+{ return *location; }
+
+static OBJC_INLINE id objc_assign_weak(id value, id *location) 
+{ return (*location = value); }
+
+
+static OBJC_INLINE void objc_finalizeOnMainThread(Class cls) { }
+static OBJC_INLINE BOOL objc_is_finalized(void *ptr) { return NO; }
+static OBJC_INLINE void objc_clear_stack(unsigned long options) { }
+
+static OBJC_INLINE BOOL objc_collectingEnabled(void) { return NO; }
+static OBJC_INLINE void objc_start_collector_thread(void) { }
+
+static OBJC_INLINE void objc_collect(unsigned long options) { }
+    
+#endif
+
+// Need to use the _O_BINARY flag on Windows to get the correct behavior
+#if DEPLOYMENT_TARGET_WINDOWS
+    #define CF_OPENFLGS        (_O_BINARY|_O_NOINHERIT)
+#else
+    #define CF_OPENFLGS        (0)
+#endif
+
+
+#if DEPLOYMENT_TARGET_WINDOWS && defined(__cplusplus)
+} // extern "C"
+#endif
index 4aefa6f853197d3f04a9ca10b0732f63229e61fe..201c9fc98236ddd0a51115c946e22a8990fee121 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*     ForFoundationOnly.h
-       Copyright (c) 1998-2007, Apple Inc. All rights reserved.
+       Copyright (c) 1998-2009, Apple Inc. All rights reserved.
 */
 
 #if !CF_BUILDING_CF && !NSBUILDINGFOUNDATION
@@ -35,7 +35,9 @@
 #include <CoreFoundation/CFBase.h>
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFArray.h>
+#include <CoreFoundation/CFData.h>
 #include <CoreFoundation/CFDictionary.h>
+#include <CoreFoundation/CFSet.h>
 #include <CoreFoundation/CFPriv.h>
 #include <CoreFoundation/CFPropertyList.h>
 #include <CoreFoundation/CFError.h>
@@ -48,9 +50,9 @@
 
 CF_EXTERN_C_BEGIN
 
-#if DEPLOYMENT_TARGET_MACOSX || 0
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
 #include <malloc/malloc.h>
-#endif //__MACH__
+#endif
 
 CF_EXTERN_C_END
 
@@ -84,7 +86,6 @@ CF_EXPORT CFErrorRef _CFBundleCreateError(CFAllocatorRef allocator, CFBundleRef
 CF_EXTERN_C_END
 
 
-#if (DEPLOYMENT_TARGET_MACOSX || 0) || defined (__WIN32__)
 // ---- CFPreferences material ----------------------------------------
 
 #define DEBUG_PREFERENCES_MEMORY 0
@@ -162,10 +163,11 @@ CF_EXPORT CFTypeRef _CFApplicationPreferencesSearchDownToDomain(_CFApplicationPr
 
 CF_EXTERN_C_END
 
-#endif
+
 
 // ---- CFString material ----------------------------------------
 
+#include <CoreFoundation/CFStringEncodingExt.h>
 
 CF_EXTERN_C_BEGIN
 
@@ -187,11 +189,18 @@ CF_EXPORT CFStringRef __CFStringCreateImmutableFunnel2(CFAllocatorRef alloc, con
 
 CF_INLINE Boolean __CFStringEncodingIsSupersetOfASCII(CFStringEncoding encoding) {
     switch (encoding & 0x0000FF00) {
+       case 0x0: // MacOS Script range
+            // Symbol & bidi encodings are not ASCII superset
+            if (encoding == kCFStringEncodingMacJapanese || encoding == kCFStringEncodingMacArabic || encoding == kCFStringEncodingMacHebrew || encoding == kCFStringEncodingMacUkrainian || encoding == kCFStringEncodingMacSymbol || encoding == kCFStringEncodingMacDingbats) return false;
+            return true;
 
         case 0x100: // Unicode range
             if (encoding != kCFStringEncodingUTF8) return false;
             return true;
 
+        case 0x200: // ISO range
+            if (encoding == kCFStringEncodingISOLatinArabic) return false;
+            return true;
             
         case 0x600: // National standards range
             if (encoding != kCFStringEncodingASCII) return false;
@@ -200,6 +209,9 @@ CF_INLINE Boolean __CFStringEncodingIsSupersetOfASCII(CFStringEncoding encoding)
         case 0x800: // ISO 2022 range
             return false; // It's modal encoding
 
+        case 0xA00: // Misc standard range
+            if ((encoding == kCFStringEncodingShiftJIS) || (encoding == kCFStringEncodingHZ_GB_2312)) return false;
+            return true;
 
         case 0xB00:
             if (encoding == kCFStringEncodingNonLossyASCII) return false;
@@ -250,11 +262,9 @@ CF_EXPORT Boolean __CFStringDecodeByteStream2(const UInt8 *bytes, UInt32 len, CF
 CF_EXPORT Boolean __CFStringDecodeByteStream3(const UInt8 *bytes, CFIndex len, CFStringEncoding encoding, Boolean alwaysUnicode, CFVarWidthCharBuffer *buffer, Boolean *useClientsMemoryPtr, UInt32 converterFlags);
 
 
-/* Convert single byte to Unicode; assumes one-to-one correspondence (that is, can only be used with 1-byte encodings). You can use the function if it's not NULL. The table is always safe to use; calling __CFSetCharToUniCharFunc() updates it.
+/* Convert single byte to Unicode; assumes one-to-one correspondence (that is, can only be used with 1-byte encodings). You can use the function if it's not NULL.
 */
 CF_EXPORT Boolean (*__CFCharToUniCharFunc)(UInt32 flags, UInt8 ch, UniChar *unicodeChar);
-CF_EXPORT void __CFSetCharToUniCharFunc(Boolean (*func)(UInt32 flags, UInt8 ch, UniChar *unicodeChar));
-CF_EXPORT UniChar __CFCharToUniCharTable[256];
 
 /* Character class functions UnicodeData-2_1_5.txt
 */
@@ -319,15 +329,6 @@ CF_EXPORT CFHashCode CFStringHashCString(const uint8_t *bytes, CFIndex len);
 CF_EXPORT CFHashCode CFStringHashCharacters(const UniChar *characters, CFIndex len);
 CF_EXPORT CFHashCode CFStringHashNSString(CFStringRef str);
 
-/* Currently for CFString usage, for handling out-of-memory conditions.
-   The callback might not return; if it does, true indicates the error was potentially dealt with; false means no.
-   Typically true means OK to continue executing.
-*/
-typedef Boolean (*CFBadErrorCallBack)(CFTypeRef obj, CFStringRef domain, CFStringRef msg);
-CF_EXPORT CFBadErrorCallBack _CFGetOutOfMemoryErrorCallBack(void);
-CF_EXPORT void _CFSetOutOfMemoryErrorCallBack(CFBadErrorCallBack callback);
-
-
 
 CF_EXTERN_C_END
 
@@ -335,9 +336,9 @@ CF_EXTERN_C_END
 // ---- Binary plist material ----------------------------------------
 
 typedef const struct __CFKeyedArchiverUID * CFKeyedArchiverUIDRef;
-extern CFTypeID _CFKeyedArchiverUIDGetTypeID(void);
-extern CFKeyedArchiverUIDRef _CFKeyedArchiverUIDCreate(CFAllocatorRef allocator, uint32_t value);
-extern uint32_t _CFKeyedArchiverUIDGetValue(CFKeyedArchiverUIDRef uid);
+CF_EXPORT CFTypeID _CFKeyedArchiverUIDGetTypeID(void);
+CF_EXPORT CFKeyedArchiverUIDRef _CFKeyedArchiverUIDCreate(CFAllocatorRef allocator, uint32_t value);
+CF_EXPORT uint32_t _CFKeyedArchiverUIDGetValue(CFKeyedArchiverUIDRef uid);
 
 
 enum {
@@ -363,7 +364,8 @@ typedef struct {
 } CFBinaryPlistHeader;
 
 typedef struct {
-    uint8_t    _unused[6];
+    uint8_t    _unused[5];
+    uint8_t     _sortVersion;
     uint8_t    _offsetIntSize;
     uint8_t    _objectRefSize;
     uint64_t   _numObjects;
@@ -371,17 +373,52 @@ typedef struct {
     uint64_t   _offsetTableOffset;
 } CFBinaryPlistTrailer;
 
-extern bool __CFBinaryPlistGetTopLevelInfo(const uint8_t *databytes, uint64_t datalen, uint8_t *marker, uint64_t *offset, CFBinaryPlistTrailer *trailer);
-extern bool __CFBinaryPlistGetOffsetForValueFromArray2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFIndex idx, uint64_t *offset, CFMutableDictionaryRef objects);
-extern bool __CFBinaryPlistGetOffsetForValueFromDictionary2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFTypeRef key, uint64_t *koffset, uint64_t *voffset, CFMutableDictionaryRef objects);
-extern bool __CFBinaryPlistCreateObject(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFPropertyListRef *plist);
-extern CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream);
 
+CF_EXPORT bool __CFBinaryPlistGetTopLevelInfo(const uint8_t *databytes, uint64_t datalen, uint8_t *marker, uint64_t *offset, CFBinaryPlistTrailer *trailer);
+CF_EXPORT bool __CFBinaryPlistGetOffsetForValueFromArray2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFIndex idx, uint64_t *offset, CFMutableDictionaryRef objects);
+CF_EXPORT bool __CFBinaryPlistGetOffsetForValueFromDictionary3(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFTypeRef key, uint64_t *koffset, uint64_t *voffset, Boolean unused, CFMutableDictionaryRef objects);
+CF_EXPORT bool __CFBinaryPlistCreateObject(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFPropertyListRef *plist);
+CF_EXPORT bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFPropertyListRef *plist);
+CF_EXPORT CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream);
+CF_EXPORT CFIndex __CFBinaryPlistWriteToStreamWithEstimate(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate); // will be removed soon
+CF_EXPORT CFIndex __CFBinaryPlistWriteToStreamWithOptions(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate, CFOptionFlags options); // will be removed soon
+CF_EXPORT CFIndex __CFBinaryPlistWrite(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate, CFOptionFlags options, CFErrorRef *error);
 
 // ---- Used by property list parsing in Foundation
 
-extern CFTypeRef _CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags option, CFStringRef *errorString, Boolean allowNewTypes, CFPropertyListFormat *format);
+CF_EXPORT CFTypeRef _CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags option, CFStringRef *errorString, Boolean allowNewTypes, CFPropertyListFormat *format);
+
+CF_EXPORT CFTypeRef _CFPropertyListCreateFromXMLString(CFAllocatorRef allocator, CFStringRef xmlString, CFOptionFlags option, CFStringRef *errorString, Boolean allowNewTypes, CFPropertyListFormat *format);
+
+CF_EXPORT bool _CFPropertyListCreateSingleValue(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFStringRef key, CFPropertyListRef *value, CFErrorRef *error);
 
+// ---- Sudden Termination material ----------------------------------------
+
+#if DEPLOYMENT_TARGET_MACOSX
+
+CF_EXPORT void _CFSuddenTerminationDisable(void);
+CF_EXPORT void _CFSuddenTerminationEnable(void);
+CF_EXPORT void _CFSuddenTerminationExitIfTerminationEnabled(int exitStatus);
+CF_EXPORT void _CFSuddenTerminationExitWhenTerminationEnabled(int exitStatus);
+CF_EXPORT size_t _CFSuddenTerminationDisablingCount(void);
+
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+// ---- Windows-specific material ---------------------------------------
+
+// These are replacements for POSIX calls on Windows, ensuring that the UTF8 parameters are converted to UTF16 before being passed to Windows
+CF_EXPORT int _NS_stat(const char *name, struct _stat *st);
+CF_EXPORT int _NS_mkdir(const char *name);
+CF_EXPORT int _NS_rmdir(const char *name);
+CF_EXPORT int _NS_chmod(const char *name, int mode);
+CF_EXPORT int _NS_unlink(const char *name);
+CF_EXPORT char *_NS_getcwd(char *dstbuf, size_t size);     // Warning: this doesn't support dstbuf as null even though 'getcwd' does
+CF_EXPORT char *_NS_getenv(const char *name);
+CF_EXPORT int _NS_rename(const char *oldName, const char *newName);
+CF_EXPORT int _NS_open(const char *name, int oflag, int pmode);
+CF_EXPORT int _NS_mkstemp(char *name, int bufSize);
+#endif
 
 // ---- Miscellaneous material ----------------------------------------
 
@@ -436,8 +473,9 @@ CF_INLINE CFHashCode _CFHashInt(long i) {
 CF_INLINE CFHashCode _CFHashDouble(double d) {
     double dInt;
     if (d < 0) d = -d;
-    dInt = rint(d);
-    return (CFHashCode)((HASHFACTOR * (CFHashCode)fmod(dInt, (double)ULONG_MAX)) + ((d - dInt) * ULONG_MAX));
+    dInt = floor(d+0.5);
+    CFHashCode integralHash = HASHFACTOR * (CFHashCode)fmod(dInt, (double)ULONG_MAX);
+    return (CFHashCode)(integralHash + (CFHashCode)((d - dInt) * ULONG_MAX));
 }
 
 
@@ -460,27 +498,41 @@ CF_EXPORT Boolean _CFRunLoopFinished(CFRunLoopRef rl, CFStringRef mode);
 
 CF_EXPORT CFIndex _CFStreamInstanceSize(void);
 
-#if (DEPLOYMENT_TARGET_MACOSX || 0)
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+typedef struct {
+    mach_vm_address_t address;
+    mach_vm_size_t size;
+    mach_port_t port;
+    bool purgeable;
+    bool corporeal;
+    bool volatyle;
+    uintptr_t reserved;
+} CFDiscorporateMemory;
+
+extern kern_return_t _CFDiscorporateMemoryAllocate(CFDiscorporateMemory *hm, size_t size, bool purgeable);
+extern kern_return_t _CFDiscorporateMemoryDeallocate(CFDiscorporateMemory *hm);
+extern kern_return_t _CFDiscorporateMemoryDematerialize(CFDiscorporateMemory *hm);
+extern kern_return_t _CFDiscorporateMemoryMaterialize(CFDiscorporateMemory *hm);
+#endif
+
+CF_EXPORT CFRange _CFDataFindBytes(CFDataRef data, CFDataRef dataToFind, CFRange searchRange, CFDataSearchFlags compareOptions);
+
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
     #if !defined(__CFReadTSR)
     #include <mach/mach_time.h>
     #define __CFReadTSR() mach_absolute_time()
     #endif
-#elif defined(__WIN32__)
+#elif DEPLOYMENT_TARGET_WINDOWS
+#if 0
 CF_INLINE UInt64 __CFReadTSR(void) {
     LARGE_INTEGER freq;
     QueryPerformanceCounter(&freq);
     return freq.QuadPart;
 }
 #endif
+#endif
 
-#define CF_HAS_NSOBJECT 1
-#define CF_HAS_NSARRAY 1
-#define CF_HAS_NSMUTABLEARRAY 1
-#define CF_HAS_NSDICTIONARY 1
-#define CF_HAS_NSMUTABLEDICTIONARY 1
-#define CF_HAS_NSSET 1
-#define CF_HAS_NSMUTABLESET 1
-#define CF_HAS_NSBATCH2 1
 
 CF_EXTERN_C_END
 
index 7400609e9619c1a487841bc8bc707a3eacdd1069..fe8b36a35e1ac946149304be2eeec304ca611f32 100644 (file)
@@ -5,7 +5,7 @@
        <key>CFBundleDevelopmentRegion</key>
        <string>en_US</string>
        <key>CFBundleExecutable</key>
-       <string>CoreFoundation</string>
+       <string>$(EXECUTABLE_NAME)</string>
        <key>CFBundleIdentifier</key>
        <string>com.apple.CoreFoundation</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <key>CFBundlePackageType</key>
        <string>FMWK</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.5</string>
+       <string>6.6</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>476</string>
+       <string>550.1</string>
        <key>CarbonLazyValues</key>
        <dict>
                <key>CodeFragmentManager</key>
diff --git a/README b/README
deleted file mode 100644 (file)
index b6f4b2d..0000000
--- a/README
+++ /dev/null
@@ -1,97 +0,0 @@
-This is the CoreFoundation framework project for Darwin,
-sometimes also known as "CF-lite", because it does not
-contain every facility available from the CoreFoundation
-framework in Mac OS X.
-
-This CoreFoundation corresponds to the Mac OS X 10.5.2 version
-of CF (CF-476.10)
-
-The purpose of this README file is to share "what needs
-doing", "how to do things", and Q&A information about
-CF-lite, as this information is discovered.
-
---- What Apple is NOT interested in, with CF-lite:
-* Everybody's little convenience methods. Just because
-  "everybody has to write their own", it does not
-  follow immediately that it is a good idea to add it
-  to the system libraries. It is not a goal of CF to
-  be a "Swiss Army Knife"; that just increases the
-  size of the binaries, and the documentation and
-  maintenance burden. Functions to reverse a string
-  or merge two arrays by taking alternate elements
-  from the two arrays are not compelling.
-
-
---- Major changes since March 2000:
-* Partial port to Linux
-* CF runtime refactored into CFRuntime.[hc], changed how
-  types are registered/known to the runtime
-* CFMachPort and CFMessagePort now public API.
-* Most private symbols now are flagged with
-  __private_extern__ so they aren't exported from
-  the binary.
-* Partial port to FreeBSD.
-* CFBundle, CFPlugIn APIs added to Darwin.
-
-
---- CF-lite to-do list:
-[Note: when it says "Apple has code" below, that usually
-means "Apple has some code it could provide to start an
-effort here", not "Apple has some code in the pipe, don't
-bother with this item". Anyone known to be doing work on
-any of these items will be listed here, including Apple.]
-* Some classes have a fair number of assertions, nearly all
-  related to parameter checking. More assertions are needed
-  nearly everywhere. The assertions that are there have been
-  often found to be valuable -- you just get a message about
-  some bad parameter and there's the bug.
-* More header doc is needed. CFArray.h and CFDictionary.h
-  are models.
-* An exception model, similar to Cocoa Foundation's. Apple
-  has some code for this already, and try/catch model like
-  C++ is simple enough to support; finally blocks a la Java
-  don't seem to be practical within the confines of ANSI C.
-* A CFFileDescriptor is needed which can act as a run loop
-  source. Or maybe it should be CFPipeDescriptor. This is
-  NOT something for general file handling -- just monitoring
-  a file descriptor which is a pipe (for which there are
-  notifications or other async activity).
-
-
-Contributors
-------------
-March 2000: partial port to Linux by Pedro Ivo Tavares (ptavares@iname.com).
-       This was mostly integrated by ckane@apple.com by CoreFoundation-5,
-       but the style was changed, and the hand-crafted Makefile, which is
-       new since this port, tries to take care of some of the things that
-       are needed for Linux (and build a libCoreFoundation.a instead of a
-       CoreFoundation.framework), but ckane does not have a Linux box and
-       can't finish that and test building.
-
-December 2000: port to FreeBSD by Sarwat Khan (sarwat@sarwat.net).
-       Port to FreeBSD, except for RunLoop.subproj items.  Integrated by
-       ckane@apple.com into CoreFoundation-8.  ckane also marginally
-       improved the Linux port in that version.
-
-March 2001: CoreFoundation-9, corresponding to CoreFoundation-197 in
-       Mac OS X, synchronizes Darwin CF with Mac OS X's released CF.
-
-May 2001: CoreFoundation-10, corresponding to CoreFoundation-206.5
-       synchronizes Darwin CF with TOT CoreFoundation.
-
-June 2001: Linux port maintenance by Robert Thompson <rothomp3@mac.com>.
-
-July 2001: Integrated addition of headerdoc for CFBinaryHeap.h from
-       Kevin Van Vechten <kevinvv@uclink4.berkeley.edu>.
-
-Sept 2001: CoreFoundation-14, sync with Mac OS X 10.1
-
-Oct 2001: More header doc (e.g., CFSet.h) and some CFTree implementation
-        from Kevin Van Vechten <kevinvv@uclink4.berkeley.edu>.
-
-Jan 2002: Windows(TM) port changes from Kevin Van Vechten <kevinvv@uclink4.berkeley.edu>.
-
-Feb 2002: Some Windows(TM) port changes from Aleskey Dukhnyakov, Andrew Dzubandovsky,
-       Roman Mukhin, and Sergey Zubarev; Orc Software<daa@orcsoftware.spb.ru>
-
-
diff --git a/SymbolAliases b/SymbolAliases
new file mode 100644 (file)
index 0000000..84b9421
--- /dev/null
@@ -0,0 +1,96 @@
+_kCFCalendarIdentifierBuddhist         _kCFBuddhistCalendar
+_kCFCalendarIdentifierChinese          _kCFChineseCalendar
+_kCFCalendarIdentifierGregorian                _kCFGregorianCalendar
+_kCFCalendarIdentifierHebrew           _kCFHebrewCalendar
+_kCFCalendarIdentifierISO8601          _kCFISO8601Calendar
+_kCFCalendarIdentifierIndian           _kCFIndianCalendar
+_kCFCalendarIdentifierIslamic          _kCFIslamicCalendar
+_kCFCalendarIdentifierIslamicCivil     _kCFIslamicCivilCalendar
+_kCFCalendarIdentifierJapanese         _kCFJapaneseCalendar
+_kCFCalendarIdentifierPersian          _kCFPersianCalendar
+_kCFCalendarIdentifierRepublicOfChina  _kCFRepublicOfChinaCalendar
+
+
+_kCFLocaleCalendarIdentifierKey                        _kCFLocaleCalendarIdentifier
+_kCFLocaleCalendarKey                          _kCFLocaleCalendar
+_kCFLocaleCollationIdentifierKey               _kCFLocaleCollationIdentifier
+_kCFLocaleCollatorIdentifierKey                        _kCFLocaleCollatorIdentifier
+_kCFLocaleCountryCodeKey                       _kCFLocaleCountryCode
+_kCFLocaleCurrencyCodeKey                      _kCFLocaleCurrencyCode
+_kCFLocaleCurrencySymbolKey                    _kCFLocaleCurrencySymbol
+_kCFLocaleDecimalSeparatorKey                  _kCFLocaleDecimalSeparator
+_kCFLocaleExemplarCharacterSetKey              _kCFLocaleExemplarCharacterSet
+_kCFLocaleGroupingSeparatorKey                 _kCFLocaleGroupingSeparator
+_kCFLocaleIdentifierKey                                _kCFLocaleIdentifier
+_kCFLocaleLanguageCodeKey                      _kCFLocaleLanguageCode
+_kCFLocaleMeasurementSystemKey                 _kCFLocaleMeasurementSystem
+_kCFLocaleScriptCodeKey                                _kCFLocaleScriptCode
+_kCFLocaleUsesMetricSystemKey                  _kCFLocaleUsesMetricSystem
+_kCFLocaleVariantCodeKey                       _kCFLocaleVariantCode
+_kCFDateFormatterAMSymbolKey                   _kCFDateFormatterAMSymbol
+_kCFDateFormatterCalendarKey                   _kCFDateFormatterCalendar
+_kCFDateFormatterCalendarIdentifierKey         _kCFDateFormatterCalendarIdentifier
+_kCFDateFormatterDefaultDateKey                        _kCFDateFormatterDefaultDate
+_kCFDateFormatterDefaultFormatKey              _kCFDateFormatterDefaultFormat
+_kCFDateFormatterEraSymbolsKey                 _kCFDateFormatterEraSymbols
+_kCFDateFormatterGregorianStartDateKey         _kCFDateFormatterGregorianStartDate
+_kCFDateFormatterIsLenientKey                  _kCFDateFormatterIsLenient
+_kCFDateFormatterLongEraSymbolsKey             _kCFDateFormatterLongEraSymbols
+_kCFDateFormatterMonthSymbolsKey               _kCFDateFormatterMonthSymbols
+_kCFDateFormatterPMSymbolKey                   _kCFDateFormatterPMSymbol
+_kCFDateFormatterQuarterSymbolsKey             _kCFDateFormatterQuarterSymbols
+_kCFDateFormatterShortMonthSymbolsKey          _kCFDateFormatterShortMonthSymbols
+_kCFDateFormatterShortQuarterSymbolsKey                _kCFDateFormatterShortQuarterSymbols
+_kCFDateFormatterShortStandaloneMonthSymbolsKey        _kCFDateFormatterShortStandaloneMonthSymbols
+_kCFDateFormatterShortStandaloneQuarterSymbolsKey      _kCFDateFormatterShortStandaloneQuarterSymbols
+_kCFDateFormatterShortStandaloneWeekdaySymbolsKey      _kCFDateFormatterShortStandaloneWeekdaySymbols
+_kCFDateFormatterShortWeekdaySymbolsKey                _kCFDateFormatterShortWeekdaySymbols
+_kCFDateFormatterStandaloneMonthSymbolsKey     _kCFDateFormatterStandaloneMonthSymbols
+_kCFDateFormatterStandaloneQuarterSymbolsKey   _kCFDateFormatterStandaloneQuarterSymbols
+_kCFDateFormatterStandaloneWeekdaySymbolsKey   _kCFDateFormatterStandaloneWeekdaySymbols
+_kCFDateFormatterTimeZoneKey                   _kCFDateFormatterTimeZone
+_kCFDateFormatterTwoDigitStartDateKey          _kCFDateFormatterTwoDigitStartDate
+_kCFDateFormatterVeryShortMonthSymbolsKey      _kCFDateFormatterVeryShortMonthSymbols
+_kCFDateFormatterVeryShortStandaloneMonthSymbolsKey    _kCFDateFormatterVeryShortStandaloneMonthSymbols
+_kCFDateFormatterVeryShortStandaloneWeekdaySymbolsKey  _kCFDateFormatterVeryShortStandaloneWeekdaySymbols
+_kCFDateFormatterVeryShortWeekdaySymbolsKey    _kCFDateFormatterVeryShortWeekdaySymbols
+_kCFDateFormatterWeekdaySymbolsKey             _kCFDateFormatterWeekdaySymbols
+_kCFNumberFormatterAlwaysShowDecimalSeparatorKey       _kCFNumberFormatterAlwaysShowDecimalSeparator
+_kCFNumberFormatterCurrencyCodeKey             _kCFNumberFormatterCurrencyCode
+_kCFNumberFormatterCurrencyDecimalSeparatorKey _kCFNumberFormatterCurrencyDecimalSeparator
+_kCFNumberFormatterCurrencyGroupingSeparatorKey        _kCFNumberFormatterCurrencyGroupingSeparator
+_kCFNumberFormatterCurrencySymbolKey           _kCFNumberFormatterCurrencySymbol
+_kCFNumberFormatterDecimalSeparatorKey         _kCFNumberFormatterDecimalSeparator
+_kCFNumberFormatterDefaultFormatKey            _kCFNumberFormatterDefaultFormat
+_kCFNumberFormatterExponentSymbolKey           _kCFNumberFormatterExponentSymbol
+_kCFNumberFormatterFormatWidthKey              _kCFNumberFormatterFormatWidth
+_kCFNumberFormatterGroupingSeparatorKey                _kCFNumberFormatterGroupingSeparator
+_kCFNumberFormatterGroupingSizeKey             _kCFNumberFormatterGroupingSize
+_kCFNumberFormatterInfinitySymbolKey           _kCFNumberFormatterInfinitySymbol
+_kCFNumberFormatterInternationalCurrencySymbolKey      _kCFNumberFormatterInternationalCurrencySymbol
+_kCFNumberFormatterIsLenientKey                        _kCFNumberFormatterIsLenient
+_kCFNumberFormatterMaxFractionDigitsKey                _kCFNumberFormatterMaxFractionDigits
+_kCFNumberFormatterMaxIntegerDigitsKey         _kCFNumberFormatterMaxIntegerDigits
+_kCFNumberFormatterMaxSignificantDigitsKey     _kCFNumberFormatterMaxSignificantDigits
+_kCFNumberFormatterMinFractionDigitsKey                _kCFNumberFormatterMinFractionDigits
+_kCFNumberFormatterMinIntegerDigitsKey         _kCFNumberFormatterMinIntegerDigits
+_kCFNumberFormatterMinSignificantDigitsKey     _kCFNumberFormatterMinSignificantDigits
+_kCFNumberFormatterMinusSignKey                        _kCFNumberFormatterMinusSign
+_kCFNumberFormatterMultiplierKey               _kCFNumberFormatterMultiplier
+_kCFNumberFormatterNaNSymbolKey                        _kCFNumberFormatterNaNSymbol
+_kCFNumberFormatterNegativePrefixKey           _kCFNumberFormatterNegativePrefix
+_kCFNumberFormatterNegativeSuffixKey           _kCFNumberFormatterNegativeSuffix
+_kCFNumberFormatterPaddingCharacterKey         _kCFNumberFormatterPaddingCharacter
+_kCFNumberFormatterPaddingPositionKey          _kCFNumberFormatterPaddingPosition
+_kCFNumberFormatterPerMillSymbolKey            _kCFNumberFormatterPerMillSymbol
+_kCFNumberFormatterPercentSymbolKey            _kCFNumberFormatterPercentSymbol
+_kCFNumberFormatterPlusSignKey                 _kCFNumberFormatterPlusSign
+_kCFNumberFormatterPositivePrefixKey           _kCFNumberFormatterPositivePrefix
+_kCFNumberFormatterPositiveSuffixKey           _kCFNumberFormatterPositiveSuffix
+_kCFNumberFormatterRoundingIncrementKey                _kCFNumberFormatterRoundingIncrement
+_kCFNumberFormatterRoundingModeKey             _kCFNumberFormatterRoundingMode
+_kCFNumberFormatterSecondaryGroupingSizeKey    _kCFNumberFormatterSecondaryGroupingSize
+_kCFNumberFormatterUseGroupingSeparatorKey     _kCFNumberFormatterUseGroupingSeparator
+_kCFNumberFormatterUseSignificantDigitsKey     _kCFNumberFormatterUseSignificantDigits
+_kCFNumberFormatterZeroSymbolKey               _kCFNumberFormatterZeroSymbol
+_kCFDateFormatterCalendarIdentifierKey         _kCFDateFormatterCalendarName
diff --git a/auto_stubs.h b/auto_stubs.h
deleted file mode 100644 (file)
index 9bea7af..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2008 Apple 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@
- */
-/*     auto_stubs.h
-       Copyright 2005-2007, Apple Inc. All rights reserved.
-*/
-
-#if !defined(AUTO_STUBS_H)
-#define AUTO_STUBS_H 1
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <malloc/malloc.h>
-#include <objc/objc.h>
-
-/* Stubs for functions in libauto. */
-
-typedef malloc_zone_t auto_zone_t;
-
-enum { AUTO_TYPE_UNKNOWN = -1, AUTO_UNSCANNED = 1, AUTO_OBJECT = 2, AUTO_MEMORY_SCANNED = 0, AUTO_MEMORY_UNSCANNED = AUTO_UNSCANNED, AUTO_OBJECT_SCANNED = AUTO_OBJECT, AUTO_OBJECT_UNSCANNED = AUTO_OBJECT | AUTO_UNSCANNED };
-typedef unsigned long auto_memory_type_t;
-
-CF_INLINE void *auto_zone(void) { return 0; }
-CF_INLINE void *auto_zone_allocate_object(void *zone, size_t size, auto_memory_type_t type, boolean_t rc, boolean_t clear) { return 0; }
-CF_INLINE const void *auto_zone_base_pointer(void *zone, const void *ptr) { return 0; }
-CF_INLINE void auto_zone_retain(void *zone, void *ptr) {}
-CF_INLINE unsigned int auto_zone_release(void *zone, void *ptr) { return 0; }
-CF_INLINE unsigned int auto_zone_retain_count(void *zone, const void *ptr) { return 0; }
-CF_INLINE void auto_zone_set_layout_type(void *zone, void *ptr, auto_memory_type_t type) {}
-CF_INLINE void auto_zone_write_barrier_range(void *zone, void *address, size_t size) {}
-CF_INLINE boolean_t auto_zone_is_finalized(void *zone, const void *ptr) { return 0; }
-CF_INLINE size_t auto_zone_size(void *zone, const void *ptr) { return 0; }
-CF_INLINE void auto_register_weak_reference(void *zone, const void *referent, void **referrer, uintptr_t *counter, void **listHead, void **listElement) {}
-CF_INLINE void auto_unregister_weak_reference(void *zone, const void *referent, void **referrer) {}
-CF_INLINE void auto_zone_register_thread(void *zone) {}
-CF_INLINE void auto_zone_unregister_thread(void *zone) {}
-CF_INLINE boolean_t auto_zone_is_valid_pointer(void *zone, const void *ptr) { return 0; }
-CF_INLINE auto_memory_type_t auto_zone_get_layout_type(auto_zone_t *zone, void *ptr) { return AUTO_UNSCANNED; }
-
-CF_INLINE void objc_collect_if_needed(unsigned long options) {}
-CF_INLINE BOOL objc_collecting_enabled(void) { return 0; }
-CF_INLINE id objc_allocate_object(Class cls, int extra) { return 0; }
-CF_INLINE id objc_assign_strongCast(id val, id *dest) { return (*dest = val); }
-CF_INLINE id objc_assign_global(id val, id *dest) { return (*dest = val); }
-CF_INLINE id objc_assign_ivar(id val, id dest, unsigned int offset) { id *d = (id *)((char *)dest + offset); return (*d = val); }
-CF_INLINE void *objc_memmove_collectable(void *dst, const void *src, size_t size) { return memmove(dst, src, size); }
-CF_INLINE BOOL objc_is_finalized(void *ptr) { return 0; }
-
-#endif /* ! AUTO_STUBS_H */
-