1dda28197Spatrick //===-- CFCString.cpp -----------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "CFCString.h"
10061da546Spatrick #include <glob.h>
11061da546Spatrick #include <string>
12061da546Spatrick
13061da546Spatrick // CFCString constructor
CFCString(CFStringRef s)14061da546Spatrick CFCString::CFCString(CFStringRef s) : CFCReleaser<CFStringRef>(s) {}
15061da546Spatrick
16061da546Spatrick // CFCString copy constructor
17*f6aab3d8Srobert CFCString::CFCString(const CFCString &rhs) = default;
18061da546Spatrick
19061da546Spatrick // CFCString copy constructor
operator =(const CFCString & rhs)20061da546Spatrick CFCString &CFCString::operator=(const CFCString &rhs) {
21061da546Spatrick if (this != &rhs)
22061da546Spatrick *this = rhs;
23061da546Spatrick return *this;
24061da546Spatrick }
25061da546Spatrick
CFCString(const char * cstr,CFStringEncoding cstr_encoding)26061da546Spatrick CFCString::CFCString(const char *cstr, CFStringEncoding cstr_encoding)
27061da546Spatrick : CFCReleaser<CFStringRef>() {
28061da546Spatrick if (cstr && cstr[0]) {
29061da546Spatrick reset(
30061da546Spatrick ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
31061da546Spatrick }
32061da546Spatrick }
33061da546Spatrick
34061da546Spatrick // Destructor
35be691f3bSpatrick CFCString::~CFCString() = default;
36061da546Spatrick
GetFileSystemRepresentation(std::string & s)37061da546Spatrick const char *CFCString::GetFileSystemRepresentation(std::string &s) {
38061da546Spatrick return CFCString::FileSystemRepresentation(get(), s);
39061da546Spatrick }
40061da546Spatrick
SetFileSystemRepresentation(const char * path)41061da546Spatrick CFStringRef CFCString::SetFileSystemRepresentation(const char *path) {
42061da546Spatrick CFStringRef new_value = NULL;
43061da546Spatrick if (path && path[0])
44061da546Spatrick new_value =
45061da546Spatrick ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
46061da546Spatrick reset(new_value);
47061da546Spatrick return get();
48061da546Spatrick }
49061da546Spatrick
50061da546Spatrick CFStringRef
SetFileSystemRepresentationFromCFType(CFTypeRef cf_type)51061da546Spatrick CFCString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
52061da546Spatrick CFStringRef new_value = NULL;
53061da546Spatrick if (cf_type != NULL) {
54061da546Spatrick CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
55061da546Spatrick
56061da546Spatrick if (cf_type_id == ::CFStringGetTypeID()) {
57061da546Spatrick // Retain since we are using the existing object
58061da546Spatrick new_value = (CFStringRef)::CFRetain(cf_type);
59061da546Spatrick } else if (cf_type_id == ::CFURLGetTypeID()) {
60061da546Spatrick new_value =
61061da546Spatrick ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
62061da546Spatrick }
63061da546Spatrick }
64061da546Spatrick reset(new_value);
65061da546Spatrick return get();
66061da546Spatrick }
67061da546Spatrick
68061da546Spatrick CFStringRef
SetFileSystemRepresentationAndExpandTilde(const char * path)69061da546Spatrick CFCString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
70061da546Spatrick std::string expanded_path;
71061da546Spatrick if (CFCString::ExpandTildeInPath(path, expanded_path))
72061da546Spatrick SetFileSystemRepresentation(expanded_path.c_str());
73061da546Spatrick else
74061da546Spatrick reset();
75061da546Spatrick return get();
76061da546Spatrick }
77061da546Spatrick
UTF8(std::string & str)78061da546Spatrick const char *CFCString::UTF8(std::string &str) {
79061da546Spatrick return CFCString::UTF8(get(), str);
80061da546Spatrick }
81061da546Spatrick
82061da546Spatrick // Static function that puts a copy of the UTF8 contents of CF_STR into STR and
83061da546Spatrick // returns the C string pointer that is contained in STR when successful, else
84061da546Spatrick // NULL is returned. This allows the std::string parameter to own the extracted
85061da546Spatrick // string,
86061da546Spatrick // and also allows that string to be returned as a C string pointer that can be
87061da546Spatrick // used.
88061da546Spatrick
UTF8(CFStringRef cf_str,std::string & str)89061da546Spatrick const char *CFCString::UTF8(CFStringRef cf_str, std::string &str) {
90061da546Spatrick if (cf_str) {
91061da546Spatrick const CFStringEncoding encoding = kCFStringEncodingUTF8;
92061da546Spatrick CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
93061da546Spatrick max_utf8_str_len =
94061da546Spatrick CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
95061da546Spatrick if (max_utf8_str_len > 0) {
96061da546Spatrick str.resize(max_utf8_str_len);
97061da546Spatrick if (!str.empty()) {
98061da546Spatrick if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
99061da546Spatrick str.resize(strlen(str.c_str()));
100061da546Spatrick return str.c_str();
101061da546Spatrick }
102061da546Spatrick }
103061da546Spatrick }
104061da546Spatrick }
105061da546Spatrick return NULL;
106061da546Spatrick }
107061da546Spatrick
ExpandTildeInPath(const char * path,std::string & expanded_path)108061da546Spatrick const char *CFCString::ExpandTildeInPath(const char *path,
109061da546Spatrick std::string &expanded_path) {
110061da546Spatrick glob_t globbuf;
111061da546Spatrick if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
112061da546Spatrick expanded_path = globbuf.gl_pathv[0];
113061da546Spatrick ::globfree(&globbuf);
114061da546Spatrick } else
115061da546Spatrick expanded_path.clear();
116061da546Spatrick
117061da546Spatrick return expanded_path.c_str();
118061da546Spatrick }
119061da546Spatrick
120061da546Spatrick // Static function that puts a copy of the file system representation of CF_STR
121061da546Spatrick // into STR and returns the C string pointer that is contained in STR when
122061da546Spatrick // successful, else NULL is returned. This allows the std::string parameter to
123061da546Spatrick // own the extracted string, and also allows that string to be returned as a C
124061da546Spatrick // string pointer that can be used.
125061da546Spatrick
FileSystemRepresentation(CFStringRef cf_str,std::string & str)126061da546Spatrick const char *CFCString::FileSystemRepresentation(CFStringRef cf_str,
127061da546Spatrick std::string &str) {
128061da546Spatrick if (cf_str) {
129061da546Spatrick CFIndex max_length =
130061da546Spatrick ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
131061da546Spatrick if (max_length > 0) {
132061da546Spatrick str.resize(max_length);
133061da546Spatrick if (!str.empty()) {
134061da546Spatrick if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
135061da546Spatrick str.size())) {
136061da546Spatrick str.erase(::strlen(str.c_str()));
137061da546Spatrick return str.c_str();
138061da546Spatrick }
139061da546Spatrick }
140061da546Spatrick }
141061da546Spatrick }
142061da546Spatrick str.erase();
143061da546Spatrick return NULL;
144061da546Spatrick }
145061da546Spatrick
GetLength() const146061da546Spatrick CFIndex CFCString::GetLength() const {
147061da546Spatrick CFStringRef str = get();
148061da546Spatrick if (str)
149061da546Spatrick return CFStringGetLength(str);
150061da546Spatrick return 0;
151061da546Spatrick }
152