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 |
18 | CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {} |
19 | |
20 | // CFString copy constructor |
21 | CFString::CFString(const CFString &rhs) = default; |
22 | |
23 | // CFString copy constructor |
24 | CFString &CFString::operator=(const CFString &rhs) { |
25 | if (this != &rhs) |
26 | *this = rhs; |
27 | return *this; |
28 | } |
29 | |
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 |
39 | CFString::~CFString() = default; |
40 | |
41 | const char *CFString::GetFileSystemRepresentation(std::string &s) { |
42 | return CFString::FileSystemRepresentation(cf_str: get(), str&: s); |
43 | } |
44 | |
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 | |
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 |
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 | |
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 | |
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 | |
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 | |
138 | CFIndex CFString::GetLength() const { |
139 | CFStringRef str = get(); |
140 | if (str) |
141 | return CFStringGetLength(str); |
142 | return 0; |
143 | } |
144 | |
145 | const char *CFString::GlobPath(const char *path, std::string &expanded_path) { |
146 | glob_t globbuf; |
147 | if (::glob(pattern: path, GLOB_TILDE, NULL, pglob: &globbuf) == 0) { |
148 | expanded_path = globbuf.gl_pathv[0]; |
149 | ::globfree(pglob: &globbuf); |
150 | } else |
151 | expanded_path.clear(); |
152 | |
153 | return expanded_path.c_str(); |
154 | } |
155 | |