180814287SRaphael Isemann //===-- CFCString.cpp -----------------------------------------------------===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 930fdc8d8SChris Lattner #include "CFCString.h" 1030fdc8d8SChris Lattner #include <glob.h> 11b9c1b51eSKate Stone #include <string> 1230fdc8d8SChris Lattner 1330fdc8d8SChris Lattner // CFCString constructor 14b9c1b51eSKate Stone CFCString::CFCString(CFStringRef s) : CFCReleaser<CFStringRef>(s) {} 1530fdc8d8SChris Lattner 1630fdc8d8SChris Lattner // CFCString copy constructor 17b9c1b51eSKate Stone CFCString::CFCString(const CFCString &rhs) : CFCReleaser<CFStringRef>(rhs) {} 1830fdc8d8SChris Lattner 1930fdc8d8SChris Lattner // CFCString copy constructor 20b9c1b51eSKate Stone CFCString &CFCString::operator=(const CFCString &rhs) { 2130fdc8d8SChris Lattner if (this != &rhs) 2230fdc8d8SChris Lattner *this = rhs; 2330fdc8d8SChris Lattner return *this; 2430fdc8d8SChris Lattner } 2530fdc8d8SChris Lattner 26b9c1b51eSKate Stone CFCString::CFCString(const char *cstr, CFStringEncoding cstr_encoding) 27b9c1b51eSKate Stone : CFCReleaser<CFStringRef>() { 28b9c1b51eSKate Stone if (cstr && cstr[0]) { 29b9c1b51eSKate Stone reset( 30b9c1b51eSKate Stone ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); 3130fdc8d8SChris Lattner } 3230fdc8d8SChris Lattner } 3330fdc8d8SChris Lattner 3430fdc8d8SChris Lattner // Destructor 35*fd2433e1SJonas Devlieghere CFCString::~CFCString() = default; 3630fdc8d8SChris Lattner 37b9c1b51eSKate Stone const char *CFCString::GetFileSystemRepresentation(std::string &s) { 3830fdc8d8SChris Lattner return CFCString::FileSystemRepresentation(get(), s); 3930fdc8d8SChris Lattner } 4030fdc8d8SChris Lattner 41b9c1b51eSKate Stone CFStringRef CFCString::SetFileSystemRepresentation(const char *path) { 4230fdc8d8SChris Lattner CFStringRef new_value = NULL; 4330fdc8d8SChris Lattner if (path && path[0]) 44b9c1b51eSKate Stone new_value = 45b9c1b51eSKate Stone ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); 4630fdc8d8SChris Lattner reset(new_value); 4730fdc8d8SChris Lattner return get(); 4830fdc8d8SChris Lattner } 4930fdc8d8SChris Lattner 5030fdc8d8SChris Lattner CFStringRef 51b9c1b51eSKate Stone CFCString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { 5230fdc8d8SChris Lattner CFStringRef new_value = NULL; 53b9c1b51eSKate Stone if (cf_type != NULL) { 5430fdc8d8SChris Lattner CFTypeID cf_type_id = ::CFGetTypeID(cf_type); 5530fdc8d8SChris Lattner 56b9c1b51eSKate Stone if (cf_type_id == ::CFStringGetTypeID()) { 5730fdc8d8SChris Lattner // Retain since we are using the existing object 5830fdc8d8SChris Lattner new_value = (CFStringRef)::CFRetain(cf_type); 59b9c1b51eSKate Stone } else if (cf_type_id == ::CFURLGetTypeID()) { 60b9c1b51eSKate Stone new_value = 61b9c1b51eSKate Stone ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); 6230fdc8d8SChris Lattner } 6330fdc8d8SChris Lattner } 6430fdc8d8SChris Lattner reset(new_value); 6530fdc8d8SChris Lattner return get(); 6630fdc8d8SChris Lattner } 6730fdc8d8SChris Lattner 6830fdc8d8SChris Lattner CFStringRef 69b9c1b51eSKate Stone CFCString::SetFileSystemRepresentationAndExpandTilde(const char *path) { 7030fdc8d8SChris Lattner std::string expanded_path; 7130fdc8d8SChris Lattner if (CFCString::ExpandTildeInPath(path, expanded_path)) 7230fdc8d8SChris Lattner SetFileSystemRepresentation(expanded_path.c_str()); 7330fdc8d8SChris Lattner else 7430fdc8d8SChris Lattner reset(); 7530fdc8d8SChris Lattner return get(); 7630fdc8d8SChris Lattner } 7730fdc8d8SChris Lattner 78b9c1b51eSKate Stone const char *CFCString::UTF8(std::string &str) { 7930fdc8d8SChris Lattner return CFCString::UTF8(get(), str); 8030fdc8d8SChris Lattner } 8130fdc8d8SChris Lattner 8205097246SAdrian Prantl // Static function that puts a copy of the UTF8 contents of CF_STR into STR and 8305097246SAdrian Prantl // returns the C string pointer that is contained in STR when successful, else 84b9c1b51eSKate Stone // NULL is returned. This allows the std::string parameter to own the extracted 85b9c1b51eSKate Stone // string, 86b9c1b51eSKate Stone // and also allows that string to be returned as a C string pointer that can be 87b9c1b51eSKate Stone // used. 8830fdc8d8SChris Lattner 89b9c1b51eSKate Stone const char *CFCString::UTF8(CFStringRef cf_str, std::string &str) { 90b9c1b51eSKate Stone if (cf_str) { 9130fdc8d8SChris Lattner const CFStringEncoding encoding = kCFStringEncodingUTF8; 9230fdc8d8SChris Lattner CFIndex max_utf8_str_len = CFStringGetLength(cf_str); 93b9c1b51eSKate Stone max_utf8_str_len = 94b9c1b51eSKate Stone CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); 95b9c1b51eSKate Stone if (max_utf8_str_len > 0) { 9630fdc8d8SChris Lattner str.resize(max_utf8_str_len); 97b9c1b51eSKate Stone if (!str.empty()) { 98b9c1b51eSKate Stone if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { 9930fdc8d8SChris Lattner str.resize(strlen(str.c_str())); 10030fdc8d8SChris Lattner return str.c_str(); 10130fdc8d8SChris Lattner } 10230fdc8d8SChris Lattner } 10330fdc8d8SChris Lattner } 10430fdc8d8SChris Lattner } 10530fdc8d8SChris Lattner return NULL; 10630fdc8d8SChris Lattner } 10730fdc8d8SChris Lattner 108b9c1b51eSKate Stone const char *CFCString::ExpandTildeInPath(const char *path, 109b9c1b51eSKate Stone std::string &expanded_path) { 11030fdc8d8SChris Lattner glob_t globbuf; 111b9c1b51eSKate Stone if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { 11230fdc8d8SChris Lattner expanded_path = globbuf.gl_pathv[0]; 11330fdc8d8SChris Lattner ::globfree(&globbuf); 114b9c1b51eSKate Stone } else 11530fdc8d8SChris Lattner expanded_path.clear(); 11630fdc8d8SChris Lattner 11730fdc8d8SChris Lattner return expanded_path.c_str(); 11830fdc8d8SChris Lattner } 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner // Static function that puts a copy of the file system representation of CF_STR 12130fdc8d8SChris Lattner // into STR and returns the C string pointer that is contained in STR when 12205097246SAdrian Prantl // successful, else NULL is returned. This allows the std::string parameter to 12305097246SAdrian Prantl // own the extracted string, and also allows that string to be returned as a C 12405097246SAdrian Prantl // string pointer that can be used. 12530fdc8d8SChris Lattner 126b9c1b51eSKate Stone const char *CFCString::FileSystemRepresentation(CFStringRef cf_str, 127b9c1b51eSKate Stone std::string &str) { 128b9c1b51eSKate Stone if (cf_str) { 129b9c1b51eSKate Stone CFIndex max_length = 130b9c1b51eSKate Stone ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); 131b9c1b51eSKate Stone if (max_length > 0) { 13230fdc8d8SChris Lattner str.resize(max_length); 133b9c1b51eSKate Stone if (!str.empty()) { 134b9c1b51eSKate Stone if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], 135b9c1b51eSKate Stone str.size())) { 13630fdc8d8SChris Lattner str.erase(::strlen(str.c_str())); 13730fdc8d8SChris Lattner return str.c_str(); 13830fdc8d8SChris Lattner } 13930fdc8d8SChris Lattner } 14030fdc8d8SChris Lattner } 14130fdc8d8SChris Lattner } 14230fdc8d8SChris Lattner str.erase(); 14330fdc8d8SChris Lattner return NULL; 14430fdc8d8SChris Lattner } 14530fdc8d8SChris Lattner 146b9c1b51eSKate Stone CFIndex CFCString::GetLength() const { 14730fdc8d8SChris Lattner CFStringRef str = get(); 14830fdc8d8SChris Lattner if (str) 14930fdc8d8SChris Lattner return CFStringGetLength(str); 15030fdc8d8SChris Lattner return 0; 15130fdc8d8SChris Lattner } 152