130fdc8d8SChris Lattner //===-- CFString.cpp --------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner //
1030fdc8d8SChris Lattner //  Created by Greg Clayton on 1/16/08.
1130fdc8d8SChris Lattner //
1230fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
1330fdc8d8SChris Lattner 
1430fdc8d8SChris Lattner #include "CFString.h"
1530fdc8d8SChris Lattner #include <glob.h>
16*b9c1b51eSKate Stone #include <string>
1730fdc8d8SChris Lattner 
1830fdc8d8SChris Lattner //----------------------------------------------------------------------
1930fdc8d8SChris Lattner // CFString constructor
2030fdc8d8SChris Lattner //----------------------------------------------------------------------
21*b9c1b51eSKate Stone CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {}
2230fdc8d8SChris Lattner 
2330fdc8d8SChris Lattner //----------------------------------------------------------------------
2430fdc8d8SChris Lattner // CFString copy constructor
2530fdc8d8SChris Lattner //----------------------------------------------------------------------
26*b9c1b51eSKate Stone CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {}
2730fdc8d8SChris Lattner 
2830fdc8d8SChris Lattner //----------------------------------------------------------------------
2930fdc8d8SChris Lattner // CFString copy constructor
3030fdc8d8SChris Lattner //----------------------------------------------------------------------
31*b9c1b51eSKate Stone CFString &CFString::operator=(const CFString &rhs) {
3230fdc8d8SChris Lattner   if (this != &rhs)
3330fdc8d8SChris Lattner     *this = rhs;
3430fdc8d8SChris Lattner   return *this;
3530fdc8d8SChris Lattner }
3630fdc8d8SChris Lattner 
37*b9c1b51eSKate Stone CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding)
38*b9c1b51eSKate Stone     : CFReleaser<CFStringRef>() {
39*b9c1b51eSKate Stone   if (cstr && cstr[0]) {
40*b9c1b51eSKate Stone     reset(
41*b9c1b51eSKate Stone         ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
4230fdc8d8SChris Lattner   }
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
4530fdc8d8SChris Lattner //----------------------------------------------------------------------
4630fdc8d8SChris Lattner // Destructor
4730fdc8d8SChris Lattner //----------------------------------------------------------------------
48*b9c1b51eSKate Stone CFString::~CFString() {}
4930fdc8d8SChris Lattner 
50*b9c1b51eSKate Stone const char *CFString::GetFileSystemRepresentation(std::string &s) {
5130fdc8d8SChris Lattner   return CFString::FileSystemRepresentation(get(), s);
5230fdc8d8SChris Lattner }
5330fdc8d8SChris Lattner 
54*b9c1b51eSKate Stone CFStringRef CFString::SetFileSystemRepresentation(const char *path) {
5530fdc8d8SChris Lattner   CFStringRef new_value = NULL;
5630fdc8d8SChris Lattner   if (path && path[0])
57*b9c1b51eSKate Stone     new_value =
58*b9c1b51eSKate Stone         ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
5930fdc8d8SChris Lattner   reset(new_value);
6030fdc8d8SChris Lattner   return get();
6130fdc8d8SChris Lattner }
6230fdc8d8SChris Lattner 
63*b9c1b51eSKate Stone CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
6430fdc8d8SChris Lattner   CFStringRef new_value = NULL;
65*b9c1b51eSKate Stone   if (cf_type != NULL) {
6630fdc8d8SChris Lattner     CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
6730fdc8d8SChris Lattner 
68*b9c1b51eSKate Stone     if (cf_type_id == ::CFStringGetTypeID()) {
6930fdc8d8SChris Lattner       // Retain since we are using the existing object
7030fdc8d8SChris Lattner       new_value = (CFStringRef)::CFRetain(cf_type);
71*b9c1b51eSKate Stone     } else if (cf_type_id == ::CFURLGetTypeID()) {
72*b9c1b51eSKate Stone       new_value =
73*b9c1b51eSKate Stone           ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
7430fdc8d8SChris Lattner     }
7530fdc8d8SChris Lattner   }
7630fdc8d8SChris Lattner   reset(new_value);
7730fdc8d8SChris Lattner   return get();
7830fdc8d8SChris Lattner }
7930fdc8d8SChris Lattner 
8030fdc8d8SChris Lattner CFStringRef
81*b9c1b51eSKate Stone CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
8230fdc8d8SChris Lattner   std::string expanded_path;
8330fdc8d8SChris Lattner   if (CFString::GlobPath(path, expanded_path))
8430fdc8d8SChris Lattner     SetFileSystemRepresentation(expanded_path.c_str());
8530fdc8d8SChris Lattner   else
8630fdc8d8SChris Lattner     reset();
8730fdc8d8SChris Lattner   return get();
8830fdc8d8SChris Lattner }
8930fdc8d8SChris Lattner 
90*b9c1b51eSKate Stone const char *CFString::UTF8(std::string &str) {
9130fdc8d8SChris Lattner   return CFString::UTF8(get(), str);
9230fdc8d8SChris Lattner }
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner // Static function that puts a copy of the UTF8 contents of CF_STR into STR
95*b9c1b51eSKate Stone // and returns the C string pointer that is contained in STR when successful,
96*b9c1b51eSKate Stone // else
97*b9c1b51eSKate Stone // NULL is returned. This allows the std::string parameter to own the extracted
98*b9c1b51eSKate Stone // string,
99*b9c1b51eSKate Stone // and also allows that string to be returned as a C string pointer that can be
100*b9c1b51eSKate Stone // used.
10130fdc8d8SChris Lattner 
102*b9c1b51eSKate Stone const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
103*b9c1b51eSKate Stone   if (cf_str) {
10430fdc8d8SChris Lattner     const CFStringEncoding encoding = kCFStringEncodingUTF8;
10530fdc8d8SChris Lattner     CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
106*b9c1b51eSKate Stone     max_utf8_str_len =
107*b9c1b51eSKate Stone         CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
108*b9c1b51eSKate Stone     if (max_utf8_str_len > 0) {
10930fdc8d8SChris Lattner       str.resize(max_utf8_str_len);
110*b9c1b51eSKate Stone       if (!str.empty()) {
111*b9c1b51eSKate Stone         if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
11230fdc8d8SChris Lattner           str.resize(strlen(str.c_str()));
11330fdc8d8SChris Lattner           return str.c_str();
11430fdc8d8SChris Lattner         }
11530fdc8d8SChris Lattner       }
11630fdc8d8SChris Lattner     }
11730fdc8d8SChris Lattner   }
11830fdc8d8SChris Lattner   return NULL;
11930fdc8d8SChris Lattner }
12030fdc8d8SChris Lattner 
12130fdc8d8SChris Lattner // Static function that puts a copy of the file system representation of CF_STR
12230fdc8d8SChris Lattner // into STR and returns the C string pointer that is contained in STR when
12330fdc8d8SChris Lattner // successful, else NULL is returned. This allows the std::string parameter
12430fdc8d8SChris Lattner // to own the extracted string, and also allows that string to be returned as
12530fdc8d8SChris Lattner // a C string pointer that can be used.
12630fdc8d8SChris Lattner 
127*b9c1b51eSKate Stone const char *CFString::FileSystemRepresentation(CFStringRef cf_str,
128*b9c1b51eSKate Stone                                                std::string &str) {
129*b9c1b51eSKate Stone   if (cf_str) {
130*b9c1b51eSKate Stone     CFIndex max_length =
131*b9c1b51eSKate Stone         ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
132*b9c1b51eSKate Stone     if (max_length > 0) {
13330fdc8d8SChris Lattner       str.resize(max_length);
134*b9c1b51eSKate Stone       if (!str.empty()) {
135*b9c1b51eSKate Stone         if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
136*b9c1b51eSKate Stone                                                   str.size())) {
13730fdc8d8SChris Lattner           str.erase(::strlen(str.c_str()));
13830fdc8d8SChris Lattner           return str.c_str();
13930fdc8d8SChris Lattner         }
14030fdc8d8SChris Lattner       }
14130fdc8d8SChris Lattner     }
14230fdc8d8SChris Lattner   }
14330fdc8d8SChris Lattner   str.erase();
14430fdc8d8SChris Lattner   return NULL;
14530fdc8d8SChris Lattner }
14630fdc8d8SChris Lattner 
147*b9c1b51eSKate Stone CFIndex CFString::GetLength() const {
14830fdc8d8SChris Lattner   CFStringRef str = get();
14930fdc8d8SChris Lattner   if (str)
15030fdc8d8SChris Lattner     return CFStringGetLength(str);
15130fdc8d8SChris Lattner   return 0;
15230fdc8d8SChris Lattner }
15330fdc8d8SChris Lattner 
154*b9c1b51eSKate Stone const char *CFString::GlobPath(const char *path, std::string &expanded_path) {
15530fdc8d8SChris Lattner   glob_t globbuf;
156*b9c1b51eSKate Stone   if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
15730fdc8d8SChris Lattner     expanded_path = globbuf.gl_pathv[0];
15830fdc8d8SChris Lattner     ::globfree(&globbuf);
159*b9c1b51eSKate Stone   } else
16030fdc8d8SChris Lattner     expanded_path.clear();
16130fdc8d8SChris Lattner 
16230fdc8d8SChris Lattner   return expanded_path.c_str();
16330fdc8d8SChris Lattner }
164