130fdc8d8SChris Lattner //===-- CFCString.cpp -------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler 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 //---------------------------------------------------------------------- 1430fdc8d8SChris Lattner // CFCString constructor 1530fdc8d8SChris Lattner //---------------------------------------------------------------------- 16b9c1b51eSKate Stone CFCString::CFCString(CFStringRef s) : CFCReleaser<CFStringRef>(s) {} 1730fdc8d8SChris Lattner 1830fdc8d8SChris Lattner //---------------------------------------------------------------------- 1930fdc8d8SChris Lattner // CFCString copy constructor 2030fdc8d8SChris Lattner //---------------------------------------------------------------------- 21b9c1b51eSKate Stone CFCString::CFCString(const CFCString &rhs) : CFCReleaser<CFStringRef>(rhs) {} 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner //---------------------------------------------------------------------- 2430fdc8d8SChris Lattner // CFCString copy constructor 2530fdc8d8SChris Lattner //---------------------------------------------------------------------- 26b9c1b51eSKate Stone CFCString &CFCString::operator=(const CFCString &rhs) { 2730fdc8d8SChris Lattner if (this != &rhs) 2830fdc8d8SChris Lattner *this = rhs; 2930fdc8d8SChris Lattner return *this; 3030fdc8d8SChris Lattner } 3130fdc8d8SChris Lattner 32b9c1b51eSKate Stone CFCString::CFCString(const char *cstr, CFStringEncoding cstr_encoding) 33b9c1b51eSKate Stone : CFCReleaser<CFStringRef>() { 34b9c1b51eSKate Stone if (cstr && cstr[0]) { 35b9c1b51eSKate Stone reset( 36b9c1b51eSKate Stone ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); 3730fdc8d8SChris Lattner } 3830fdc8d8SChris Lattner } 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner //---------------------------------------------------------------------- 4130fdc8d8SChris Lattner // Destructor 4230fdc8d8SChris Lattner //---------------------------------------------------------------------- 43b9c1b51eSKate Stone CFCString::~CFCString() {} 4430fdc8d8SChris Lattner 45b9c1b51eSKate Stone const char *CFCString::GetFileSystemRepresentation(std::string &s) { 4630fdc8d8SChris Lattner return CFCString::FileSystemRepresentation(get(), s); 4730fdc8d8SChris Lattner } 4830fdc8d8SChris Lattner 49b9c1b51eSKate Stone CFStringRef CFCString::SetFileSystemRepresentation(const char *path) { 5030fdc8d8SChris Lattner CFStringRef new_value = NULL; 5130fdc8d8SChris Lattner if (path && path[0]) 52b9c1b51eSKate Stone new_value = 53b9c1b51eSKate Stone ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); 5430fdc8d8SChris Lattner reset(new_value); 5530fdc8d8SChris Lattner return get(); 5630fdc8d8SChris Lattner } 5730fdc8d8SChris Lattner 5830fdc8d8SChris Lattner CFStringRef 59b9c1b51eSKate Stone CFCString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { 6030fdc8d8SChris Lattner CFStringRef new_value = NULL; 61b9c1b51eSKate Stone if (cf_type != NULL) { 6230fdc8d8SChris Lattner CFTypeID cf_type_id = ::CFGetTypeID(cf_type); 6330fdc8d8SChris Lattner 64b9c1b51eSKate Stone if (cf_type_id == ::CFStringGetTypeID()) { 6530fdc8d8SChris Lattner // Retain since we are using the existing object 6630fdc8d8SChris Lattner new_value = (CFStringRef)::CFRetain(cf_type); 67b9c1b51eSKate Stone } else if (cf_type_id == ::CFURLGetTypeID()) { 68b9c1b51eSKate Stone new_value = 69b9c1b51eSKate Stone ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); 7030fdc8d8SChris Lattner } 7130fdc8d8SChris Lattner } 7230fdc8d8SChris Lattner reset(new_value); 7330fdc8d8SChris Lattner return get(); 7430fdc8d8SChris Lattner } 7530fdc8d8SChris Lattner 7630fdc8d8SChris Lattner CFStringRef 77b9c1b51eSKate Stone CFCString::SetFileSystemRepresentationAndExpandTilde(const char *path) { 7830fdc8d8SChris Lattner std::string expanded_path; 7930fdc8d8SChris Lattner if (CFCString::ExpandTildeInPath(path, expanded_path)) 8030fdc8d8SChris Lattner SetFileSystemRepresentation(expanded_path.c_str()); 8130fdc8d8SChris Lattner else 8230fdc8d8SChris Lattner reset(); 8330fdc8d8SChris Lattner return get(); 8430fdc8d8SChris Lattner } 8530fdc8d8SChris Lattner 86b9c1b51eSKate Stone const char *CFCString::UTF8(std::string &str) { 8730fdc8d8SChris Lattner return CFCString::UTF8(get(), str); 8830fdc8d8SChris Lattner } 8930fdc8d8SChris Lattner 9005097246SAdrian Prantl // Static function that puts a copy of the UTF8 contents of CF_STR into STR and 9105097246SAdrian Prantl // returns the C string pointer that is contained in STR when successful, else 92b9c1b51eSKate Stone // NULL is returned. This allows the std::string parameter to own the extracted 93b9c1b51eSKate Stone // string, 94b9c1b51eSKate Stone // and also allows that string to be returned as a C string pointer that can be 95b9c1b51eSKate Stone // used. 9630fdc8d8SChris Lattner 97b9c1b51eSKate Stone const char *CFCString::UTF8(CFStringRef cf_str, std::string &str) { 98b9c1b51eSKate Stone if (cf_str) { 9930fdc8d8SChris Lattner const CFStringEncoding encoding = kCFStringEncodingUTF8; 10030fdc8d8SChris Lattner CFIndex max_utf8_str_len = CFStringGetLength(cf_str); 101b9c1b51eSKate Stone max_utf8_str_len = 102b9c1b51eSKate Stone CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); 103b9c1b51eSKate Stone if (max_utf8_str_len > 0) { 10430fdc8d8SChris Lattner str.resize(max_utf8_str_len); 105b9c1b51eSKate Stone if (!str.empty()) { 106b9c1b51eSKate Stone if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { 10730fdc8d8SChris Lattner str.resize(strlen(str.c_str())); 10830fdc8d8SChris Lattner return str.c_str(); 10930fdc8d8SChris Lattner } 11030fdc8d8SChris Lattner } 11130fdc8d8SChris Lattner } 11230fdc8d8SChris Lattner } 11330fdc8d8SChris Lattner return NULL; 11430fdc8d8SChris Lattner } 11530fdc8d8SChris Lattner 116b9c1b51eSKate Stone const char *CFCString::ExpandTildeInPath(const char *path, 117b9c1b51eSKate Stone std::string &expanded_path) { 11830fdc8d8SChris Lattner glob_t globbuf; 119b9c1b51eSKate Stone if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { 12030fdc8d8SChris Lattner expanded_path = globbuf.gl_pathv[0]; 12130fdc8d8SChris Lattner ::globfree(&globbuf); 122b9c1b51eSKate Stone } else 12330fdc8d8SChris Lattner expanded_path.clear(); 12430fdc8d8SChris Lattner 12530fdc8d8SChris Lattner return expanded_path.c_str(); 12630fdc8d8SChris Lattner } 12730fdc8d8SChris Lattner 12830fdc8d8SChris Lattner // Static function that puts a copy of the file system representation of CF_STR 12930fdc8d8SChris Lattner // into STR and returns the C string pointer that is contained in STR when 13005097246SAdrian Prantl // successful, else NULL is returned. This allows the std::string parameter to 13105097246SAdrian Prantl // own the extracted string, and also allows that string to be returned as a C 13205097246SAdrian Prantl // string pointer that can be used. 13330fdc8d8SChris Lattner 134b9c1b51eSKate Stone const char *CFCString::FileSystemRepresentation(CFStringRef cf_str, 135b9c1b51eSKate Stone std::string &str) { 136b9c1b51eSKate Stone if (cf_str) { 137b9c1b51eSKate Stone CFIndex max_length = 138b9c1b51eSKate Stone ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); 139b9c1b51eSKate Stone if (max_length > 0) { 14030fdc8d8SChris Lattner str.resize(max_length); 141b9c1b51eSKate Stone if (!str.empty()) { 142b9c1b51eSKate Stone if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], 143b9c1b51eSKate Stone str.size())) { 14430fdc8d8SChris Lattner str.erase(::strlen(str.c_str())); 14530fdc8d8SChris Lattner return str.c_str(); 14630fdc8d8SChris Lattner } 14730fdc8d8SChris Lattner } 14830fdc8d8SChris Lattner } 14930fdc8d8SChris Lattner } 15030fdc8d8SChris Lattner str.erase(); 15130fdc8d8SChris Lattner return NULL; 15230fdc8d8SChris Lattner } 15330fdc8d8SChris Lattner 154b9c1b51eSKate Stone CFIndex CFCString::GetLength() const { 15530fdc8d8SChris Lattner CFStringRef str = get(); 15630fdc8d8SChris Lattner if (str) 15730fdc8d8SChris Lattner return CFStringGetLength(str); 15830fdc8d8SChris Lattner return 0; 15930fdc8d8SChris Lattner } 160