180814287SRaphael Isemann //===-- CFCString.cpp -----------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "CFCString.h"
1030fdc8d8SChris Lattner #include <glob.h>
11b9c1b51eSKate Stone #include <string>
1230fdc8d8SChris Lattner 
1330fdc8d8SChris Lattner // CFCString constructor
CFCString(CFStringRef s)14b9c1b51eSKate Stone CFCString::CFCString(CFStringRef s) : CFCReleaser<CFStringRef>(s) {}
1530fdc8d8SChris Lattner 
1630fdc8d8SChris Lattner // CFCString copy constructor
17*24f9a2f5SShafik Yaghmour CFCString::CFCString(const CFCString &rhs) = default;
1830fdc8d8SChris Lattner 
1930fdc8d8SChris Lattner // CFCString copy constructor
operator =(const CFCString & rhs)20b9c1b51eSKate Stone CFCString &CFCString::operator=(const CFCString &rhs) {
2130fdc8d8SChris Lattner   if (this != &rhs)
2230fdc8d8SChris Lattner     *this = rhs;
2330fdc8d8SChris Lattner   return *this;
2430fdc8d8SChris Lattner }
2530fdc8d8SChris Lattner 
CFCString(const char * cstr,CFStringEncoding cstr_encoding)26b9c1b51eSKate Stone CFCString::CFCString(const char *cstr, CFStringEncoding cstr_encoding)
27b9c1b51eSKate Stone     : CFCReleaser<CFStringRef>() {
28b9c1b51eSKate Stone   if (cstr && cstr[0]) {
29b9c1b51eSKate Stone     reset(
30b9c1b51eSKate Stone         ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
3130fdc8d8SChris Lattner   }
3230fdc8d8SChris Lattner }
3330fdc8d8SChris Lattner 
3430fdc8d8SChris Lattner // Destructor
35fd2433e1SJonas Devlieghere CFCString::~CFCString() = default;
3630fdc8d8SChris Lattner 
GetFileSystemRepresentation(std::string & s)37b9c1b51eSKate Stone const char *CFCString::GetFileSystemRepresentation(std::string &s) {
3830fdc8d8SChris Lattner   return CFCString::FileSystemRepresentation(get(), s);
3930fdc8d8SChris Lattner }
4030fdc8d8SChris Lattner 
SetFileSystemRepresentation(const char * path)41b9c1b51eSKate Stone CFStringRef CFCString::SetFileSystemRepresentation(const char *path) {
4230fdc8d8SChris Lattner   CFStringRef new_value = NULL;
4330fdc8d8SChris Lattner   if (path && path[0])
44b9c1b51eSKate Stone     new_value =
45b9c1b51eSKate Stone         ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
4630fdc8d8SChris Lattner   reset(new_value);
4730fdc8d8SChris Lattner   return get();
4830fdc8d8SChris Lattner }
4930fdc8d8SChris Lattner 
5030fdc8d8SChris Lattner CFStringRef
SetFileSystemRepresentationFromCFType(CFTypeRef cf_type)51b9c1b51eSKate Stone CFCString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
5230fdc8d8SChris Lattner   CFStringRef new_value = NULL;
53b9c1b51eSKate Stone   if (cf_type != NULL) {
5430fdc8d8SChris Lattner     CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
5530fdc8d8SChris Lattner 
56b9c1b51eSKate Stone     if (cf_type_id == ::CFStringGetTypeID()) {
5730fdc8d8SChris Lattner       // Retain since we are using the existing object
5830fdc8d8SChris Lattner       new_value = (CFStringRef)::CFRetain(cf_type);
59b9c1b51eSKate Stone     } else if (cf_type_id == ::CFURLGetTypeID()) {
60b9c1b51eSKate Stone       new_value =
61b9c1b51eSKate Stone           ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
6230fdc8d8SChris Lattner     }
6330fdc8d8SChris Lattner   }
6430fdc8d8SChris Lattner   reset(new_value);
6530fdc8d8SChris Lattner   return get();
6630fdc8d8SChris Lattner }
6730fdc8d8SChris Lattner 
6830fdc8d8SChris Lattner CFStringRef
SetFileSystemRepresentationAndExpandTilde(const char * path)69b9c1b51eSKate Stone CFCString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
7030fdc8d8SChris Lattner   std::string expanded_path;
7130fdc8d8SChris Lattner   if (CFCString::ExpandTildeInPath(path, expanded_path))
7230fdc8d8SChris Lattner     SetFileSystemRepresentation(expanded_path.c_str());
7330fdc8d8SChris Lattner   else
7430fdc8d8SChris Lattner     reset();
7530fdc8d8SChris Lattner   return get();
7630fdc8d8SChris Lattner }
7730fdc8d8SChris Lattner 
UTF8(std::string & str)78b9c1b51eSKate Stone const char *CFCString::UTF8(std::string &str) {
7930fdc8d8SChris Lattner   return CFCString::UTF8(get(), str);
8030fdc8d8SChris Lattner }
8130fdc8d8SChris Lattner 
8205097246SAdrian Prantl // Static function that puts a copy of the UTF8 contents of CF_STR into STR and
8305097246SAdrian Prantl // returns the C string pointer that is contained in STR when successful, else
84b9c1b51eSKate Stone // NULL is returned. This allows the std::string parameter to own the extracted
85b9c1b51eSKate Stone // string,
86b9c1b51eSKate Stone // and also allows that string to be returned as a C string pointer that can be
87b9c1b51eSKate Stone // used.
8830fdc8d8SChris Lattner 
UTF8(CFStringRef cf_str,std::string & str)89b9c1b51eSKate Stone const char *CFCString::UTF8(CFStringRef cf_str, std::string &str) {
90b9c1b51eSKate Stone   if (cf_str) {
9130fdc8d8SChris Lattner     const CFStringEncoding encoding = kCFStringEncodingUTF8;
9230fdc8d8SChris Lattner     CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
93b9c1b51eSKate Stone     max_utf8_str_len =
94b9c1b51eSKate Stone         CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
95b9c1b51eSKate Stone     if (max_utf8_str_len > 0) {
9630fdc8d8SChris Lattner       str.resize(max_utf8_str_len);
97b9c1b51eSKate Stone       if (!str.empty()) {
98b9c1b51eSKate Stone         if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
9930fdc8d8SChris Lattner           str.resize(strlen(str.c_str()));
10030fdc8d8SChris Lattner           return str.c_str();
10130fdc8d8SChris Lattner         }
10230fdc8d8SChris Lattner       }
10330fdc8d8SChris Lattner     }
10430fdc8d8SChris Lattner   }
10530fdc8d8SChris Lattner   return NULL;
10630fdc8d8SChris Lattner }
10730fdc8d8SChris Lattner 
ExpandTildeInPath(const char * path,std::string & expanded_path)108b9c1b51eSKate Stone const char *CFCString::ExpandTildeInPath(const char *path,
109b9c1b51eSKate Stone                                          std::string &expanded_path) {
11030fdc8d8SChris Lattner   glob_t globbuf;
111b9c1b51eSKate Stone   if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
11230fdc8d8SChris Lattner     expanded_path = globbuf.gl_pathv[0];
11330fdc8d8SChris Lattner     ::globfree(&globbuf);
114b9c1b51eSKate Stone   } else
11530fdc8d8SChris Lattner     expanded_path.clear();
11630fdc8d8SChris Lattner 
11730fdc8d8SChris Lattner   return expanded_path.c_str();
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
12205097246SAdrian Prantl // successful, else NULL is returned. This allows the std::string parameter to
12305097246SAdrian Prantl // own the extracted string, and also allows that string to be returned as a C
12405097246SAdrian Prantl // string pointer that can be used.
12530fdc8d8SChris Lattner 
FileSystemRepresentation(CFStringRef cf_str,std::string & str)126b9c1b51eSKate Stone const char *CFCString::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 
GetLength() const146b9c1b51eSKate Stone CFIndex CFCString::GetLength() const {
14730fdc8d8SChris Lattner   CFStringRef str = get();
14830fdc8d8SChris Lattner   if (str)
14930fdc8d8SChris Lattner     return CFStringGetLength(str);
15030fdc8d8SChris Lattner   return 0;
15130fdc8d8SChris Lattner }
152