diff --git a/include/MacStd/CoreFoundation.hpp b/include/MacStd/CoreFoundation.hpp index 0ae82d3..ffb830d 100644 --- a/include/MacStd/CoreFoundation.hpp +++ b/include/MacStd/CoreFoundation.hpp @@ -44,9 +44,54 @@ namespace macstd { using cfdictionary = cfobject; using cferror = cfobject; using cfreadstream = cfobject; - using cfstring = cfobject; using cfurl = cfobject; + template , typename A = std::allocator> + void strcat(std::basic_string& str, CFStringRef h, CFStringEncoding encoding = kCFStringEncodingUTF8) + { + auto ptr = CFStringGetCStringPtr(h, encoding); + if (ptr) { + str += ptr; + return; + } + char buf[0x200]; + if (CFStringGetCString(h, buf, sizeof(buf)/sizeof(*buf), encoding)) { + str += buf; + return; + } + auto n = str.size(); + auto m = CFStringGetMaximumSizeForEncoding(CFStringGetLength(h), encoding); + str.resize(n + m); + if (!CFStringGetCString(h, &str[n], m, encoding)) [[unlikely]] + throw std::runtime_error("CFStringGetCString failed"); + str.resize(n + strlen(&str[n])); + } + + template , typename A = std::allocator> + void strcpy(std::basic_string& str, CFStringRef h, CFStringEncoding encoding = kCFStringEncodingUTF8) + { + str.clear(); + strcat(str, h, encoding); + } + + /// + /// Core Foundation string + /// + class cfstring : public cfobject + { + public: + cfstring(CFStringRef h) : cfobject(h) {} + + cfstring(const char *s) : cfobject(CFStringCreateWithCString(kCFAllocatorDefault, s, kCFStringEncodingUTF8)) + { + if (!valid()) [[unlikely]] + throw std::bad_alloc(); + } + + template + cfstring(const std::basic_string &s) : cfstring(s.c_str()) {} + }; + /// /// Core Foundation runtime error /// @@ -126,18 +171,18 @@ namespace macstd { /// static std::string message(CFErrorRef error) { - macstd::cfstring description(CFErrorCopyDescription(error)); - if (description.valid() && CFStringGetLength(description) > 0) { - auto str = CFStringGetCStringPtr(description, kCFStringEncodingUTF8); - if (str) - return str; + std::string msg; + cfstring cfstr(CFErrorCopyDescription(error)); + if (cfstr.valid() && CFStringGetLength(cfstr) > 0) { + strcpy(msg, cfstr, kCFStringEncodingUTF8); + } else { + msg = "Core Foundation error "; + msg += std::to_string(CFErrorGetCode(error)); } - std::string msg("Core Foundation error " + std::to_string(CFErrorGetCode(error))); - macstd::cfstring domain(CFErrorGetDomain(error)); + cfstring domain(CFErrorGetDomain(error)); if (domain.valid() && CFStringGetLength(domain) > 0) { - auto str = CFStringGetCStringPtr(domain, kCFStringEncodingUTF8); - if (str) - msg += std::string(", domain ") + str; + msg += ", domain "; + strcat(msg, domain, kCFStringEncodingUTF8); } return msg; } diff --git a/include/MacStd/Security.hpp b/include/MacStd/Security.hpp index 0c11d9c..1555411 100644 --- a/include/MacStd/Security.hpp +++ b/include/MacStd/Security.hpp @@ -62,14 +62,15 @@ namespace macstd case errAuthorizationDenied: return "Authorization was denied"; case errAuthorizationInteractionNotAllowed: return "User interaction not allowed for authorization"; } + std::string msg; cfstring cfstr(SecCopyErrorMessageString(num, NULL)); - if (!cfstr.valid()) - return "Security Framework error " + std::to_string(num); - auto ptr = CFStringGetCStringPtr(cfstr, kCFStringEncodingUTF8); - if (!ptr) - return "Security Framework error " + std::to_string(num); - std::string str(ptr); - return str; + if (cfstr.valid() && CFStringGetLength(cfstr) > 0) { + strcpy(msg, cfstr, kCFStringEncodingUTF8); + } else { + msg = "Security Framework error "; + msg += std::to_string(num); + } + return msg; } };