130fdc8d8SChris Lattner //===-- CFString.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 //  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 //----------------------------------------------------------------------
1830fdc8d8SChris Lattner // CFString constructor
1930fdc8d8SChris Lattner //----------------------------------------------------------------------
20b9c1b51eSKate Stone CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {}
2130fdc8d8SChris Lattner 
2230fdc8d8SChris Lattner //----------------------------------------------------------------------
2330fdc8d8SChris Lattner // CFString copy constructor
2430fdc8d8SChris Lattner //----------------------------------------------------------------------
25b9c1b51eSKate Stone CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {}
2630fdc8d8SChris Lattner 
2730fdc8d8SChris Lattner //----------------------------------------------------------------------
2830fdc8d8SChris Lattner // CFString copy constructor
2930fdc8d8SChris Lattner //----------------------------------------------------------------------
30b9c1b51eSKate Stone CFString &CFString::operator=(const CFString &rhs) {
3130fdc8d8SChris Lattner   if (this != &rhs)
3230fdc8d8SChris Lattner     *this = rhs;
3330fdc8d8SChris Lattner   return *this;
3430fdc8d8SChris Lattner }
3530fdc8d8SChris Lattner 
36b9c1b51eSKate Stone CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding)
37b9c1b51eSKate Stone     : CFReleaser<CFStringRef>() {
38b9c1b51eSKate Stone   if (cstr && cstr[0]) {
39b9c1b51eSKate Stone     reset(
40b9c1b51eSKate Stone         ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
4130fdc8d8SChris Lattner   }
4230fdc8d8SChris Lattner }
4330fdc8d8SChris Lattner 
4430fdc8d8SChris Lattner //----------------------------------------------------------------------
4530fdc8d8SChris Lattner // Destructor
4630fdc8d8SChris Lattner //----------------------------------------------------------------------
47b9c1b51eSKate Stone CFString::~CFString() {}
4830fdc8d8SChris Lattner 
49b9c1b51eSKate Stone const char *CFString::GetFileSystemRepresentation(std::string &s) {
5030fdc8d8SChris Lattner   return CFString::FileSystemRepresentation(get(), s);
5130fdc8d8SChris Lattner }
5230fdc8d8SChris Lattner 
53b9c1b51eSKate Stone CFStringRef CFString::SetFileSystemRepresentation(const char *path) {
5430fdc8d8SChris Lattner   CFStringRef new_value = NULL;
5530fdc8d8SChris Lattner   if (path && path[0])
56b9c1b51eSKate Stone     new_value =
57b9c1b51eSKate Stone         ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
5830fdc8d8SChris Lattner   reset(new_value);
5930fdc8d8SChris Lattner   return get();
6030fdc8d8SChris Lattner }
6130fdc8d8SChris Lattner 
62b9c1b51eSKate Stone CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
6330fdc8d8SChris Lattner   CFStringRef new_value = NULL;
64b9c1b51eSKate Stone   if (cf_type != NULL) {
6530fdc8d8SChris Lattner     CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
6630fdc8d8SChris Lattner 
67b9c1b51eSKate Stone     if (cf_type_id == ::CFStringGetTypeID()) {
6830fdc8d8SChris Lattner       // Retain since we are using the existing object
6930fdc8d8SChris Lattner       new_value = (CFStringRef)::CFRetain(cf_type);
70b9c1b51eSKate Stone     } else if (cf_type_id == ::CFURLGetTypeID()) {
71b9c1b51eSKate Stone       new_value =
72b9c1b51eSKate Stone           ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
7330fdc8d8SChris Lattner     }
7430fdc8d8SChris Lattner   }
7530fdc8d8SChris Lattner   reset(new_value);
7630fdc8d8SChris Lattner   return get();
7730fdc8d8SChris Lattner }
7830fdc8d8SChris Lattner 
7930fdc8d8SChris Lattner CFStringRef
80b9c1b51eSKate Stone CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
8130fdc8d8SChris Lattner   std::string expanded_path;
8230fdc8d8SChris Lattner   if (CFString::GlobPath(path, expanded_path))
8330fdc8d8SChris Lattner     SetFileSystemRepresentation(expanded_path.c_str());
8430fdc8d8SChris Lattner   else
8530fdc8d8SChris Lattner     reset();
8630fdc8d8SChris Lattner   return get();
8730fdc8d8SChris Lattner }
8830fdc8d8SChris Lattner 
89b9c1b51eSKate Stone const char *CFString::UTF8(std::string &str) {
9030fdc8d8SChris Lattner   return CFString::UTF8(get(), str);
9130fdc8d8SChris Lattner }
9230fdc8d8SChris Lattner 
9330fdc8d8SChris Lattner // Static function that puts a copy of the UTF8 contents of CF_STR into STR
94b9c1b51eSKate Stone // and returns the C string pointer that is contained in STR when successful,
95b9c1b51eSKate Stone // else
96b9c1b51eSKate Stone // NULL is returned. This allows the std::string parameter to own the extracted
97b9c1b51eSKate Stone // string,
98b9c1b51eSKate Stone // and also allows that string to be returned as a C string pointer that can be
99b9c1b51eSKate Stone // used.
10030fdc8d8SChris Lattner 
101b9c1b51eSKate Stone const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
102b9c1b51eSKate Stone   if (cf_str) {
10330fdc8d8SChris Lattner     const CFStringEncoding encoding = kCFStringEncodingUTF8;
10430fdc8d8SChris Lattner     CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
105b9c1b51eSKate Stone     max_utf8_str_len =
106b9c1b51eSKate Stone         CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
107b9c1b51eSKate Stone     if (max_utf8_str_len > 0) {
10830fdc8d8SChris Lattner       str.resize(max_utf8_str_len);
109b9c1b51eSKate Stone       if (!str.empty()) {
110b9c1b51eSKate Stone         if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
11130fdc8d8SChris Lattner           str.resize(strlen(str.c_str()));
11230fdc8d8SChris Lattner           return str.c_str();
11330fdc8d8SChris Lattner         }
11430fdc8d8SChris Lattner       }
11530fdc8d8SChris Lattner     }
11630fdc8d8SChris Lattner   }
11730fdc8d8SChris Lattner   return NULL;
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
12230fdc8d8SChris Lattner // successful, else NULL is returned. This allows the std::string parameter
12330fdc8d8SChris Lattner // to own the extracted string, and also allows that string to be returned as
12430fdc8d8SChris Lattner // a C string pointer that can be used.
12530fdc8d8SChris Lattner 
126b9c1b51eSKate Stone const char *CFString::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 
146b9c1b51eSKate Stone CFIndex CFString::GetLength() const {
14730fdc8d8SChris Lattner   CFStringRef str = get();
14830fdc8d8SChris Lattner   if (str)
14930fdc8d8SChris Lattner     return CFStringGetLength(str);
15030fdc8d8SChris Lattner   return 0;
15130fdc8d8SChris Lattner }
15230fdc8d8SChris Lattner 
153b9c1b51eSKate Stone const char *CFString::GlobPath(const char *path, std::string &expanded_path) {
15430fdc8d8SChris Lattner   glob_t globbuf;
155b9c1b51eSKate Stone   if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
15630fdc8d8SChris Lattner     expanded_path = globbuf.gl_pathv[0];
15730fdc8d8SChris Lattner     ::globfree(&globbuf);
158b9c1b51eSKate Stone   } else
15930fdc8d8SChris Lattner     expanded_path.clear();
16030fdc8d8SChris Lattner 
16130fdc8d8SChris Lattner   return expanded_path.c_str();
16230fdc8d8SChris Lattner }
163