{"id":22796427,"url":"https://github.com/macmade/cfpp","last_synced_at":"2025-04-19T13:13:26.313Z","repository":{"id":14763517,"uuid":"17484903","full_name":"macmade/CFPP","owner":"macmade","description":"C++ wrapper for CoreFoundation base classes.","archived":false,"fork":false,"pushed_at":"2024-05-08T07:27:01.000Z","size":2014,"stargazers_count":73,"open_issues_count":1,"forks_count":20,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-29T08:11:20.914Z","etag":null,"topics":["c-plus-plus","corefoundation","framework","interoperability","wrapper"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/macmade.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"macmade"}},"created_at":"2014-03-06T16:47:52.000Z","updated_at":"2025-03-27T21:01:59.000Z","dependencies_parsed_at":"2024-05-07T16:41:47.235Z","dependency_job_id":"0c8f8f72-9c7a-44d2-9b3f-42522b1c1223","html_url":"https://github.com/macmade/CFPP","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FCFPP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FCFPP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FCFPP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/macmade%2FCFPP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/macmade","download_url":"https://codeload.github.com/macmade/CFPP/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249701676,"owners_count":21312758,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-plus-plus","corefoundation","framework","interoperability","wrapper"],"created_at":"2024-12-12T05:12:58.204Z","updated_at":"2025-04-19T13:13:26.295Z","avatar_url":"https://github.com/macmade.png","language":"C","funding_links":["https://github.com/sponsors/macmade"],"categories":[],"sub_categories":[],"readme":"CoreFoundation++\n================\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/macmade/CFPP/ci-mac.yaml?label=macOS\u0026logo=apple)](https://github.com/macmade/CFPP/actions/workflows/ci-mac.yaml)\n[![Build Status](https://img.shields.io/github/actions/workflow/status/macmade/CFPP/ci-win.yaml?label=Windows\u0026logo=windows)](https://github.com/macmade/CFPP/actions/workflows/ci-win.yaml)\n[![Issues](http://img.shields.io/github/issues/macmade/CFPP.svg?logo=github)](https://github.com/macmade/CFPP/issues)\n![Status](https://img.shields.io/badge/status-active-brightgreen.svg?logo=git)\n![License](https://img.shields.io/badge/license-mit-brightgreen.svg?logo=open-source-initiative)  \n[![Contact](https://img.shields.io/badge/follow-@macmade-blue.svg?logo=twitter\u0026style=social)](https://twitter.com/macmade)\n[![Sponsor](https://img.shields.io/badge/sponsor-macmade-pink.svg?logo=github-sponsors\u0026style=social)](https://github.com/sponsors/macmade)\n\n### C++ wrapper for CoreFoundation base classes\n\nTable of Contents\n-----------------\n\n  1. [About CoreFoundation](#1)\n  2. [About CoreFoundation++](#2)\n  3. [Availability / Platforms](#3)\n  4. [Available / Wrapped classes](#4)\n  5. [Example](#5)\n  6. [Documentation](#6)\n  7. [To-Do](#7)\n  8. [License](#8)\n  9. [Repository Infos](#9)\n\n\u003ca name=\"1\"\u003e\u003c/a\u003e\nAbout CoreFoundation\n--------------------\n\nCore Foundation (CF) is a C API available in Mac OS X \u0026 iOS:\n\n\u003e\u003e Core Foundation is a framework that provides fundamental software services\n\u003e\u003e useful to application services, application environments, and to applications\n\u003e\u003e themselves. Core Foundation also provides abstractions for common data types,\n\u003e\u003e facilitates internationalization with Unicode string storage, and offers\n\u003e\u003e a suite of utilities such as plug-in support, XML property lists, URL\n\u003e\u003e resource access, and preferences.\n\n*Source: Core Foundation Framework Reference*\n\nTo learn more about CoreFoundation, please read the «[Core Foundation Design Concepts][1]» guide.\n\n[1]: https://developer.apple.com/library/mac/documentation/corefoundation/Conceptual/CFDesignConcepts/CFDesignConcepts.html#//apple_ref/doc/uid/10000122i\n\n\u003ca name=\"2\"\u003e\u003c/a\u003e\nAbout CoreFoundation++\n----------------------\n\nCoreFoundation++ (CFPP) is a C++ wrapper for Apple's CoreFoundation API.\n\nCoreFoundation is a powerful C API which allows object-oriented style coding and reference counting memory management in C and provides a lot of useful classes.  \nCoreFoundation is intensively used in Apple's low-level frameworks, and is also used as a base for some classes of the Foundation (Objective-C) framework.\n\nThat being said, programming with CoreFoundation can sometimes be a real pain.  \nEven the simplest things takes several lines of code, which leads to obvious maintainability issues.  \nThis is especially true when mixing CoreFoundation with C++, because you'll need to cast almost everything.\n\nCoreFoundation++ uses the good parts of the C++ language to wrap the most used CoreFoundation classes, and to makes them easy to use, for instance by using operator overloading.\n\n\u003ca name=\"3\"\u003e\u003c/a\u003e\nAvailability / Platforms\n------------------------\n\nCoreFoundation++ is available for **MacOS X, iOS and Windows** (Windows builds assume the CoreFoundation DLLs are available), and can be compiled for **32 bits or 64 bits** systems.\n  \nA complete Xcode project is available, providing the following targets:\n\n    - A Mac OS X static library\n    - A Mac OS X dynamic library\n    - A Mac OS X framework\n    - An iOS static library\n\nOn Windows, a VisualStudio solution is provided with the following configurations:\n\n    - DLL - VC120_XP\n    - DLL - VC140_XP\n    - Static library - VC120_XP\n    - Static library - VC140_XP\n\n\u003ca name=\"4\"\u003e\u003c/a\u003e\nAvailable / Wrapped classes\n---------------------------\n\n    - CFType              =\u003e CF::Type (abstract)\n    - CFBoolean           =\u003e CF::Boolean\n    - CFNumber            =\u003e CF::Number\n    - CFString            =\u003e CF::String\n    - CFDate              =\u003e CF::Date\n    - CFData              =\u003e CF::Data\n    - CFMutableData       =\u003e CF::Data\n    - CFURL               =\u003e CF::URL\n    - CFArray             =\u003e CF::Array\n    - CFMutableArray      =\u003e CF::Array\n    - CFDictionary        =\u003e CF::Dictionary\n    - CFMutableDictionary =\u003e CF::Dictionary\n    - CFUUIDRef           =\u003e CF::UUID\n    - CFErrorRef          =\u003e CF::Error\n    - CFReadStream        =\u003e CF::ReadStream\n    - CFWriteStream       =\u003e CF::WriteStream\n\n\u003ca name=\"5\"\u003e\u003c/a\u003e\nExample\n-------\n\nLet's say you want to create a CFDictionary containing two keys, both CFString objects, the second one created from an external char pointer.  \nThe value for the first key is a CFData object, created from an external data buffer, while the value for the second key is a CFArray object containing two values, a CFNumber object and a CFURL object, created from an external char pointer.\n\nSo let's assume the following:\n\n    extern const char * externalKey;\n    extern const char * externalByteBuffer;\n    extern size_t       externalByteBufferLength;\n    extern const char * externalURL;\n\n### Example with CoreFoundation++:\n\nPeople used to the CoreFoundation API knows that creating dictionaries and arrays can be extremely painful.  \nBut with CoreFoundation++, it's extremely easy:\n\n    {\n        CF::Number number = 42;\n        CF::URL    url    = externalURL;\n        CF::Array  array;\n        \n        /* Adds number and URL to the array */\n        array \u003c\u003c number \u003c\u003c url;\n        \n        CF::Data data\n        (\n            ( CF::Data::Byte * )externalByteBuffer,\n            ( CFIndex )externalByteBufferLength\n        );\n        \n        CF::Dictionary dictionary;\n        \n        /* Adds the two key/value pairs in the dictionary */\n        dictionary \u003c\u003c CF::Pair( \"key-1\",     data );\n        dictionary \u003c\u003c CF::Pair( externalKey, data );\n        \n        /* Prints the dictionary */\n        std::cout \u003c\u003c dictionary \u003c\u003c std::endl;\n        \n        /* Nothing more, memory is automatically managed... */\n    }\n\n### Example with CoreFoundation:\n\nFor comparison, with the CoreFoundation C API, you will have write the following code:\n\n    {\n        /* First of all, we need a C array to store our dictionary keys */\n        CFStringRef keys[ 2 ];\n        \n        /*\n         * Let's create the dictionary keys. First key is straightforward because\n         * of the CFSTR macro, while the second one is less...\n         */\n        keys[ 0 ] = CFSTR( \"key-1\" );\n        keys[ 1 ] = CFStringCreateWithCString\n        (\n            ( CFAllocatorRef )NULL,\n            externalKey,\n            kCFStringEncodingUTF8\n        );\n        \n        /* Let's create the data object from the external byte buffer */\n        CFDataRef data = CFDataCreate\n        (\n            ( CFAllocatorRef )NULL,\n            ( const UInt8 * )externalByteBuffer,\n            ( CFIndex )externalByteBufferLength\n        );\n        \n        /*\n         * Now, let's create some number object. Note that we need a temporary\n         * variable, as we need to pass an address of a primitive type...\n         */\n        int tempInt        = 42;\n        CFNumberRef number = CFNumberCreate\n        (\n            ( CFAllocatorRef )NULL,\n            kCFNumberSInt32Type,\n            \u0026tempInt\n        );\n        \n        /*\n         * Now, create an URL object. Note that we need to create a temporary\n         * CFString object\n         */\n        CFStringRef tempStringURL = CFStringCreateWithCString\n        (\n            ( CFAllocatorRef )NULL,\n            externalURL,\n            kCFStringEncodingUTF8\n        );\n        CFURLRef url = CFURLCreateWithString\n        (\n            ( CFAllocatorRef )NULL,\n            tempStringURL,\n            NULL\n        );\n        \n        /* Before creating the array, we need a C array to store the values */\n        CFTypeRef arrayValues[ 2 ];\n        \n        arrayValues[ 0 ] = number;\n        arrayValues[ 1 ] = url;\n        \n        /* Now we can create the array... */\n        CFArrayRef array = CFArrayCreate\n        (\n            ( CFAllocatorRef )NULL,\n            ( const void ** )arrayValues,\n            2,\n            \u0026kCFTypeArrayCallBacks\n        );\n        \n        /* Now, of course, we need a C array to store the dictionary values */\n        CFTypeRef values[ 2 ];\n        \n        values[ 0 ] = data;\n        values[ 1 ] = array;\n        \n        /* Finally, we can create our dictionary... */\n        CFDictionaryRef dictionary = CFDictionaryCreate\n        (\n            ( CFAllocatorRef )NULL,\n            ( const void ** )keys,\n            ( const void ** )values,\n            2,\n            \u0026kCFTypeDictionaryKeyCallBacks,\n            \u0026kCFTypeDictionaryValueCallBacks\n        );\n        \n        /* And of course, as we allocated objects, we need to release them... */\n        CFRelease( keys[ 1 ] );\n        CFRelease( data );\n        CFRelease( number );\n        CFRelease( tempStringURL );\n        CFRelease( url );\n        CFRelease( array );\n        \n        /* That's it, prints the dictionary and release it */\n        CFShow( dictionary );\n        CFRelease( dictionary );\n    }\n\n\u003ca name=\"6\"\u003e\u003c/a\u003e\nDocumentation\n-------------\n\n### Memory management\n\nCoreFoundation uses a reference counting memory management scheme.  \nAll allocated, copied or retained objects must be explicitly released, when the ownership is no longer needed.\n\nIt's the same as in Objective-C (with MRC), with the difference that there's no autorelease mechanism.\n\nCoreFoundation++ manages the memory for you, meaning you no longer have to call `CFRelease` explicitly.  \nAll CF++ wrappers act as a shared pointer (`std::shared_ptr`).\n\nThey will automatically retain ownership of a CoreFoundation object, and several CF++ wrappers may own the same object.  \nThe CoreFoundation object is destroyed and its memory deallocated when either of the following happens:\n\n  * The last remaining CF++ wrapper owning the object is destroyed\n  * The last remaining CF++ wrapper owning the object is assigned another CoreFoundation object via operator `=`.\n\nFor instance:\n\n    {\n        int x                = 42\n        CFNumberRef cfNumber = CFNumberCreate\n        (\n            ( CFAllocatorRef )NULL,\n            kCFNumberSInt32Type,\n            \u0026x\n        );\n        \n        CF::Number num1 = cfNumber;\n        \n        /*\n         * CF::Number will retain the CFNumber object, so the one\n         * we allocated explicitly can be released safely\n         */\n        CFRelease( cfNumber );\n        \n        {\n            CF::Number num2\n            \n            /* num1 and num2 owns the same CoreFoundation object */\n            num2 = num1:\n        }\n        \n        /*\n         * End of scope - num2 is destroyed and will release\n         * the CFNumber object, which is still retained by num1\n         */\n    }\n        \n    /*\n     * End of scope - num1 is destroyed and will release\n     * the CFNumber object, which will be deallocated.\n     */\n\n### CF::Type\n\n`CF::Type` is the base abstract class for all CF++ wrappers.\n\n**Equality:**\n\nEvery CF++ wrapper can be compared using the `==` operator.  \nIt will evaluate to `false` is the two operands are not of the same type. Otherwise, it will internally use `CFCompare` to test for equality:\n\n    CF::Number  x;\n    CF::Boolean y;\n    \n    if( x == y ) { /* ... */ }\n    \n**Casting:**\n\nCF++ wrappers can be used transparently as CoreFoundation objects, thanks to the C++ cast operator.  \nIt means you can use a CF++ wrapper object as argument to a CoreFoundation function:\n\n    CF::String s = \"hello, world\";\n    \n    CFShow( s );\n    \nBesides, all CF++ wrappers can be created with CoreFoundation objects:\n\n    CFStringRef cfS = CFSTR( \"hello, world\" );\n    CF::String  s( cfS );\n    /* Or also: */\n    CF::String s = cfS;\n\n**Debug output:**\n\nCF++ wrappers can be used with C++ `ostream` objects (like `std::cout`).  \nIt will print the same output as a call to `CFShow`:\n\n    CF::Number x;\n    \n    /* Both will produce the same output */\n    CFShow( x );\n    std::cout \u003c\u003c x \u003c\u003c std::endl;\n\n### CF::Boolean\n\n`CF::Boolean` is a wrapper for `CFBooleanRef`.\n\n**Creation:**\n\n`CF::Boolean` can be instantiated using another `CF::Boolean`, a `CFBooleanRef` or a `bool`:\n\n    CF::Boolean b1 = kCFBooleanTrue;\n    CF::Boolean b2 = b1;\n    CF::Boolean b3 = false;\n\n**Mutation:**\n\n`CF::Boolean` value can be set through the `=` operator:\n\n    CF::Boolean b1 = false;\n    b1             = true;\n    \n**Equality:**\n\n`CF::Boolean` can be compared to another `CF::Boolean`, a `CFBooleanRef` or a `bool`:\n\n    CF::Boolean b1 = false;\n    CF::Boolean b2 = true;\n    \n    if( b1 == b2 )             { /* ... */ }\n    if( b1 == kCFBooleanTrue ) { /* ... */ }\n    if( b1 == true )           { /* ... */ }\n\n**Casting:**\n\n`CF::Boolean` can be safely casted to a `bool` or `CFBooleanRef`:\n\n    CF::Boolean  b1     = true;\n    CFBooleanRef cfBool = b1;\n    bool         b      = b1;\n        \n### CF::Number\n\n`CF::Number` is a wrapper for `CFNumberRef`.\n\n**Creation:**\n\n`CF::Number` can be instantiated using another `CF::Number`, a `CFNumberRef` or an integral or floating point type:\n\n    CF::Number n1 = someCFNumberRefObject;\n    CF::Number n2 = n1;\n    CF::Number n3 = 42;\n    CF::Number n4 = 42.0f;\n\n**Mutation:**\n\n`CF::Number` value can be set/transformed through every operator:\n    \n    CF::Number n1 = 42;\n    CF::Number n2 = 10;\n    \n    n1--;\n    n2++;\n    \n    n1 += n2;\n    n1 ^= n2\n    n2 += 10;\n    n1 \u0026= 0xFF00;\n    n2 /= n1;\n    n1  = n1 | n2;\n    n1  = n1 \u003e\u003e 8;\n    \n    /* etc... */\n\nNote that you can determine is a `CF::Number` objects contains a floating point value using the `IsFloatType` method.\n\n**Equality:**\n\n`CF::Number` can be compared to another `CF::Number`, a `CFNumberRef` or a an integral or floating point type.  \nAll comparison operators are available:\n\n    CF::Number n1 = 42;\n    CF::Number n2 = 10;\n    \n    if( ( n1 != someCFNumberRefObject || n1 != n2 ) \u0026\u0026 n1 == 10 ) { /* ... */ }\n    if( n1 != 10.0f || n1 \u003e= 20 || n2 \u003c 40.0f )                   { /* ... */ }\n    if( n1 || n2 )                                                { /* ... */ }\n\n**Casting:**\n\n`CF::Number` can be safely casted to a `CFNumberRef` or a an integral or floating point type:\n\n    CF::Number  n1     = 42;\n    CFNumberRef cfNum  = n1;\n    int         i      = n1;\n    long        l      = n1;\n    double      d      = n1;\n    int64_t     i64    = n1;\n    \n### CF::String\n\nCF::String is a wrapper for CFStringRef.\n\n**Creation:**\n\n`CF::String` can be instantiated using another CF::String, a CFStringRef, a `std::string` or an `char` pointer:\n\n    CF::String s1 = someCFStringRefObject;\n    CF::String s2 = s1;\n    CF::String s3 = std::string( \"hello, world\" );\n    CF::String s4 = \"hello, world\";\n    \n**Mutation:**\n\n`CF::String` value can be set/transformed through the operator `=` and `+=` operator:\n    \n    CF::String s = \"hello\"\n    s           += \", world\"\n    s\t\t\t = \"hello, universe\";\n\n**Equality:**\n\n`CF::String` can be compared to another `CF::String`, a `CFStringRef`, a `std::string` or a `char` pointer:\n\n    CF::String s1 = \"hello, world\";\n    CF::String s2 = \"hello, universe\";\n    \n    if( s1 == someCFStringRefObject )            { /* ... */ }\n    if( s1 != s2 )                               { /* ... */ }\n    if( s1 == std::string( \"hello, universe\" ) ) { /* ... */ }\n    if( s1 != \"hello, universe\" )                { /* ... */ }\n\nCasting:\n\n`CF::String` can be safely casted to a `CFStringRef`, a `std::string` or a `char` pointer:\n\n    CF::String  s1  = \"hello, world\";\n    CFStringRef cfS = s1;\n    std::string s   = s1;\n    char      * cp  = s1;\n\n**Character access:**\n\nIndividual characters can be accessed through the `[]`operator:\n\n    CF::String s1 = \"hello, world\";\n    char       c1 = s1[  1 ] /* 'e' */;\n    char       c2 = s1[ -1 ] /* 'd' */;\n\n### CF::Array\n\n`CF::Array` is a wrapper for `CFArrayRef`.\n\n**Creation:**\n\n`CF::Array` can be instantiated using another `CF::Array`, or a `CFArrayRef`.  \nAll `CF::Array` objects are created as mutable, and an initial capacity can be passed to the constructor:\n\n    CF::Array a1 = someCFArrayRefObject;\n\tCF::Array a2 = a1;\n\tCF::Array a3( 100 );\n\n**Mutation:**\n\n`CFTypeRef` or `CF:Type` objects can be added to an array using the `\u003c\u003c` operator:\n\n    CF::Array  a;\n    CF::Number n = 42;\n    CF::String s = \"hello, world\";\n    \n    a \u003c\u003c someCFTypeRefObject;\n    a \u003c\u003c n;\n    a \u003c\u003c s;\n    \n    /* Or simply: */\n    a \u003c\u003c someCFTypeRefObject \u003c\u003c n \u003c\u003c s;\n\nAn other `CF:Array` can be appended using the `+=` operator:\n\n    CF::Array  a1;\n    CF::Array  a2;\n    CF::Number n = 42;\n    CF::String s = \"hello, world\";\n    \n    a1 \u003c\u003c n;\n    a2 \u003c\u003c s;\n    a1 += a2;\n\n**Element access:**\n\nValues can be retrieved using the `[]` operator:\n\n    CF::Array  a;\n    CF::Number n1 = 42;\n    CF::String s1 = \"hello, world\";\n    \n    a \u003c\u003c someCFTypeRefObject \u003c\u003c n1 \u003c\u003c s1;\n    \n    CFTypeRef  cfObject = a[ 0 ];\n    CF::Number n2       = a[ 1 ];\n    CF::String s2       = a[ 2 ];\n\n**Casting:**\n\n`CF::Array` can be safely casted to a `CFArrayRef`:\n\n    CF::Array  a( 100 );\n    CFArrayRef cfA = a;\n\n**Other methods:**\n\nOther `CFArrayRef` methods are available, like `GetCount`, `RemoveValueAtIndex`, `ExchangeValuesAtIndices`, etc.\n\n### CF::Dictionary\n\n`CF::Dictionary` is a wrapper for `CFDictionaryRef`.\n\n**Creation:**\n\n`CF::Dictionary` can be instantiated using another `CF::Dictionary`, or a `CFDictionaryRef`.  \nAll `CF::Dictionary` objects are created as mutable, and an initial capacity can be passed to the constructor:\n\n    CF::Dictionary d1 = someCFDictionaryRefObject;\n\tCF::Dictionary d2 = d1;\n\tCF::Dictionary d3( 100 );\n\n**Mutation:**\n\nA key/value pair can be added to a dictionary using the `+=` operator.  \nTo create a key/value pair, use the `CF::Pair` object, which can be constructed with `CFTypeRef` or `CF:Type` objects.  \nNote that `std::string` or `char` pointers can be safely used as keys:\n\n    CF::Dictionary d;\n    CF::String     s = \"key\";\n    CF::Number     n = 42;\n    \n    d += CF::Pair( someCFTypeRefObject, someOtherCFTypeRefObject );\n    d += CF::Pair( s, n );\n    d += CF::Pair( std::string( \"key\" ), n );\n    d += CF::Pair( \"key\", n );\n\nA key can be replaced using the `\u003c\u003c` operator:\n\n\n    CF::Dictionary d;\n    CF::Number     n1 = 42;\n    CF::Number     n2 = 43;\n    \n    d += CF::Pair( s, n1 );\n    d \u003c\u003c CF::Pair( s, n2 );\n\n**Casting:**\n\n`CF::Dictionary` can be safely casted to a `CFDictionaryRef`:\n\n    CF::Dictionary  d( 100 );\n    CFDictionaryRef cfD = d;\n\n**Other methods:**\n\nOther `CFDictionaryRef` methods are available, like `GetCount`, `ContainsKey`, `RemoveValue`, etc.\n\n### CF::Date\n\n`CF::Date` is a wrapper for `CFDateRef`.\n\n**Creation:**\n\n`CF::Date` can be instantiated using another `CF::Date`, a `CFDateRef` or a `CFAbsoluteTime`.  \nWhen a `CF::Date` object is created without argument, it defaults to the current date:  \n\n    CF::Date d1;\n    CF::Date d2 = someCFDateRefObject;\n\tCF::Date d3 = d1;\n\tCF::Date d4 = 100;\n\n**Mutation:**\n\n`CF::Date` value can be set/transformed through many operators:\n\n    CF::Date d1;\n    CF::Date d2;\n    \n    d1++;\n    d2--;\n    \n    d1 += d2;\n    d2  = d1 + d2;\n\n**Equality:**\n\n`CF::Date` can be compared to another `CF::Date`, a `CFDateRef` or a `CFAbsoluteTime`.\nAlmost all comparison operators are available:\n\n    CF::Date d1;\n    CF::Date d2;\n    \n    if( d1 == someCFDateRefObject ) { /* ... */ }\n    if( d1 != d2 )                  { /* ... */ }\n    if( d1 \u003e  100 )                 { /* ... */ }\n    if( d1 \u003c= d2 )                  { /* ... */ }\n\n**Casting:**\n\n`CF::Date` can be safely casted to a `CFDateRef` or `CFAbsoluteTime`:\n\n    CF::Date       d;\n    CFDateRef      cfD = d;\n    CFAbsoluteTime t   = d;\n\n### CF::Data\n\n`CF::Data` is a wrapper for `CFDataRef`.\n\n**Creation:**\n\n`CF::Data` can be instantiated using another `CF::Data`, a `CFDataRef`, a `CFStringRef`, a `std::string` or a `CF::Data::Byte` pointer: \n\n    const char * cp = \"hello, world\";\n    CF::Data     d1 = someCFDataRefObject;\n    CF::Data     d2 = someCFStringRefObject;\n\tCF::Data     d3 = d1;\n\tCF::Data     d4 = std::string( \"hello, world\" );\n\tCF::Data     d5( ( CF::Data::Byte * )cp, 12 );\n\n**Mutation:**\n\nData can be appended using the `+=` operator.  \nThe following types can be appended: `CF::Data::Byte`, `CFStringRef`, `CFDataRef`and `std::string`:\n\n    CF::Date d;\n    \n    d += 42;\n    d += someCFtringRefObject;\n    d += someCFDataRefObject;\n    d += std::string( \"hello, world\" );\n\nTo append a `CF::Data::Byte` pointer, une the `AppendBytes` method.\n\n**Element access:**\n\nSingle bytes can be retrieved as `CF::Data::Byte` using the `[]` operator:\n\n    CF::Date       d( std::string( \"hello, world\" ) );\n    CF::Date::byte b = d[ 2 ];\n\n**Casting:**\n\n`CF::Data` can be safely casted to a `CFDataRef`, `std::string` and `CF::Data::Byte` pointer:\n\n    CF::Data         d;\n    CFDateRef        cfD = d;\n    std::string      s   = d;\n    CF::Data::Byte * bp  = d;\n\n**Other methods:**\n\nOther `CFDataRef` methods are available, like `GetLength`, `GetMutableBytePtr`, `ReplaceBytes`, etc.\n\n### CF::URL\n\n`CF::URL` is a wrapper for `CFURLRef`.\n\n**Creation:**\n\n`CF::URL` can be instantiated using another `CF::URL`, a `CFURLRef`, a `CFStringRef`, or a `std::string`: \n\n    CF::URL url1 = someCFURLRefObject;\n    CF::URL url2 = someCFStringRefObject;\n    CF::URL url3 = url1;\n    CF::URL url4 = std::string( \"http://www.example.org/\" );\n\n**Equality:**\n\nCF::URL can be compared to another CF::URL, a CFURLRef, a CFStringRef, or a std::string:\n\n    CF::URL url1( \"http://www.example.org/\" );\n    CF::URL url2( \"http://www.xs-labs.com/\" );\n    \n    if( url1 == url2 )                                     { /* ... */ }\n    if( url1 != someCFURLRefObject )                       { /* ... */ }\n    if( url1 == someCFStringRefObject )                    { /* ... */ }\n    if( url1 != std::string( \"http://www.xs-labs.com/\" ) ) { /* ... */ }\n\n**Mutation:**\n\nPath components can be appended to a `CF::URL` using the `/=` operator:\n\n    CF::URL url1( \"http://www.example.org/\" );\n    \n    url /= \"path\";\n    url /= \"to\";\n    url /= \"some\";\n    url /= \"page\";\n\n**Parts access:**\n\nIndividual URL parts can be accessed as `std::string` using the `[]` operator, specifying a `CF::URL::Part`, or through regular methods:\n\n    CF::URL url( \"http://www.example.org/\" );\n    \n    std::string scheme = url[ CF::URL::PartScheme ];\n    std::string host   = url.GetHostName();\n\n**Casting:**\n\n`CF::URL` can be safely casted to a `CFURLRef`, `CFStringRef`, or `std::string`:\n\n    CF::URL     url( \"http://www.example.org/\" );\n    CFURLRef    cfUrl = url;\n    CFStringRef cfS   = url;\n    std::string s     = url;\n\n\u003ca name=\"7\"\u003e\u003c/a\u003e\nTo-Do\n-----\n\nThe following classes will be implemented soon:\n\n    - CFBundle\n    - CFDateFormatter\n    - CFNotificationCenter\n    - CFNull\n    - CFNumberFormatter\n    - CFRunLoop\n    - CFRunLoopSource\n    - CFRunLoopTimer\n    - CFSocket\n    - CFSet\n    - CFMutableSet\n\n\u003ca name=\"8\"\u003e\u003c/a\u003e\nLicense\n-------\n\nCoreFoundation++ is released under the terms of the MIT License.\n\n\u003ca name=\"9\"\u003e\u003c/a\u003e\nRepository Infos\n----------------\n\n    Owner:\t\t\tJean-David Gadina - XS-Labs\n    Web:\t\t\twww.xs-labs.com\n    Blog:\t\t\twww.noxeos.com\n    Twitter:\t\t@macmade\n    GitHub:\t\t\tgithub.com/macmade\n    LinkedIn:\t\tch.linkedin.com/in/macmade/\n    StackOverflow:\tstackoverflow.com/users/182676/macmade\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacmade%2Fcfpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmacmade%2Fcfpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmacmade%2Fcfpp/lists"}