130fdc8d8SChris Lattner //===-- CFCString.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 #include "CFCString.h"
1030fdc8d8SChris Lattner #include <glob.h>
11b9c1b51eSKate Stone #include <string>
1230fdc8d8SChris Lattner 
1330fdc8d8SChris Lattner //----------------------------------------------------------------------
1430fdc8d8SChris Lattner // CFCString constructor
1530fdc8d8SChris Lattner //----------------------------------------------------------------------
16b9c1b51eSKate Stone CFCString::CFCString(CFStringRef s) : CFCReleaser<CFStringRef>(s) {}
1730fdc8d8SChris Lattner 
1830fdc8d8SChris Lattner //----------------------------------------------------------------------
1930fdc8d8SChris Lattner // CFCString copy constructor
2030fdc8d8SChris Lattner //----------------------------------------------------------------------
21b9c1b51eSKate Stone CFCString::CFCString(const CFCString &rhs) : CFCReleaser<CFStringRef>(rhs) {}
2230fdc8d8SChris Lattner 
2330fdc8d8SChris Lattner //----------------------------------------------------------------------
2430fdc8d8SChris Lattner // CFCString copy constructor
2530fdc8d8SChris Lattner //----------------------------------------------------------------------
26b9c1b51eSKate Stone CFCString &CFCString::operator=(const CFCString &rhs) {
2730fdc8d8SChris Lattner   if (this != &rhs)
2830fdc8d8SChris Lattner     *this = rhs;
2930fdc8d8SChris Lattner   return *this;
3030fdc8d8SChris Lattner }
3130fdc8d8SChris Lattner 
32b9c1b51eSKate Stone CFCString::CFCString(const char *cstr, CFStringEncoding cstr_encoding)
33b9c1b51eSKate Stone     : CFCReleaser<CFStringRef>() {
34b9c1b51eSKate Stone   if (cstr && cstr[0]) {
35b9c1b51eSKate Stone     reset(
36b9c1b51eSKate Stone         ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
3730fdc8d8SChris Lattner   }
3830fdc8d8SChris Lattner }
3930fdc8d8SChris Lattner 
4030fdc8d8SChris Lattner //----------------------------------------------------------------------
4130fdc8d8SChris Lattner // Destructor
4230fdc8d8SChris Lattner //----------------------------------------------------------------------
43b9c1b51eSKate Stone CFCString::~CFCString() {}
4430fdc8d8SChris Lattner 
45b9c1b51eSKate Stone const char *CFCString::GetFileSystemRepresentation(std::string &s) {
4630fdc8d8SChris Lattner   return CFCString::FileSystemRepresentation(get(), s);
4730fdc8d8SChris Lattner }
4830fdc8d8SChris Lattner 
49b9c1b51eSKate Stone CFStringRef CFCString::SetFileSystemRepresentation(const char *path) {
5030fdc8d8SChris Lattner   CFStringRef new_value = NULL;
5130fdc8d8SChris Lattner   if (path && path[0])
52b9c1b51eSKate Stone     new_value =
53b9c1b51eSKate Stone         ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
5430fdc8d8SChris Lattner   reset(new_value);
5530fdc8d8SChris Lattner   return get();
5630fdc8d8SChris Lattner }
5730fdc8d8SChris Lattner 
5830fdc8d8SChris Lattner CFStringRef
59b9c1b51eSKate Stone CFCString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
6030fdc8d8SChris Lattner   CFStringRef new_value = NULL;
61b9c1b51eSKate Stone   if (cf_type != NULL) {
6230fdc8d8SChris Lattner     CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
6330fdc8d8SChris Lattner 
64b9c1b51eSKate Stone     if (cf_type_id == ::CFStringGetTypeID()) {
6530fdc8d8SChris Lattner       // Retain since we are using the existing object
6630fdc8d8SChris Lattner       new_value = (CFStringRef)::CFRetain(cf_type);
67b9c1b51eSKate Stone     } else if (cf_type_id == ::CFURLGetTypeID()) {
68b9c1b51eSKate Stone       new_value =
69b9c1b51eSKate Stone           ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
7030fdc8d8SChris Lattner     }
7130fdc8d8SChris Lattner   }
7230fdc8d8SChris Lattner   reset(new_value);
7330fdc8d8SChris Lattner   return get();
7430fdc8d8SChris Lattner }
7530fdc8d8SChris Lattner 
7630fdc8d8SChris Lattner CFStringRef
77b9c1b51eSKate Stone CFCString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
7830fdc8d8SChris Lattner   std::string expanded_path;
7930fdc8d8SChris Lattner   if (CFCString::ExpandTildeInPath(path, expanded_path))
8030fdc8d8SChris Lattner     SetFileSystemRepresentation(expanded_path.c_str());
8130fdc8d8SChris Lattner   else
8230fdc8d8SChris Lattner     reset();
8330fdc8d8SChris Lattner   return get();
8430fdc8d8SChris Lattner }
8530fdc8d8SChris Lattner 
86b9c1b51eSKate Stone const char *CFCString::UTF8(std::string &str) {
8730fdc8d8SChris Lattner   return CFCString::UTF8(get(), str);
8830fdc8d8SChris Lattner }
8930fdc8d8SChris Lattner 
9005097246SAdrian Prantl // Static function that puts a copy of the UTF8 contents of CF_STR into STR and
9105097246SAdrian Prantl // returns the C string pointer that is contained in STR when successful, else
92b9c1b51eSKate Stone // NULL is returned. This allows the std::string parameter to own the extracted
93b9c1b51eSKate Stone // string,
94b9c1b51eSKate Stone // and also allows that string to be returned as a C string pointer that can be
95b9c1b51eSKate Stone // used.
9630fdc8d8SChris Lattner 
97b9c1b51eSKate Stone const char *CFCString::UTF8(CFStringRef cf_str, std::string &str) {
98b9c1b51eSKate Stone   if (cf_str) {
9930fdc8d8SChris Lattner     const CFStringEncoding encoding = kCFStringEncodingUTF8;
10030fdc8d8SChris Lattner     CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
101b9c1b51eSKate Stone     max_utf8_str_len =
102b9c1b51eSKate Stone         CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
103b9c1b51eSKate Stone     if (max_utf8_str_len > 0) {
10430fdc8d8SChris Lattner       str.resize(max_utf8_str_len);
105b9c1b51eSKate Stone       if (!str.empty()) {
106b9c1b51eSKate Stone         if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
10730fdc8d8SChris Lattner           str.resize(strlen(str.c_str()));
10830fdc8d8SChris Lattner           return str.c_str();
10930fdc8d8SChris Lattner         }
11030fdc8d8SChris Lattner       }
11130fdc8d8SChris Lattner     }
11230fdc8d8SChris Lattner   }
11330fdc8d8SChris Lattner   return NULL;
11430fdc8d8SChris Lattner }
11530fdc8d8SChris Lattner 
116b9c1b51eSKate Stone const char *CFCString::ExpandTildeInPath(const char *path,
117b9c1b51eSKate Stone                                          std::string &expanded_path) {
11830fdc8d8SChris Lattner   glob_t globbuf;
119b9c1b51eSKate Stone   if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
12030fdc8d8SChris Lattner     expanded_path = globbuf.gl_pathv[0];
12130fdc8d8SChris Lattner     ::globfree(&globbuf);
122b9c1b51eSKate Stone   } else
12330fdc8d8SChris Lattner     expanded_path.clear();
12430fdc8d8SChris Lattner 
12530fdc8d8SChris Lattner   return expanded_path.c_str();
12630fdc8d8SChris Lattner }
12730fdc8d8SChris Lattner 
12830fdc8d8SChris Lattner // Static function that puts a copy of the file system representation of CF_STR
12930fdc8d8SChris Lattner // into STR and returns the C string pointer that is contained in STR when
13005097246SAdrian Prantl // successful, else NULL is returned. This allows the std::string parameter to
13105097246SAdrian Prantl // own the extracted string, and also allows that string to be returned as a C
13205097246SAdrian Prantl // string pointer that can be used.
13330fdc8d8SChris Lattner 
134b9c1b51eSKate Stone const char *CFCString::FileSystemRepresentation(CFStringRef cf_str,
135b9c1b51eSKate Stone                                                 std::string &str) {
136b9c1b51eSKate Stone   if (cf_str) {
137b9c1b51eSKate Stone     CFIndex max_length =
138b9c1b51eSKate Stone         ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
139b9c1b51eSKate Stone     if (max_length > 0) {
14030fdc8d8SChris Lattner       str.resize(max_length);
141b9c1b51eSKate Stone       if (!str.empty()) {
142b9c1b51eSKate Stone         if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
143b9c1b51eSKate Stone                                                   str.size())) {
14430fdc8d8SChris Lattner           str.erase(::strlen(str.c_str()));
14530fdc8d8SChris Lattner           return str.c_str();
14630fdc8d8SChris Lattner         }
14730fdc8d8SChris Lattner       }
14830fdc8d8SChris Lattner     }
14930fdc8d8SChris Lattner   }
15030fdc8d8SChris Lattner   str.erase();
15130fdc8d8SChris Lattner   return NULL;
15230fdc8d8SChris Lattner }
15330fdc8d8SChris Lattner 
154b9c1b51eSKate Stone CFIndex CFCString::GetLength() const {
15530fdc8d8SChris Lattner   CFStringRef str = get();
15630fdc8d8SChris Lattner   if (str)
15730fdc8d8SChris Lattner     return CFStringGetLength(str);
15830fdc8d8SChris Lattner   return 0;
15930fdc8d8SChris Lattner }
160