//===-- CFString.cpp --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Created by Greg Clayton on 1/16/08.
//
//===----------------------------------------------------------------------===//
#include "CFString.h"
#include <glob.h>
#include <string>
// CFString constructor
CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {}
// CFString copy constructor
CFString::CFString(const CFString &rhs) = default;
// CFString copy constructor
CFString &CFString::operator=(const CFString &rhs) {
if (this != &rhs)
*this = rhs;
return *this;
}
CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding)
: CFReleaser<CFStringRef>() {
if (cstr && cstr[0]) {
reset(
::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding));
}
}
// Destructor
CFString::~CFString() = default;
const char *CFString::GetFileSystemRepresentation(std::string &s) {
return CFString::FileSystemRepresentation(get(), s);
}
CFStringRef CFString::SetFileSystemRepresentation(const char *path) {
CFStringRef new_value = NULL;
if (path && path[0])
new_value =
::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path);
reset(new_value);
return get();
}
CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) {
CFStringRef new_value = NULL;
if (cf_type != NULL) {
CFTypeID cf_type_id = ::CFGetTypeID(cf_type);
if (cf_type_id == ::CFStringGetTypeID()) {
// Retain since we are using the existing object
new_value = (CFStringRef)::CFRetain(cf_type);
} else if (cf_type_id == ::CFURLGetTypeID()) {
new_value =
::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle);
}
}
reset(new_value);
return get();
}
CFStringRef
CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) {
std::string expanded_path;
if (CFString::GlobPath(path, expanded_path))
SetFileSystemRepresentation(expanded_path.c_str());
else
reset();
return get();
}
const char *CFString::UTF8(std::string &str) {
return CFString::UTF8(get(), str);
}
// Static function that puts a copy of the UTF8 contents of CF_STR into STR
// and returns the C string pointer that is contained in STR when successful,
// else
// NULL is returned. This allows the std::string parameter to own the extracted
// string,
// and also allows that string to be returned as a C string pointer that can be
// used.
const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
if (cf_str) {
const CFStringEncoding encoding = kCFStringEncodingUTF8;
CFIndex max_utf8_str_len = CFStringGetLength(cf_str);
max_utf8_str_len =
CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding);
if (max_utf8_str_len > 0) {
str.resize(max_utf8_str_len);
if (!str.empty()) {
if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) {
str.resize(strlen(str.c_str()));
return str.c_str();
}
}
}
}
return NULL;
}
// Static function that puts a copy of the file system representation of CF_STR
// into STR and returns the C string pointer that is contained in STR when
// successful, else NULL is returned. This allows the std::string parameter
// to own the extracted string, and also allows that string to be returned as
// a C string pointer that can be used.
const char *CFString::FileSystemRepresentation(CFStringRef cf_str,
std::string &str) {
if (cf_str) {
CFIndex max_length =
::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str);
if (max_length > 0) {
str.resize(max_length);
if (!str.empty()) {
if (::CFStringGetFileSystemRepresentation(cf_str, &str[0],
str.size())) {
str.erase(::strlen(str.c_str()));
return str.c_str();
}
}
}
}
str.erase();
return NULL;
}
CFIndex CFString::GetLength() const {
CFStringRef str = get();
if (str)
return CFStringGetLength(str);
return 0;
}
const char *CFString::GlobPath(const char *path, std::string &expanded_path) {
glob_t globbuf;
if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) {
expanded_path = globbuf.gl_pathv[0];
::globfree(&globbuf);
} else
expanded_path.clear();
return expanded_path.c_str();
}