11

How can I convert a CFURLRef to a C++ std::string?

I also can convert from the CFURLRef to a CFStringRef by:

CFStringRef CFURLGetString ( CFURLRef anURL );

But now I have the same problem. How can I convert the CFStringRef to a std::string?

3ef9g
  • 781
  • 2
  • 9
  • 19

4 Answers4

12

A CFStringRef is toll free bridged to a NSString object, so if you're using Cocoa or Objective C in any way, converting is super simple:

NSString *foo = (NSString *)yourOriginalCFStringRef;
std::string *bar = new std::string([foo UTF8String]);

More detail can be found here.

Now, since you didn't tag this question with Cocoa or Objective-C, I'm guessing you don't want to use the Objective-C solution.

In this case, you need to get the C string equivalent from your CFStringRef:

const CFIndex kCStringSize = 128; 
char temporaryCString[kCStringSize];
bzero(temporaryCString,kCStringSize);
CFStringGetCString(yourStringRef, temporaryCString, kCStringSize, kCFStringEncodingUTF8);
std::string *bar = new std::string(temporaryCString);

I didn't do any error checking on this code and you may need to null terminate the string fetched via CFStringGetCString (I tried to mitigate that by doing bzero).

Community
  • 1
  • 1
Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
9

This function is possibly the most simple solution:

const char * CFStringGetCStringPtr ( CFStringRef theString, CFStringEncoding encoding );

Of course, there is a ctr for std::string(char*) which gives you this one-liner for the conversion:

std::string str(CFStringGetCStringPtr(CFURLGetString(anUrl),kCFStringEncodingUTF8));
Alan T.
  • 91
  • 1
  • 3
  • 5
    While this answer is simple, it bit me recently. I just discovered that in the docs, the comment next to `CFStringGetCStringPtr` says: `/* May return NULL at any time; be prepared for NULL */`. So be careful if you use this. – dgross Oct 30 '15 at 19:20
2

The safest way of achieving this would be:

CFIndex bufferSize = CFStringGetLength(cfString) + 1; // The +1 is for having space for the string to be NUL terminated
char buffer[bufferSize];

// CFStringGetCString is documented to return a false if the buffer is too small 
// (which shouldn't happen in this example) or if the conversion generally fails    
if (CFStringGetCString(cfString, buffer, bufferSize, kCFStringEncodingUTF8))
{
    std::string cppString (buffer);
}

The CFStringGetCString is not documented to return a NULL like CFStringGetCStringPtr can.

Make sure that you are using the correct CFStringEncoding type. I think that UTF8 encoding should be safe for most things.

You can check out Apple's documentation about CFStringGetCString at https://developer.apple.com/reference/corefoundation/1542721-cfstringgetcstring?language=objc

MultiColourPixel
  • 1,222
  • 10
  • 19
1

Here is my implementation of conversion function

std::string stdStringFromCF(CFStringRef s)
{
    if (auto fastCString = CFStringGetCStringPtr(s, kCFStringEncodingUTF8))
    {
        return std::string(fastCString);
    }
    auto utf16length = CFStringGetLength(s);
    auto maxUtf8len = CFStringGetMaximumSizeForEncoding(utf16length, kCFStringEncodingUTF8);
    std::string converted(maxUtf8len, '\0');

    CFStringGetCString(s, converted.data(), maxUtf8len, kCFStringEncodingUTF8);
    converted.resize(std::strlen(converted.data()));

    return converted;
}

Didn't test that yet.

Marek R
  • 32,568
  • 6
  • 55
  • 140