130fdc8d8SChris Lattner //===-- CFString.cpp --------------------------------------------*- C++ -*-===//
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 //  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 // CFString constructor
CFString(CFStringRef s)18b9c1b51eSKate Stone CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {}
1930fdc8d8SChris Lattner 
2030fdc8d8SChris Lattner // CFString copy constructor
21*24f9a2f5SShafik Yaghmour CFString::CFString(const CFString &rhs) = default;
2230fdc8d8SChris Lattner 
2330fdc8d8SChris Lattner // CFString copy constructor
operator =(const CFString & rhs)24b9c1b51eSKate Stone CFString &CFString::operator=(const CFString &rhs) {
2530fdc8d8SChris Lattner   if (this != &rhs)
2630fdc8d8SChris Lattner     *this = rhs;
2730fdc8d8SChris Lattner   return *this;
2830fdc8d8SChris Lattner }
2930fdc8d8SChris Lattner 
CFString(const char * cstr,CFStringEncoding cstr_encoding)30b9c1b51eSKate Stone CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding)
31b9c1b51eSKate Stone     : CFReleaser<CFStringRef>() {
32b9c1b51eSKate Stone   if (cstr && cstr[0]) {
33b9c1b51eSKate Stone     reset(
34b9c1b51eSKate Stone         ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
3530fdc8d8SChris Lattner   }
3630fdc8d8SChris Lattner }
3730fdc8d8SChris Lattner 
3830fdc8d8SChris Lattner // Destructor
39*24f9a2f5SShafik Yaghmour CFString::~CFString() = default;
4030fdc8d8SChris Lattner 
GetFileSystemRepresentation(std::string & s)41b9c1b51eSKate Stone const char *CFString::GetFileSystemRepresentation(std::string &s) {
4230fdc8d8SChris Lattner   return CFString::FileSystemRepresentation(get(), s);
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
SetFileSystemRepresentation(const char * path)45b9c1b51eSKate Stone CFStringRef CFString::SetFileSystemRepresentation(const char *path) {
4630fdc8d8SChris Lattner   CFStringRef new_value = NULL;
4730fdc8d8SChris Lattner   if (path && path[0])
48b9c1b51eSKate Stone     new_value =
49b9c1b51eSKate Stone         ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
5030fdc8d8SChris Lattner   reset(new_value);
5130fdc8d8SChris Lattner   return get();
5230fdc8d8SChris Lattner }
5330fdc8d8SChris Lattner 
SetFileSystemRepresentationFromCFType(CFTypeRef cf_type)54b9c1b51eSKate Stone CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
5530fdc8d8SChris Lattner   CFStringRef new_value = NULL;
56b9c1b51eSKate Stone   if (cf_type != NULL) {
5730fdc8d8SChris Lattner     CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
5830fdc8d8SChris Lattner 
59b9c1b51eSKate Stone     if (cf_type_id == ::CFStringGetTypeID()) {
6030fdc8d8SChris Lattner       // Retain since we are using the existing object
6130fdc8d8SChris Lattner       new_value = (CFStringRef)::CFRetain(cf_type);
62b9c1b51eSKate Stone     } else if (cf_type_id == ::CFURLGetTypeID()) {
63b9c1b51eSKate Stone       new_value =
64b9c1b51eSKate Stone           ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
6530fdc8d8SChris Lattner     }
6630fdc8d8SChris Lattner   }
6730fdc8d8SChris Lattner   reset(new_value);
6830fdc8d8SChris Lattner   return get();
6930fdc8d8SChris Lattner }
7030fdc8d8SChris Lattner 
7130fdc8d8SChris Lattner CFStringRef
SetFileSystemRepresentationAndExpandTilde(const char * path)72b9c1b51eSKate Stone CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
7330fdc8d8SChris Lattner   std::string expanded_path;
7430fdc8d8SChris Lattner   if (CFString::GlobPath(path, expanded_path))
7530fdc8d8SChris Lattner     SetFileSystemRepresentation(expanded_path.c_str());
7630fdc8d8SChris Lattner   else
7730fdc8d8SChris Lattner     reset();
7830fdc8d8SChris Lattner   return get();
7930fdc8d8SChris Lattner }
8030fdc8d8SChris Lattner 
UTF8(std::string & str)81b9c1b51eSKate Stone const char *CFString::UTF8(std::string &str) {
8230fdc8d8SChris Lattner   return CFString::UTF8(get(), str);
8330fdc8d8SChris Lattner }
8430fdc8d8SChris Lattner 
8530fdc8d8SChris Lattner // Static function that puts a copy of the UTF8 contents of CF_STR into STR
86b9c1b51eSKate Stone // and returns the C string pointer that is contained in STR when successful,
87b9c1b51eSKate Stone // else
88b9c1b51eSKate Stone // NULL is returned. This allows the std::string parameter to own the extracted
89b9c1b51eSKate Stone // string,
90b9c1b51eSKate Stone // and also allows that string to be returned as a C string pointer that can be
91b9c1b51eSKate Stone // used.
9230fdc8d8SChris Lattner 
UTF8(CFStringRef cf_str,std::string & str)93b9c1b51eSKate Stone const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
94b9c1b51eSKate Stone   if (cf_str) {
9530fdc8d8SChris Lattner     const CFStringEncoding encoding = kCFStringEncodingUTF8;
9630fdc8d8SChris Lattner     CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
97b9c1b51eSKate Stone     max_utf8_str_len =
98b9c1b51eSKate Stone         CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
99b9c1b51eSKate Stone     if (max_utf8_str_len > 0) {
10030fdc8d8SChris Lattner       str.resize(max_utf8_str_len);
101b9c1b51eSKate Stone       if (!str.empty()) {
102b9c1b51eSKate Stone         if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
10330fdc8d8SChris Lattner           str.resize(strlen(str.c_str()));
10430fdc8d8SChris Lattner           return str.c_str();
10530fdc8d8SChris Lattner         }
10630fdc8d8SChris Lattner       }
10730fdc8d8SChris Lattner     }
10830fdc8d8SChris Lattner   }
10930fdc8d8SChris Lattner   return NULL;
11030fdc8d8SChris Lattner }
11130fdc8d8SChris Lattner 
11230fdc8d8SChris Lattner // Static function that puts a copy of the file system representation of CF_STR
11330fdc8d8SChris Lattner // into STR and returns the C string pointer that is contained in STR when
11430fdc8d8SChris Lattner // successful, else NULL is returned. This allows the std::string parameter
11530fdc8d8SChris Lattner // to own the extracted string, and also allows that string to be returned as
11630fdc8d8SChris Lattner // a C string pointer that can be used.
11730fdc8d8SChris Lattner 
FileSystemRepresentation(CFStringRef cf_str,std::string & str)118b9c1b51eSKate Stone const char *CFString::FileSystemRepresentation(CFStringRef cf_str,
119b9c1b51eSKate Stone                                                std::string &str) {
120b9c1b51eSKate Stone   if (cf_str) {
121b9c1b51eSKate Stone     CFIndex max_length =
122b9c1b51eSKate Stone         ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
123b9c1b51eSKate Stone     if (max_length > 0) {
12430fdc8d8SChris Lattner       str.resize(max_length);
125b9c1b51eSKate Stone       if (!str.empty()) {
126b9c1b51eSKate Stone         if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
127b9c1b51eSKate Stone                                                   str.size())) {
12830fdc8d8SChris Lattner           str.erase(::strlen(str.c_str()));
12930fdc8d8SChris Lattner           return str.c_str();
13030fdc8d8SChris Lattner         }
13130fdc8d8SChris Lattner       }
13230fdc8d8SChris Lattner     }
13330fdc8d8SChris Lattner   }
13430fdc8d8SChris Lattner   str.erase();
13530fdc8d8SChris Lattner   return NULL;
13630fdc8d8SChris Lattner }
13730fdc8d8SChris Lattner 
GetLength() const138b9c1b51eSKate Stone CFIndex CFString::GetLength() const {
13930fdc8d8SChris Lattner   CFStringRef str = get();
14030fdc8d8SChris Lattner   if (str)
14130fdc8d8SChris Lattner     return CFStringGetLength(str);
14230fdc8d8SChris Lattner   return 0;
14330fdc8d8SChris Lattner }
14430fdc8d8SChris Lattner 
GlobPath(const char * path,std::string & expanded_path)145b9c1b51eSKate Stone const char *CFString::GlobPath(const char *path, std::string &expanded_path) {
14630fdc8d8SChris Lattner   glob_t globbuf;
147b9c1b51eSKate Stone   if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
14830fdc8d8SChris Lattner     expanded_path = globbuf.gl_pathv[0];
14930fdc8d8SChris Lattner     ::globfree(&globbuf);
150b9c1b51eSKate Stone   } else
15130fdc8d8SChris Lattner     expanded_path.clear();
15230fdc8d8SChris Lattner 
15330fdc8d8SChris Lattner   return expanded_path.c_str();
15430fdc8d8SChris Lattner }
155