152 lines · cpp
1//===-- CFCString.cpp -----------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "CFCString.h"10#include <glob.h>11#include <string>12 13// CFCString constructor14CFCString::CFCString(CFStringRef s) : CFCReleaser<CFStringRef>(s) {}15 16// CFCString copy constructor17CFCString::CFCString(const CFCString &rhs) = default;18 19// CFCString copy constructor20CFCString &CFCString::operator=(const CFCString &rhs) {21 if (this != &rhs)22 *this = rhs;23 return *this;24}25 26CFCString::CFCString(const char *cstr, CFStringEncoding cstr_encoding)27 : CFCReleaser<CFStringRef>() {28 if (cstr && cstr[0]) {29 reset(30 ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));31 }32}33 34// Destructor35CFCString::~CFCString() = default;36 37const char *CFCString::GetFileSystemRepresentation(std::string &s) {38 return CFCString::FileSystemRepresentation(get(), s);39}40 41CFStringRef CFCString::SetFileSystemRepresentation(const char *path) {42 CFStringRef new_value = NULL;43 if (path && path[0])44 new_value =45 ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);46 reset(new_value);47 return get();48}49 50CFStringRef51CFCString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {52 CFStringRef new_value = NULL;53 if (cf_type != NULL) {54 CFTypeID cf_type_id = ::CFGetTypeID(cf_type);55 56 if (cf_type_id == ::CFStringGetTypeID()) {57 // Retain since we are using the existing object58 new_value = (CFStringRef)::CFRetain(cf_type);59 } else if (cf_type_id == ::CFURLGetTypeID()) {60 new_value =61 ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);62 }63 }64 reset(new_value);65 return get();66}67 68CFStringRef69CFCString::SetFileSystemRepresentationAndExpandTilde(const char *path) {70 std::string expanded_path;71 if (CFCString::ExpandTildeInPath(path, expanded_path))72 SetFileSystemRepresentation(expanded_path.c_str());73 else74 reset();75 return get();76}77 78const char *CFCString::UTF8(std::string &str) {79 return CFCString::UTF8(get(), str);80}81 82// Static function that puts a copy of the UTF8 contents of CF_STR into STR and83// returns the C string pointer that is contained in STR when successful, else84// NULL is returned. This allows the std::string parameter to own the extracted85// string,86// and also allows that string to be returned as a C string pointer that can be87// used.88 89const char *CFCString::UTF8(CFStringRef cf_str, std::string &str) {90 if (cf_str) {91 const CFStringEncoding encoding = kCFStringEncodingUTF8;92 CFIndex max_utf8_str_len = CFStringGetLength(cf_str);93 max_utf8_str_len =94 CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);95 if (max_utf8_str_len > 0) {96 str.resize(max_utf8_str_len);97 if (!str.empty()) {98 if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {99 str.resize(strlen(str.c_str()));100 return str.c_str();101 }102 }103 }104 }105 return NULL;106}107 108const char *CFCString::ExpandTildeInPath(const char *path,109 std::string &expanded_path) {110 glob_t globbuf;111 if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {112 expanded_path = globbuf.gl_pathv[0];113 ::globfree(&globbuf);114 } else115 expanded_path.clear();116 117 return expanded_path.c_str();118}119 120// Static function that puts a copy of the file system representation of CF_STR121// into STR and returns the C string pointer that is contained in STR when122// successful, else NULL is returned. This allows the std::string parameter to123// own the extracted string, and also allows that string to be returned as a C124// string pointer that can be used.125 126const char *CFCString::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 146CFIndex CFCString::GetLength() const {147 CFStringRef str = get();148 if (str)149 return CFStringGetLength(str);150 return 0;151}152