1311128Sdim//===-- CFString.cpp --------------------------------------------*- C++ -*-===//
2311128Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6311128Sdim//
7311128Sdim//===----------------------------------------------------------------------===//
8311128Sdim//
9311128Sdim//  Created by Greg Clayton on 1/16/08.
10311128Sdim//
11311128Sdim//===----------------------------------------------------------------------===//
12311128Sdim
13311128Sdim#include "CFString.h"
14311128Sdim#include <glob.h>
15311128Sdim#include <string>
16311128Sdim
17311128Sdim// CFString constructor
18311128SdimCFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {}
19311128Sdim
20311128Sdim// CFString copy constructor
21311128SdimCFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {}
22311128Sdim
23311128Sdim// CFString copy constructor
24311128SdimCFString &CFString::operator=(const CFString &rhs) {
25311128Sdim  if (this != &rhs)
26311128Sdim    *this = rhs;
27311128Sdim  return *this;
28311128Sdim}
29311128Sdim
30311128SdimCFString::CFString(const char *cstr, CFStringEncoding cstr_encoding)
31311128Sdim    : CFReleaser<CFStringRef>() {
32311128Sdim  if (cstr && cstr[0]) {
33311128Sdim    reset(
34311128Sdim        ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
35311128Sdim  }
36311128Sdim}
37311128Sdim
38311128Sdim// Destructor
39311128SdimCFString::~CFString() {}
40311128Sdim
41311128Sdimconst char *CFString::GetFileSystemRepresentation(std::string &s) {
42311128Sdim  return CFString::FileSystemRepresentation(get(), s);
43311128Sdim}
44311128Sdim
45311128SdimCFStringRef CFString::SetFileSystemRepresentation(const char *path) {
46311128Sdim  CFStringRef new_value = NULL;
47311128Sdim  if (path && path[0])
48311128Sdim    new_value =
49311128Sdim        ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
50311128Sdim  reset(new_value);
51311128Sdim  return get();
52311128Sdim}
53311128Sdim
54311128SdimCFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
55311128Sdim  CFStringRef new_value = NULL;
56311128Sdim  if (cf_type != NULL) {
57311128Sdim    CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
58311128Sdim
59311128Sdim    if (cf_type_id == ::CFStringGetTypeID()) {
60311128Sdim      // Retain since we are using the existing object
61311128Sdim      new_value = (CFStringRef)::CFRetain(cf_type);
62311128Sdim    } else if (cf_type_id == ::CFURLGetTypeID()) {
63311128Sdim      new_value =
64311128Sdim          ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
65311128Sdim    }
66311128Sdim  }
67311128Sdim  reset(new_value);
68311128Sdim  return get();
69311128Sdim}
70311128Sdim
71311128SdimCFStringRef
72311128SdimCFString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
73311128Sdim  std::string expanded_path;
74311128Sdim  if (CFString::GlobPath(path, expanded_path))
75311128Sdim    SetFileSystemRepresentation(expanded_path.c_str());
76311128Sdim  else
77311128Sdim    reset();
78311128Sdim  return get();
79311128Sdim}
80311128Sdim
81311128Sdimconst char *CFString::UTF8(std::string &str) {
82311128Sdim  return CFString::UTF8(get(), str);
83311128Sdim}
84311128Sdim
85341825Sdim// Static function that puts a copy of the UTF8 contents of CF_STR into STR and
86341825Sdim// returns the C string pointer that is contained in STR when successful, else
87311128Sdim// NULL is returned. This allows the std::string parameter to own the extracted
88311128Sdim// string,
89311128Sdim// and also allows that string to be returned as a C string pointer that can be
90311128Sdim// used.
91311128Sdim
92311128Sdimconst char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
93311128Sdim  if (cf_str) {
94311128Sdim    const CFStringEncoding encoding = kCFStringEncodingUTF8;
95311128Sdim    CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
96311128Sdim    max_utf8_str_len =
97311128Sdim        CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
98311128Sdim    if (max_utf8_str_len > 0) {
99311128Sdim      str.resize(max_utf8_str_len);
100311128Sdim      if (!str.empty()) {
101311128Sdim        if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
102311128Sdim          str.resize(strlen(str.c_str()));
103311128Sdim          return str.c_str();
104311128Sdim        }
105311128Sdim      }
106311128Sdim    }
107311128Sdim  }
108311128Sdim  return NULL;
109311128Sdim}
110311128Sdim
111311128Sdim// Static function that puts a copy of the file system representation of CF_STR
112311128Sdim// into STR and returns the C string pointer that is contained in STR when
113341825Sdim// successful, else NULL is returned. This allows the std::string parameter to
114341825Sdim// own the extracted string, and also allows that string to be returned as a C
115341825Sdim// string pointer that can be used.
116311128Sdim
117311128Sdimconst char *CFString::FileSystemRepresentation(CFStringRef cf_str,
118311128Sdim                                               std::string &str) {
119311128Sdim  if (cf_str) {
120311128Sdim    CFIndex max_length =
121311128Sdim        ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
122311128Sdim    if (max_length > 0) {
123311128Sdim      str.resize(max_length);
124311128Sdim      if (!str.empty()) {
125311128Sdim        if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
126311128Sdim                                                  str.size())) {
127311128Sdim          str.erase(::strlen(str.c_str()));
128311128Sdim          return str.c_str();
129311128Sdim        }
130311128Sdim      }
131311128Sdim    }
132311128Sdim  }
133311128Sdim  str.erase();
134311128Sdim  return NULL;
135311128Sdim}
136311128Sdim
137311128SdimCFIndex CFString::GetLength() const {
138311128Sdim  CFStringRef str = get();
139311128Sdim  if (str)
140311128Sdim    return CFStringGetLength(str);
141311128Sdim  return 0;
142311128Sdim}
143311128Sdim
144311128Sdimconst char *CFString::GlobPath(const char *path, std::string &expanded_path) {
145311128Sdim  glob_t globbuf;
146311128Sdim  if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
147311128Sdim    expanded_path = globbuf.gl_pathv[0];
148311128Sdim    ::globfree(&globbuf);
149311128Sdim  } else
150311128Sdim    expanded_path.clear();
151311128Sdim
152311128Sdim  return expanded_path.c_str();
153311128Sdim}
154