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