| //===-- CFString.cpp --------------------------------------------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Created by Greg Clayton on 1/16/08. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "CFString.h" | |
| #include <glob.h> | |
| #include <string> | |
| // CFString constructor | |
| CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {} | |
| // CFString copy constructor | |
| CFString::CFString(const CFString &rhs) = default; | |
| // CFString copy constructor | |
| CFString &CFString::operator=(const CFString &rhs) { | |
| if (this != &rhs) | |
| *this = rhs; | |
| return *this; | |
| } | |
| CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding) | |
| : CFReleaser<CFStringRef>() { | |
| if (cstr && cstr[0]) { | |
| reset( | |
| ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); | |
| } | |
| } | |
| // Destructor | |
| CFString::~CFString() = default; | |
| const char *CFString::GetFileSystemRepresentation(std::string &s) { | |
| return CFString::FileSystemRepresentation(get(), s); | |
| } | |
| CFStringRef CFString::SetFileSystemRepresentation(const char *path) { | |
| CFStringRef new_value = NULL; | |
| if (path && path[0]) | |
| new_value = | |
| ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); | |
| reset(new_value); | |
| return get(); | |
| } | |
| CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { | |
| CFStringRef new_value = NULL; | |
| if (cf_type != NULL) { | |
| CFTypeID cf_type_id = ::CFGetTypeID(cf_type); | |
| if (cf_type_id == ::CFStringGetTypeID()) { | |
| // Retain since we are using the existing object | |
| new_value = (CFStringRef)::CFRetain(cf_type); | |
| } else if (cf_type_id == ::CFURLGetTypeID()) { | |
| new_value = | |
| ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); | |
| } | |
| } | |
| reset(new_value); | |
| return get(); | |
| } | |
| CFStringRef | |
| CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) { | |
| std::string expanded_path; | |
| if (CFString::GlobPath(path, expanded_path)) | |
| SetFileSystemRepresentation(expanded_path.c_str()); | |
| else | |
| reset(); | |
| return get(); | |
| } | |
| const char *CFString::UTF8(std::string &str) { | |
| return CFString::UTF8(get(), str); | |
| } | |
| // Static function that puts a copy of the UTF8 contents of CF_STR into STR | |
| // and returns the C string pointer that is contained in STR when successful, | |
| // else | |
| // NULL is returned. This allows the std::string parameter to own the extracted | |
| // string, | |
| // and also allows that string to be returned as a C string pointer that can be | |
| // used. | |
| const char *CFString::UTF8(CFStringRef cf_str, std::string &str) { | |
| if (cf_str) { | |
| const CFStringEncoding encoding = kCFStringEncodingUTF8; | |
| CFIndex max_utf8_str_len = CFStringGetLength(cf_str); | |
| max_utf8_str_len = | |
| CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); | |
| if (max_utf8_str_len > 0) { | |
| str.resize(max_utf8_str_len); | |
| if (!str.empty()) { | |
| if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { | |
| str.resize(strlen(str.c_str())); | |
| return str.c_str(); | |
| } | |
| } | |
| } | |
| } | |
| return NULL; | |
| } | |
| // Static function that puts a copy of the file system representation of CF_STR | |
| // into STR and returns the C string pointer that is contained in STR when | |
| // successful, else NULL is returned. This allows the std::string parameter | |
| // to own the extracted string, and also allows that string to be returned as | |
| // a C string pointer that can be used. | |
| const char *CFString::FileSystemRepresentation(CFStringRef cf_str, | |
| std::string &str) { | |
| if (cf_str) { | |
| CFIndex max_length = | |
| ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); | |
| if (max_length > 0) { | |
| str.resize(max_length); | |
| if (!str.empty()) { | |
| if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], | |
| str.size())) { | |
| str.erase(::strlen(str.c_str())); | |
| return str.c_str(); | |
| } | |
| } | |
| } | |
| } | |
| str.erase(); | |
| return NULL; | |
| } | |
| CFIndex CFString::GetLength() const { | |
| CFStringRef str = get(); | |
| if (str) | |
| return CFStringGetLength(str); | |
| return 0; | |
| } | |
| const char *CFString::GlobPath(const char *path, std::string &expanded_path) { | |
| glob_t globbuf; | |
| if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { | |
| expanded_path = globbuf.gl_pathv[0]; | |
| ::globfree(&globbuf); | |
| } else | |
| expanded_path.clear(); | |
| return expanded_path.c_str(); | |
| } |