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 18CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {} 19 20// CFString copy constructor 21CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {} 22 23// CFString copy constructor 24CFString &CFString::operator=(const CFString &rhs) { 25 if (this != &rhs) 26 *this = rhs; 27 return *this; 28} 29 30CFString::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 39CFString::~CFString() {} 40 41const char *CFString::GetFileSystemRepresentation(std::string &s) { 42 return CFString::FileSystemRepresentation(get(), s); 43} 44 45CFStringRef 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 54CFStringRef 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 71CFStringRef 72CFString::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 81const 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 and 86// returns the C string pointer that is contained in STR when successful, else 87// NULL is returned. This allows the std::string parameter to own the extracted 88// string, 89// and also allows that string to be returned as a C string pointer that can be 90// used. 91 92const char *CFString::UTF8(CFStringRef cf_str, std::string &str) { 93 if (cf_str) { 94 const CFStringEncoding encoding = kCFStringEncodingUTF8; 95 CFIndex max_utf8_str_len = CFStringGetLength(cf_str); 96 max_utf8_str_len = 97 CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); 98 if (max_utf8_str_len > 0) { 99 str.resize(max_utf8_str_len); 100 if (!str.empty()) { 101 if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { 102 str.resize(strlen(str.c_str())); 103 return str.c_str(); 104 } 105 } 106 } 107 } 108 return NULL; 109} 110 111// Static function that puts a copy of the file system representation of CF_STR 112// into STR and returns the C string pointer that is contained in STR when 113// successful, else NULL is returned. This allows the std::string parameter to 114// own the extracted string, and also allows that string to be returned as a C 115// string pointer that can be used. 116 117const char *CFString::FileSystemRepresentation(CFStringRef cf_str, 118 std::string &str) { 119 if (cf_str) { 120 CFIndex max_length = 121 ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); 122 if (max_length > 0) { 123 str.resize(max_length); 124 if (!str.empty()) { 125 if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], 126 str.size())) { 127 str.erase(::strlen(str.c_str())); 128 return str.c_str(); 129 } 130 } 131 } 132 } 133 str.erase(); 134 return NULL; 135} 136 137CFIndex CFString::GetLength() const { 138 CFStringRef str = get(); 139 if (str) 140 return CFStringGetLength(str); 141 return 0; 142} 143 144const char *CFString::GlobPath(const char *path, std::string &expanded_path) { 145 glob_t globbuf; 146 if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { 147 expanded_path = globbuf.gl_pathv[0]; 148 ::globfree(&globbuf); 149 } else 150 expanded_path.clear(); 151 152 return expanded_path.c_str(); 153} 154