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