1061da546Spatrick //===-- CFString.cpp --------------------------------------------*- C++ -*-===//
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 // Created by Greg Clayton on 1/16/08.
10061da546Spatrick //
11061da546Spatrick //===----------------------------------------------------------------------===//
12061da546Spatrick
13061da546Spatrick #include "CFString.h"
14061da546Spatrick #include <glob.h>
15061da546Spatrick #include <string>
16061da546Spatrick
17061da546Spatrick // CFString constructor
CFString(CFStringRef s)18061da546Spatrick CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {}
19061da546Spatrick
20061da546Spatrick // CFString copy constructor
21*f6aab3d8Srobert CFString::CFString(const CFString &rhs) = default;
22061da546Spatrick
23061da546Spatrick // CFString copy constructor
operator =(const CFString & rhs)24061da546Spatrick CFString &CFString::operator=(const CFString &rhs) {
25061da546Spatrick if (this != &rhs)
26061da546Spatrick *this = rhs;
27061da546Spatrick return *this;
28061da546Spatrick }
29061da546Spatrick
CFString(const char * cstr,CFStringEncoding cstr_encoding)30061da546Spatrick CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding)
31061da546Spatrick : CFReleaser<CFStringRef>() {
32061da546Spatrick if (cstr && cstr[0]) {
33061da546Spatrick reset(
34061da546Spatrick ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
35061da546Spatrick }
36061da546Spatrick }
37061da546Spatrick
38061da546Spatrick // Destructor
39*f6aab3d8Srobert CFString::~CFString() = default;
40061da546Spatrick
GetFileSystemRepresentation(std::string & s)41061da546Spatrick const char *CFString::GetFileSystemRepresentation(std::string &s) {
42061da546Spatrick return CFString::FileSystemRepresentation(get(), s);
43061da546Spatrick }
44061da546Spatrick
SetFileSystemRepresentation(const char * path)45061da546Spatrick CFStringRef CFString::SetFileSystemRepresentation(const char *path) {
46061da546Spatrick CFStringRef new_value = NULL;
47061da546Spatrick if (path && path[0])
48061da546Spatrick new_value =
49061da546Spatrick ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
50061da546Spatrick reset(new_value);
51061da546Spatrick return get();
52061da546Spatrick }
53061da546Spatrick
SetFileSystemRepresentationFromCFType(CFTypeRef cf_type)54061da546Spatrick CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
55061da546Spatrick CFStringRef new_value = NULL;
56061da546Spatrick if (cf_type != NULL) {
57061da546Spatrick CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
58061da546Spatrick
59061da546Spatrick if (cf_type_id == ::CFStringGetTypeID()) {
60061da546Spatrick // Retain since we are using the existing object
61061da546Spatrick new_value = (CFStringRef)::CFRetain(cf_type);
62061da546Spatrick } else if (cf_type_id == ::CFURLGetTypeID()) {
63061da546Spatrick new_value =
64061da546Spatrick ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
65061da546Spatrick }
66061da546Spatrick }
67061da546Spatrick reset(new_value);
68061da546Spatrick return get();
69061da546Spatrick }
70061da546Spatrick
71061da546Spatrick CFStringRef
SetFileSystemRepresentationAndExpandTilde(const char * path)72061da546Spatrick CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
73061da546Spatrick std::string expanded_path;
74061da546Spatrick if (CFString::GlobPath(path, expanded_path))
75061da546Spatrick SetFileSystemRepresentation(expanded_path.c_str());
76061da546Spatrick else
77061da546Spatrick reset();
78061da546Spatrick return get();
79061da546Spatrick }
80061da546Spatrick
UTF8(std::string & str)81061da546Spatrick const char *CFString::UTF8(std::string &str) {
82061da546Spatrick return CFString::UTF8(get(), str);
83061da546Spatrick }
84061da546Spatrick
85061da546Spatrick // Static function that puts a copy of the UTF8 contents of CF_STR into STR
86061da546Spatrick // and returns the C string pointer that is contained in STR when successful,
87061da546Spatrick // else
88061da546Spatrick // NULL is returned. This allows the std::string parameter to own the extracted
89061da546Spatrick // string,
90061da546Spatrick // and also allows that string to be returned as a C string pointer that can be
91061da546Spatrick // used.
92061da546Spatrick
UTF8(CFStringRef cf_str,std::string & str)93061da546Spatrick const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
94061da546Spatrick if (cf_str) {
95061da546Spatrick const CFStringEncoding encoding = kCFStringEncodingUTF8;
96061da546Spatrick CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
97061da546Spatrick max_utf8_str_len =
98061da546Spatrick CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
99061da546Spatrick if (max_utf8_str_len > 0) {
100061da546Spatrick str.resize(max_utf8_str_len);
101061da546Spatrick if (!str.empty()) {
102061da546Spatrick if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
103061da546Spatrick str.resize(strlen(str.c_str()));
104061da546Spatrick return str.c_str();
105061da546Spatrick }
106061da546Spatrick }
107061da546Spatrick }
108061da546Spatrick }
109061da546Spatrick return NULL;
110061da546Spatrick }
111061da546Spatrick
112061da546Spatrick // Static function that puts a copy of the file system representation of CF_STR
113061da546Spatrick // into STR and returns the C string pointer that is contained in STR when
114061da546Spatrick // successful, else NULL is returned. This allows the std::string parameter
115061da546Spatrick // to own the extracted string, and also allows that string to be returned as
116061da546Spatrick // a C string pointer that can be used.
117061da546Spatrick
FileSystemRepresentation(CFStringRef cf_str,std::string & str)118061da546Spatrick const char *CFString::FileSystemRepresentation(CFStringRef cf_str,
119061da546Spatrick std::string &str) {
120061da546Spatrick if (cf_str) {
121061da546Spatrick CFIndex max_length =
122061da546Spatrick ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
123061da546Spatrick if (max_length > 0) {
124061da546Spatrick str.resize(max_length);
125061da546Spatrick if (!str.empty()) {
126061da546Spatrick if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
127061da546Spatrick str.size())) {
128061da546Spatrick str.erase(::strlen(str.c_str()));
129061da546Spatrick return str.c_str();
130061da546Spatrick }
131061da546Spatrick }
132061da546Spatrick }
133061da546Spatrick }
134061da546Spatrick str.erase();
135061da546Spatrick return NULL;
136061da546Spatrick }
137061da546Spatrick
GetLength() const138061da546Spatrick CFIndex CFString::GetLength() const {
139061da546Spatrick CFStringRef str = get();
140061da546Spatrick if (str)
141061da546Spatrick return CFStringGetLength(str);
142061da546Spatrick return 0;
143061da546Spatrick }
144061da546Spatrick
GlobPath(const char * path,std::string & expanded_path)145061da546Spatrick const char *CFString::GlobPath(const char *path, std::string &expanded_path) {
146061da546Spatrick glob_t globbuf;
147061da546Spatrick if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
148061da546Spatrick expanded_path = globbuf.gl_pathv[0];
149061da546Spatrick ::globfree(&globbuf);
150061da546Spatrick } else
151061da546Spatrick expanded_path.clear();
152061da546Spatrick
153061da546Spatrick return expanded_path.c_str();
154061da546Spatrick }
155