1 //===-- CFString.cpp --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Created by Greg Clayton on 1/16/08.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "CFString.h"
15 #include <string>
16 #include <glob.h>
17 
18 //----------------------------------------------------------------------
19 // CFString constructor
20 //----------------------------------------------------------------------
CFString(CFStringRef s)21 CFString::CFString(CFStringRef s) :
22     CFReleaser<CFStringRef> (s)
23 {
24 }
25 
26 //----------------------------------------------------------------------
27 // CFString copy constructor
28 //----------------------------------------------------------------------
CFString(const CFString & rhs)29 CFString::CFString(const CFString& rhs) :
30     CFReleaser<CFStringRef> (rhs)
31 {
32 
33 }
34 
35 //----------------------------------------------------------------------
36 // CFString copy constructor
37 //----------------------------------------------------------------------
38 CFString&
operator =(const CFString & rhs)39 CFString::operator=(const CFString& rhs)
40 {
41     if (this != &rhs)
42         *this = rhs;
43     return *this;
44 }
45 
CFString(const char * cstr,CFStringEncoding cstr_encoding)46 CFString::CFString (const char *cstr, CFStringEncoding cstr_encoding) :
47     CFReleaser<CFStringRef> ()
48 {
49     if (cstr && cstr[0])
50     {
51         reset(::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
52     }
53 }
54 
55 //----------------------------------------------------------------------
56 // Destructor
57 //----------------------------------------------------------------------
~CFString()58 CFString::~CFString()
59 {
60 }
61 
62 const char *
GetFileSystemRepresentation(std::string & s)63 CFString::GetFileSystemRepresentation(std::string& s)
64 {
65     return CFString::FileSystemRepresentation(get(), s);
66 }
67 
68 CFStringRef
SetFileSystemRepresentation(const char * path)69 CFString::SetFileSystemRepresentation (const char *path)
70 {
71     CFStringRef new_value = NULL;
72     if (path && path[0])
73         new_value = ::CFStringCreateWithFileSystemRepresentation (kCFAllocatorDefault, path);
74     reset(new_value);
75     return get();
76 }
77 
78 
79 CFStringRef
SetFileSystemRepresentationFromCFType(CFTypeRef cf_type)80 CFString::SetFileSystemRepresentationFromCFType (CFTypeRef cf_type)
81 {
82     CFStringRef new_value = NULL;
83     if (cf_type != NULL)
84     {
85         CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
86 
87         if (cf_type_id == ::CFStringGetTypeID())
88         {
89             // Retain since we are using the existing object
90             new_value = (CFStringRef)::CFRetain(cf_type);
91         }
92         else if (cf_type_id == ::CFURLGetTypeID())
93         {
94             new_value = ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
95         }
96     }
97     reset(new_value);
98     return get();
99 }
100 
101 CFStringRef
SetFileSystemRepresentationAndExpandTilde(const char * path)102 CFString::SetFileSystemRepresentationAndExpandTilde (const char *path)
103 {
104     std::string expanded_path;
105     if (CFString::GlobPath(path, expanded_path))
106         SetFileSystemRepresentation(expanded_path.c_str());
107     else
108         reset();
109     return get();
110 }
111 
112 const char *
UTF8(std::string & str)113 CFString::UTF8(std::string& str)
114 {
115     return CFString::UTF8(get(), str);
116 }
117 
118 // Static function that puts a copy of the UTF8 contents of CF_STR into STR
119 // and returns the C string pointer that is contained in STR when successful, else
120 // NULL is returned. This allows the std::string parameter to own the extracted string,
121 // and also allows that string to be returned as a C string pointer that can be used.
122 
123 const char *
UTF8(CFStringRef cf_str,std::string & str)124 CFString::UTF8 (CFStringRef cf_str, std::string& str)
125 {
126     if (cf_str)
127     {
128         const CFStringEncoding encoding = kCFStringEncodingUTF8;
129         CFIndex max_utf8_str_len = CFStringGetLength (cf_str);
130         max_utf8_str_len = CFStringGetMaximumSizeForEncoding (max_utf8_str_len, encoding);
131         if (max_utf8_str_len > 0)
132         {
133             str.resize(max_utf8_str_len);
134             if (!str.empty())
135             {
136                 if (CFStringGetCString (cf_str, &str[0], str.size(), encoding))
137                 {
138                     str.resize(strlen(str.c_str()));
139                     return str.c_str();
140                 }
141             }
142         }
143     }
144     return NULL;
145 }
146 
147 // Static function that puts a copy of the file system representation of CF_STR
148 // into STR and returns the C string pointer that is contained in STR when
149 // successful, else NULL is returned. This allows the std::string parameter
150 // to own the extracted string, and also allows that string to be returned as
151 // a C string pointer that can be used.
152 
153 const char *
FileSystemRepresentation(CFStringRef cf_str,std::string & str)154 CFString::FileSystemRepresentation (CFStringRef cf_str, std::string& str)
155 {
156     if (cf_str)
157     {
158         CFIndex max_length = ::CFStringGetMaximumSizeOfFileSystemRepresentation (cf_str);
159         if (max_length > 0)
160         {
161             str.resize(max_length);
162             if (!str.empty())
163             {
164                 if (::CFStringGetFileSystemRepresentation (cf_str, &str[0], str.size()))
165                 {
166                     str.erase(::strlen(str.c_str()));
167                     return str.c_str();
168                 }
169             }
170         }
171     }
172     str.erase();
173     return NULL;
174 }
175 
176 
177 CFIndex
GetLength() const178 CFString::GetLength() const
179 {
180     CFStringRef str = get();
181     if (str)
182         return CFStringGetLength (str);
183     return 0;
184 }
185 
186 
187 const char*
GlobPath(const char * path,std::string & expanded_path)188 CFString::GlobPath(const char* path, std::string &expanded_path)
189 {
190     glob_t globbuf;
191     if (::glob (path, GLOB_TILDE, NULL, &globbuf) == 0)
192     {
193         expanded_path = globbuf.gl_pathv[0];
194         ::globfree (&globbuf);
195     }
196     else
197         expanded_path.clear();
198 
199     return expanded_path.c_str();
200 }
201 
202