1 //===-- CFCString.cpp -----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CFCString.h" 10 #include <glob.h> 11 #include <string> 12 13 // CFCString constructor 14 CFCString::CFCString(CFStringRef s) : CFCReleaser<CFStringRef>(s) {} 15 16 // CFCString copy constructor 17 CFCString::CFCString(const CFCString &rhs) : CFCReleaser<CFStringRef>(rhs) {} 18 19 // CFCString copy constructor 20 CFCString &CFCString::operator=(const CFCString &rhs) { 21 if (this != &rhs) 22 *this = rhs; 23 return *this; 24 } 25 26 CFCString::CFCString(const char *cstr, CFStringEncoding cstr_encoding) 27 : CFCReleaser<CFStringRef>() { 28 if (cstr && cstr[0]) { 29 reset( 30 ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); 31 } 32 } 33 34 // Destructor 35 CFCString::~CFCString() = default; 36 37 const char *CFCString::GetFileSystemRepresentation(std::string &s) { 38 return CFCString::FileSystemRepresentation(get(), s); 39 } 40 41 CFStringRef CFCString::SetFileSystemRepresentation(const char *path) { 42 CFStringRef new_value = NULL; 43 if (path && path[0]) 44 new_value = 45 ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); 46 reset(new_value); 47 return get(); 48 } 49 50 CFStringRef 51 CFCString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { 52 CFStringRef new_value = NULL; 53 if (cf_type != NULL) { 54 CFTypeID cf_type_id = ::CFGetTypeID(cf_type); 55 56 if (cf_type_id == ::CFStringGetTypeID()) { 57 // Retain since we are using the existing object 58 new_value = (CFStringRef)::CFRetain(cf_type); 59 } else if (cf_type_id == ::CFURLGetTypeID()) { 60 new_value = 61 ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); 62 } 63 } 64 reset(new_value); 65 return get(); 66 } 67 68 CFStringRef 69 CFCString::SetFileSystemRepresentationAndExpandTilde(const char *path) { 70 std::string expanded_path; 71 if (CFCString::ExpandTildeInPath(path, expanded_path)) 72 SetFileSystemRepresentation(expanded_path.c_str()); 73 else 74 reset(); 75 return get(); 76 } 77 78 const char *CFCString::UTF8(std::string &str) { 79 return CFCString::UTF8(get(), str); 80 } 81 82 // Static function that puts a copy of the UTF8 contents of CF_STR into STR and 83 // returns the C string pointer that is contained in STR when successful, else 84 // NULL is returned. This allows the std::string parameter to own the extracted 85 // string, 86 // and also allows that string to be returned as a C string pointer that can be 87 // used. 88 89 const char *CFCString::UTF8(CFStringRef cf_str, std::string &str) { 90 if (cf_str) { 91 const CFStringEncoding encoding = kCFStringEncodingUTF8; 92 CFIndex max_utf8_str_len = CFStringGetLength(cf_str); 93 max_utf8_str_len = 94 CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); 95 if (max_utf8_str_len > 0) { 96 str.resize(max_utf8_str_len); 97 if (!str.empty()) { 98 if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { 99 str.resize(strlen(str.c_str())); 100 return str.c_str(); 101 } 102 } 103 } 104 } 105 return NULL; 106 } 107 108 const char *CFCString::ExpandTildeInPath(const char *path, 109 std::string &expanded_path) { 110 glob_t globbuf; 111 if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { 112 expanded_path = globbuf.gl_pathv[0]; 113 ::globfree(&globbuf); 114 } else 115 expanded_path.clear(); 116 117 return expanded_path.c_str(); 118 } 119 120 // Static function that puts a copy of the file system representation of CF_STR 121 // into STR and returns the C string pointer that is contained in STR when 122 // successful, else NULL is returned. This allows the std::string parameter to 123 // own the extracted string, and also allows that string to be returned as a C 124 // string pointer that can be used. 125 126 const char *CFCString::FileSystemRepresentation(CFStringRef cf_str, 127 std::string &str) { 128 if (cf_str) { 129 CFIndex max_length = 130 ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); 131 if (max_length > 0) { 132 str.resize(max_length); 133 if (!str.empty()) { 134 if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], 135 str.size())) { 136 str.erase(::strlen(str.c_str())); 137 return str.c_str(); 138 } 139 } 140 } 141 } 142 str.erase(); 143 return NULL; 144 } 145 146 CFIndex CFCString::GetLength() const { 147 CFStringRef str = get(); 148 if (str) 149 return CFStringGetLength(str); 150 return 0; 151 } 152