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