1 //===-- CFString.cpp --------------------------------------------*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  Created by Greg Clayton on 1/16/08.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "CFString.h"
14 #include <glob.h>
15 #include <string>
16 
17 // CFString constructor
CFString(CFStringRef s)18 CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {}
19 
20 // CFString copy constructor
CFString(const CFString & rhs)21 CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {}
22 
23 // CFString copy constructor
operator =(const CFString & rhs)24 CFString &CFString::operator=(const CFString &rhs) {
25   if (this != &rhs)
26     *this = rhs;
27   return *this;
28 }
29 
CFString(const char * cstr,CFStringEncoding cstr_encoding)30 CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding)
31     : CFReleaser<CFStringRef>() {
32   if (cstr && cstr[0]) {
33     reset(
34         ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
35   }
36 }
37 
38 // Destructor
~CFString()39 CFString::~CFString() {}
40 
GetFileSystemRepresentation(std::string & s)41 const char *CFString::GetFileSystemRepresentation(std::string &s) {
42   return CFString::FileSystemRepresentation(get(), s);
43 }
44 
SetFileSystemRepresentation(const char * path)45 CFStringRef CFString::SetFileSystemRepresentation(const char *path) {
46   CFStringRef new_value = NULL;
47   if (path && path[0])
48     new_value =
49         ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
50   reset(new_value);
51   return get();
52 }
53 
SetFileSystemRepresentationFromCFType(CFTypeRef cf_type)54 CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
55   CFStringRef new_value = NULL;
56   if (cf_type != NULL) {
57     CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
58 
59     if (cf_type_id == ::CFStringGetTypeID()) {
60       // Retain since we are using the existing object
61       new_value = (CFStringRef)::CFRetain(cf_type);
62     } else if (cf_type_id == ::CFURLGetTypeID()) {
63       new_value =
64           ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
65     }
66   }
67   reset(new_value);
68   return get();
69 }
70 
71 CFStringRef
SetFileSystemRepresentationAndExpandTilde(const char * path)72 CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
73   std::string expanded_path;
74   if (CFString::GlobPath(path, expanded_path))
75     SetFileSystemRepresentation(expanded_path.c_str());
76   else
77     reset();
78   return get();
79 }
80 
UTF8(std::string & str)81 const char *CFString::UTF8(std::string &str) {
82   return CFString::UTF8(get(), str);
83 }
84 
85 // Static function that puts a copy of the UTF8 contents of CF_STR into STR
86 // and returns the C string pointer that is contained in STR when successful,
87 // else
88 // NULL is returned. This allows the std::string parameter to own the extracted
89 // string,
90 // and also allows that string to be returned as a C string pointer that can be
91 // used.
92 
UTF8(CFStringRef cf_str,std::string & str)93 const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
94   if (cf_str) {
95     const CFStringEncoding encoding = kCFStringEncodingUTF8;
96     CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
97     max_utf8_str_len =
98         CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
99     if (max_utf8_str_len > 0) {
100       str.resize(max_utf8_str_len);
101       if (!str.empty()) {
102         if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
103           str.resize(strlen(str.c_str()));
104           return str.c_str();
105         }
106       }
107     }
108   }
109   return NULL;
110 }
111 
112 // Static function that puts a copy of the file system representation of CF_STR
113 // into STR and returns the C string pointer that is contained in STR when
114 // successful, else NULL is returned. This allows the std::string parameter
115 // to own the extracted string, and also allows that string to be returned as
116 // a C string pointer that can be used.
117 
FileSystemRepresentation(CFStringRef cf_str,std::string & str)118 const char *CFString::FileSystemRepresentation(CFStringRef cf_str,
119                                                std::string &str) {
120   if (cf_str) {
121     CFIndex max_length =
122         ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
123     if (max_length > 0) {
124       str.resize(max_length);
125       if (!str.empty()) {
126         if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
127                                                   str.size())) {
128           str.erase(::strlen(str.c_str()));
129           return str.c_str();
130         }
131       }
132     }
133   }
134   str.erase();
135   return NULL;
136 }
137 
GetLength() const138 CFIndex CFString::GetLength() const {
139   CFStringRef str = get();
140   if (str)
141     return CFStringGetLength(str);
142   return 0;
143 }
144 
GlobPath(const char * path,std::string & expanded_path)145 const char *CFString::GlobPath(const char *path, std::string &expanded_path) {
146   glob_t globbuf;
147   if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
148     expanded_path = globbuf.gl_pathv[0];
149     ::globfree(&globbuf);
150   } else
151     expanded_path.clear();
152 
153   return expanded_path.c_str();
154 }
155