130fdc8d8SChris Lattner //===-- CFString.cpp --------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner // 930fdc8d8SChris Lattner // Created by Greg Clayton on 1/16/08. 1030fdc8d8SChris Lattner // 1130fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 1230fdc8d8SChris Lattner 1330fdc8d8SChris Lattner #include "CFString.h" 1430fdc8d8SChris Lattner #include <glob.h> 15b9c1b51eSKate Stone #include <string> 1630fdc8d8SChris Lattner 1730fdc8d8SChris Lattner //---------------------------------------------------------------------- 1830fdc8d8SChris Lattner // CFString constructor 1930fdc8d8SChris Lattner //---------------------------------------------------------------------- 20b9c1b51eSKate Stone CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {} 2130fdc8d8SChris Lattner 2230fdc8d8SChris Lattner //---------------------------------------------------------------------- 2330fdc8d8SChris Lattner // CFString copy constructor 2430fdc8d8SChris Lattner //---------------------------------------------------------------------- 25b9c1b51eSKate Stone CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {} 2630fdc8d8SChris Lattner 2730fdc8d8SChris Lattner //---------------------------------------------------------------------- 2830fdc8d8SChris Lattner // CFString copy constructor 2930fdc8d8SChris Lattner //---------------------------------------------------------------------- 30b9c1b51eSKate Stone CFString &CFString::operator=(const CFString &rhs) { 3130fdc8d8SChris Lattner if (this != &rhs) 3230fdc8d8SChris Lattner *this = rhs; 3330fdc8d8SChris Lattner return *this; 3430fdc8d8SChris Lattner } 3530fdc8d8SChris Lattner 36b9c1b51eSKate Stone CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding) 37b9c1b51eSKate Stone : CFReleaser<CFStringRef>() { 38b9c1b51eSKate Stone if (cstr && cstr[0]) { 39b9c1b51eSKate Stone reset( 40b9c1b51eSKate Stone ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); 4130fdc8d8SChris Lattner } 4230fdc8d8SChris Lattner } 4330fdc8d8SChris Lattner 4430fdc8d8SChris Lattner //---------------------------------------------------------------------- 4530fdc8d8SChris Lattner // Destructor 4630fdc8d8SChris Lattner //---------------------------------------------------------------------- 47b9c1b51eSKate Stone CFString::~CFString() {} 4830fdc8d8SChris Lattner 49b9c1b51eSKate Stone const char *CFString::GetFileSystemRepresentation(std::string &s) { 5030fdc8d8SChris Lattner return CFString::FileSystemRepresentation(get(), s); 5130fdc8d8SChris Lattner } 5230fdc8d8SChris Lattner 53b9c1b51eSKate Stone CFStringRef CFString::SetFileSystemRepresentation(const char *path) { 5430fdc8d8SChris Lattner CFStringRef new_value = NULL; 5530fdc8d8SChris Lattner if (path && path[0]) 56b9c1b51eSKate Stone new_value = 57b9c1b51eSKate Stone ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); 5830fdc8d8SChris Lattner reset(new_value); 5930fdc8d8SChris Lattner return get(); 6030fdc8d8SChris Lattner } 6130fdc8d8SChris Lattner 62b9c1b51eSKate Stone CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { 6330fdc8d8SChris Lattner CFStringRef new_value = NULL; 64b9c1b51eSKate Stone if (cf_type != NULL) { 6530fdc8d8SChris Lattner CFTypeID cf_type_id = ::CFGetTypeID(cf_type); 6630fdc8d8SChris Lattner 67b9c1b51eSKate Stone if (cf_type_id == ::CFStringGetTypeID()) { 6830fdc8d8SChris Lattner // Retain since we are using the existing object 6930fdc8d8SChris Lattner new_value = (CFStringRef)::CFRetain(cf_type); 70b9c1b51eSKate Stone } else if (cf_type_id == ::CFURLGetTypeID()) { 71b9c1b51eSKate Stone new_value = 72b9c1b51eSKate Stone ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); 7330fdc8d8SChris Lattner } 7430fdc8d8SChris Lattner } 7530fdc8d8SChris Lattner reset(new_value); 7630fdc8d8SChris Lattner return get(); 7730fdc8d8SChris Lattner } 7830fdc8d8SChris Lattner 7930fdc8d8SChris Lattner CFStringRef 80b9c1b51eSKate Stone CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) { 8130fdc8d8SChris Lattner std::string expanded_path; 8230fdc8d8SChris Lattner if (CFString::GlobPath(path, expanded_path)) 8330fdc8d8SChris Lattner SetFileSystemRepresentation(expanded_path.c_str()); 8430fdc8d8SChris Lattner else 8530fdc8d8SChris Lattner reset(); 8630fdc8d8SChris Lattner return get(); 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner 89b9c1b51eSKate Stone const char *CFString::UTF8(std::string &str) { 9030fdc8d8SChris Lattner return CFString::UTF8(get(), str); 9130fdc8d8SChris Lattner } 9230fdc8d8SChris Lattner 9330fdc8d8SChris Lattner // Static function that puts a copy of the UTF8 contents of CF_STR into STR 94b9c1b51eSKate Stone // and returns the C string pointer that is contained in STR when successful, 95b9c1b51eSKate Stone // else 96b9c1b51eSKate Stone // NULL is returned. This allows the std::string parameter to own the extracted 97b9c1b51eSKate Stone // string, 98b9c1b51eSKate Stone // and also allows that string to be returned as a C string pointer that can be 99b9c1b51eSKate Stone // used. 10030fdc8d8SChris Lattner 101b9c1b51eSKate Stone const char *CFString::UTF8(CFStringRef cf_str, std::string &str) { 102b9c1b51eSKate Stone if (cf_str) { 10330fdc8d8SChris Lattner const CFStringEncoding encoding = kCFStringEncodingUTF8; 10430fdc8d8SChris Lattner CFIndex max_utf8_str_len = CFStringGetLength(cf_str); 105b9c1b51eSKate Stone max_utf8_str_len = 106b9c1b51eSKate Stone CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); 107b9c1b51eSKate Stone if (max_utf8_str_len > 0) { 10830fdc8d8SChris Lattner str.resize(max_utf8_str_len); 109b9c1b51eSKate Stone if (!str.empty()) { 110b9c1b51eSKate Stone if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { 11130fdc8d8SChris Lattner str.resize(strlen(str.c_str())); 11230fdc8d8SChris Lattner return str.c_str(); 11330fdc8d8SChris Lattner } 11430fdc8d8SChris Lattner } 11530fdc8d8SChris Lattner } 11630fdc8d8SChris Lattner } 11730fdc8d8SChris Lattner return NULL; 11830fdc8d8SChris Lattner } 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner // Static function that puts a copy of the file system representation of CF_STR 12130fdc8d8SChris Lattner // into STR and returns the C string pointer that is contained in STR when 12230fdc8d8SChris Lattner // successful, else NULL is returned. This allows the std::string parameter 12330fdc8d8SChris Lattner // to own the extracted string, and also allows that string to be returned as 12430fdc8d8SChris Lattner // a C string pointer that can be used. 12530fdc8d8SChris Lattner 126b9c1b51eSKate Stone const char *CFString::FileSystemRepresentation(CFStringRef cf_str, 127b9c1b51eSKate Stone std::string &str) { 128b9c1b51eSKate Stone if (cf_str) { 129b9c1b51eSKate Stone CFIndex max_length = 130b9c1b51eSKate Stone ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); 131b9c1b51eSKate Stone if (max_length > 0) { 13230fdc8d8SChris Lattner str.resize(max_length); 133b9c1b51eSKate Stone if (!str.empty()) { 134b9c1b51eSKate Stone if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], 135b9c1b51eSKate Stone str.size())) { 13630fdc8d8SChris Lattner str.erase(::strlen(str.c_str())); 13730fdc8d8SChris Lattner return str.c_str(); 13830fdc8d8SChris Lattner } 13930fdc8d8SChris Lattner } 14030fdc8d8SChris Lattner } 14130fdc8d8SChris Lattner } 14230fdc8d8SChris Lattner str.erase(); 14330fdc8d8SChris Lattner return NULL; 14430fdc8d8SChris Lattner } 14530fdc8d8SChris Lattner 146b9c1b51eSKate Stone CFIndex CFString::GetLength() const { 14730fdc8d8SChris Lattner CFStringRef str = get(); 14830fdc8d8SChris Lattner if (str) 14930fdc8d8SChris Lattner return CFStringGetLength(str); 15030fdc8d8SChris Lattner return 0; 15130fdc8d8SChris Lattner } 15230fdc8d8SChris Lattner 153b9c1b51eSKate Stone const char *CFString::GlobPath(const char *path, std::string &expanded_path) { 15430fdc8d8SChris Lattner glob_t globbuf; 155b9c1b51eSKate Stone if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { 15630fdc8d8SChris Lattner expanded_path = globbuf.gl_pathv[0]; 15730fdc8d8SChris Lattner ::globfree(&globbuf); 158b9c1b51eSKate Stone } else 15930fdc8d8SChris Lattner expanded_path.clear(); 16030fdc8d8SChris Lattner 16130fdc8d8SChris Lattner return expanded_path.c_str(); 16230fdc8d8SChris Lattner } 163