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