Sources/Model/Foundation/Files/CFFile.mm
/* |
<codex> |
<import>CFFile.h</import> |
</codex> |
*/ |
#pragma mark - |
#pragma mark Private - Headers |
#import "CFFile.h" |
#pragma mark - |
#pragma mark Private - Namespaces |
using namespace CF; |
#pragma mark - |
#pragma mark Private - Type Definitions |
typedef NSArray* NSArrayRef; |
typedef NSString* NSStringRef; |
#pragma mark - |
#pragma mark Private - Utilities - Files |
static bool CFFileGetFileSize(CFURLRef pURL, |
CFIndex* pFileSize) |
{ |
CFErrorRef pError = nullptr; |
CFNumberRef pSize = nullptr; |
bool bSuccess = CFURLCopyResourcePropertyForKey(pURL, |
kCFURLFileSizeKey, |
&pSize, |
&pError); |
if(bSuccess) |
{ |
bSuccess = CFNumberGetValue(pSize, kCFNumberSInt64Type, pFileSize); |
if(!bSuccess) |
{ |
*pFileSize = 0; |
} // if |
} // if |
if(pSize != nullptr) |
{ |
CFRelease(pSize); |
} // if |
return bSuccess; |
} // CFFileGetFileSize |
static CFIndex CFFileAcquire(const CFIndex& nSize, |
UInt8* pBuffer, |
CFURLRef pURL) |
{ |
CFIndex nLength = 0; |
CFReadStreamRef pStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, pURL); |
if(pStream != nullptr) |
{ |
if(CFReadStreamOpen(pStream)) |
{ |
nLength = CFReadStreamRead(pStream, pBuffer, nSize); |
CFReadStreamClose(pStream); |
} // if |
CFRelease(pStream); |
} // if |
return nLength; |
} // CFFileAcquire |
static UInt8* CFFileCreateBuffer(CFIndex& nLength, |
CFURLRef pURL) |
{ |
CFIndex nSize = 0; |
UInt8* pBuffer = nullptr; |
if(CFFileGetFileSize(pURL, &nSize)) |
{ |
pBuffer = (UInt8 *)calloc(nSize, sizeof(UInt8)); |
if(pBuffer != nullptr) |
{ |
CFIndex nReadSz = CFFileAcquire(nSize, pBuffer, pURL); |
nLength = (nReadSz == nSize) ? nReadSz : -1; |
} // if |
} // if |
return pBuffer; |
} // CFFileCreateBuffer |
static CFDataRef CFFileCreate(CFURLRef pURL) |
{ |
CFDataRef pData = nullptr; |
if(pURL != nullptr) |
{ |
CFIndex nLength = 0; |
UInt8* pBuffer = CFFileCreateBuffer(nLength, pURL); |
if(pBuffer != nullptr) |
{ |
pData = CFDataCreate(kCFAllocatorDefault, |
pBuffer, |
nLength); |
free(pBuffer); |
} // if |
} // if |
return pData; |
} // CFFileCreate |
#pragma mark - |
#pragma mark Private - Utilities - URLs |
static CFURLRef CFFileCreateURL(CFStringRef pPathname) |
{ |
CFURLRef pURL = nullptr; |
if(pPathname != nullptr) |
{ |
pURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, pPathname, kCFURLPOSIXPathStyle, false); |
} // if |
return pURL; |
} // CFFileCreateURL |
static CFURLRef CFFileCreateURL(CFStringRef pName, |
CFStringRef pExt) |
{ |
CFURLRef pURL = nullptr; |
if(pName != nullptr) |
{ |
CFBundleRef pBundle = CFBundleGetMainBundle(); |
if(pBundle != nullptr) |
{ |
pURL = CFBundleCopyResourceURL(pBundle, pName, pExt, nullptr); |
} // if |
} // if |
return pURL; |
} // CFFileCreate |
static CFURLRef CFFileCreateURL(const CFSearchPathDomainMask& domain, |
const CFSearchPathDirectory& directory, |
CFStringRef pDirName, |
CFStringRef pFileName, |
CFStringRef pFileExt) |
{ |
CFURLRef pURL = nullptr; |
if(pFileName && pDirName) |
{ |
CFArrayRef pLibPaths = CFArrayRef(NSSearchPathForDirectoriesInDomains(directory, domain, YES)); |
if(pLibPaths != nullptr) |
{ |
CFStringRef pDirPath = CFStringRef(CFArrayGetValueAtIndex(pLibPaths, 0)); |
CFStringRef pValues[3] = {pDirPath, pDirName, pFileName}; |
CFArrayRef pComponents = CFArrayCreate(kCFAllocatorDefault, |
(const void **)&pValues, |
3, |
&kCFTypeArrayCallBacks); |
if(pComponents) |
{ |
CFStringRef pPathname = CFStringCreateByCombiningStrings(kCFAllocatorDefault, |
pComponents, |
CFSTR("/")); |
if(pPathname) |
{ |
if(pFileExt != nullptr) |
{ |
CFStringRef pFormat = CFSTR("%@.%@"); |
CFStringRef pFullPath = CFStringCreateWithFormat(kCFAllocatorDefault, |
nullptr, |
pFormat, |
pPathname, |
pFileExt); |
if(pFullPath) |
{ |
pURL = CFFileCreateURL(pFullPath); |
CFRelease(pFullPath); |
} // if |
} // if |
else |
{ |
pURL = CFFileCreateURL(pPathname); |
} // else |
CFRelease(pPathname); |
} // if |
CFRelease(pComponents); |
} // if |
} // if |
} // if |
return pURL; |
} // CFFileCreateURL |
#pragma mark - |
#pragma mark Private - Utilities - Writing |
static bool CFFileWrite(CFURLRef pURL, |
CFDataRef pData) |
{ |
bool bSuccess = (pURL != nullptr) && (pData != nullptr); |
if(bSuccess) |
{ |
const CFIndex nLength = CFDataGetLength(pData); |
const UInt8* pBuffer = CFDataGetBytePtr(pData); |
bSuccess = (nLength > 0) && (pBuffer != nullptr); |
if(bSuccess) |
{ |
CFWriteStreamRef pStream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, pURL); |
if(pStream != nullptr) |
{ |
bSuccess = CFWriteStreamOpen(pStream); |
if(bSuccess) |
{ |
CFIndex nSize = CFWriteStreamWrite(pStream, pBuffer, nLength); |
bSuccess = nLength == nSize; |
CFWriteStreamClose(pStream); |
} // if |
CFRelease(pStream); |
} // if |
} // if |
} // if |
return bSuccess; |
} // CFFileWrite |
#pragma mark - |
#pragma mark Private - Utilities - Strings |
static bool CFFileStringHasPropertyListExt(CFStringRef pPathname) |
{ |
CFRange foundRange; |
CFRange searchRange = CFRangeMake(0, CFStringGetLength(pPathname)); |
CFStringRef searchStr = CFSTR("plist"); |
CFStringCompareFlags searchOptions = kCFCompareCaseInsensitive; |
return CFStringFindWithOptions(pPathname, searchStr, searchRange, searchOptions, &foundRange); |
} // CFFileStringHasPropertyListExt |
static bool CFFileStringIsPropertyListExt(CFStringRef pExt) |
{ |
CFRange searchRange = CFRangeMake(0, CFStringGetLength(pExt)); |
CFStringRef searchStr = CFSTR("plist"); |
CFStringCompareFlags searchOptions = kCFCompareCaseInsensitive; |
CFComparisonResult result = CFStringCompareWithOptions(pExt, searchStr, searchRange, searchOptions); |
return result == kCFCompareEqualTo; |
} // CFFileStringIsPropertyListExt |
static bool CFFileStringHasPropertyListExt(CFStringRef pName, CFStringRef pExt) |
{ |
return (pExt != nullptr) ? CFFileStringIsPropertyListExt(pExt) : CFFileStringHasPropertyListExt(pName); |
} // CFFileStringHasPropertyListExt |
#pragma mark - |
#pragma mark Private - Methods |
// Initialize all instance variables |
void File::initialize() |
{ |
mnFormat = kCFPropertyListXMLFormat_v1_0; |
mnOptions = kCFPropertyListMutableContainers; |
mnDirectory = CFSearchPathDirectory(0); |
mnDomain = NSAllDomainsMask; |
mnLength = 0; |
mpPList = nullptr; |
mpError = nullptr; |
mpData = nullptr; |
mpURL = nullptr; |
} // initialize |
// Create and initialize all ivars |
void File::acquire(const bool& isPList) |
{ |
mpData = CFFileCreate(mpURL); |
if(mpData != nullptr) |
{ |
mnLength = CFDataGetLength(mpData); |
if(isPList) |
{ |
CFErrorRef pError = nullptr; |
mpPList = CFPropertyListCreateWithData(kCFAllocatorDefault, |
mpData, |
mnOptions, |
&mnFormat, |
&pError); |
if(pError != nullptr) |
{ |
mpError = CFErrorCopyDescription(pError); |
CFRelease(pError); |
} // if |
} // if |
} // if |
} // acquire |
// Create a deep-copy |
void File::clone(const File& rFile) |
{ |
mnOptions = rFile.mnOptions; |
mnFormat = rFile.mnFormat; |
if(rFile.mpData != nullptr) |
{ |
CFDataRef pData = CFDataCreateCopy(kCFAllocatorDefault, rFile.mpData); |
if(pData != nullptr) |
{ |
if(mpData != nullptr) |
{ |
CFRelease(mpData); |
} // if |
mpData = pData; |
} // if |
} // if |
if(rFile.mpPList != nullptr) |
{ |
CFPropertyListRef pPList = CFPropertyListCreateDeepCopy(kCFAllocatorDefault, rFile.mpPList, mnOptions); |
if(pPList != nullptr) |
{ |
if(mpPList != nullptr) |
{ |
CFRelease(mpPList); |
} // if |
mpPList = pPList; |
} // if |
} // if |
if(rFile.mpError != nullptr) |
{ |
CFStringRef pError = CFStringCreateCopy(kCFAllocatorDefault, rFile.mpError); |
if(pError != nullptr) |
{ |
if(mpError != nullptr) |
{ |
CFRelease(mpError); |
} // if |
mpError = pError; |
} // if |
} // if |
if(rFile.mpURL != nullptr) |
{ |
CFURLRef pURL = CFURLCreateWithString(kCFAllocatorDefault, |
CFURLGetString(rFile.mpURL), |
CFURLGetBaseURL(rFile.mpURL)); |
if(pURL != nullptr) |
{ |
if(mpURL != nullptr) |
{ |
CFRelease(mpURL); |
} // if |
mpURL = pURL; |
} // if |
} // if |
} // clone |
// Create a deep-copy of the property list |
void File::clone(CFPropertyListRef pPListSrc) |
{ |
CFPropertyListRef pPListDst = CFPropertyListCreateDeepCopy(kCFAllocatorDefault, pPListSrc, mnOptions); |
if(pPListDst != nullptr) |
{ |
if(mpPList != nullptr) |
{ |
CFRelease(mpPList); |
} // if |
mpPList = pPListDst; |
CFErrorRef pError = nullptr; |
CFDataRef pData = CFPropertyListCreateData(kCFAllocatorDefault, mpPList, mnFormat, mnOptions, &pError); |
if(pError != nullptr) |
{ |
CFStringRef pDescription = CFErrorCopyDescription(pError); |
if(pDescription != nullptr) |
{ |
if(mpError != nullptr) |
{ |
CFRelease(mpError); |
} // if |
mpError = pDescription; |
} // if |
CFRelease(pError); |
} // if |
if(pData != nullptr) |
{ |
if(mpData != nullptr) |
{ |
CFRelease(mpData); |
} // if |
mpData = pData; |
mnLength = CFDataGetLength(mpData); |
} // else |
} // if |
} // clone |
// Write the file to a location using url |
bool File::write(CFURLRef pURL) |
{ |
bool bSuccess = false; |
if(mpURL != nullptr) |
{ |
CFRelease(mpURL); |
} // if |
mpURL = pURL; |
bSuccess = CFFileWrite(mpURL, mpData); |
return bSuccess; |
} // write |
#pragma mark - |
#pragma mark Public - Constructors |
// Constructor for reading a file with an absolute pathname |
File::File(CFStringRef pPathname) |
{ |
initialize(); |
mpURL = CFFileCreateURL(pPathname); |
if(mpURL != nullptr) |
{ |
bool isPList = CFFileStringHasPropertyListExt(pPathname); |
acquire(isPList); |
} // if |
} // Constructor |
// Constructor for reading a file in an application's bundle |
File::File(CFStringRef pFileName, |
CFStringRef pFileExt) |
{ |
initialize(); |
mpURL = CFFileCreateURL(pFileName, pFileExt); |
if(mpURL != nullptr) |
{ |
bool isPList = CFFileStringHasPropertyListExt(pFileName, pFileExt); |
acquire(isPList); |
} // if |
} // Constructor |
// Constructor for reading a file in a domain |
File::File(const CFSearchPathDomainMask& domain, |
const CFSearchPathDirectory& directory, |
CFStringRef pDirName, |
CFStringRef pFileName, |
CFStringRef pFileExt) |
{ |
initialize(); |
mpURL = CFFileCreateURL(domain, directory, pDirName, pFileName, pFileExt); |
if(mpURL != nullptr) |
{ |
mnDirectory = directory; |
mnDomain = domain; |
bool isPList = CFFileStringHasPropertyListExt(pFileName, pFileExt); |
acquire(isPList); |
} // if |
} // Constructor |
// Constructor for reading a file using a URL |
File::File(CFURLRef pURL) |
{ |
initialize(); |
if(pURL != nullptr) |
{ |
mpURL = CFURLCreateWithString(kCFAllocatorDefault, |
CFURLGetString(pURL), |
CFURLGetBaseURL(pURL)); |
if(mpURL != nullptr) |
{ |
bool isPList = CFFileStringHasPropertyListExt(CFURLGetString(mpURL)); |
acquire(isPList); |
} // if |
} // if |
} // Constructor |
#pragma mark - |
#pragma mark Public - Destructor |
// Delete the object |
File::~File() |
{ |
if(mpData != nullptr) |
{ |
CFRelease(mpData); |
mpData = nullptr; |
} // if |
if(mpPList != nullptr) |
{ |
CFRelease(mpPList); |
mpPList = nullptr; |
} // if |
if(mpError != nullptr) |
{ |
CFRelease(mpError); |
mpError = nullptr; |
} // if |
if(mpURL != nullptr) |
{ |
CFRelease(mpURL); |
mpURL = nullptr; |
} // if |
} // Destructor |
#pragma mark - |
#pragma mark Public - Copy Constructor |
// Copy constructor for deep-copy |
File::File(const File& rFile) |
{ |
clone(rFile); |
} // Copy Constructor |
#pragma mark - |
#pragma mark Public - Assignment Operators |
// Assignment operator for deep object copy |
File& File::operator=(const File& rFile) |
{ |
if(this != &rFile) |
{ |
clone(rFile); |
} // if |
return *this; |
} // Operator = |
// Assignment operator for propert list deep-copy |
File& File::operator=(CFPropertyListRef pPListSrc) |
{ |
if(pPListSrc != nullptr) |
{ |
clone(pPListSrc); |
} // if |
return *this; |
} // Operator = |
#pragma mark - |
#pragma mark Public - Accessors |
// Accessor to return a c-string representation of the read file |
const char* File::cstring() const |
{ |
return (mpData != nullptr) ? reinterpret_cast<const char*>(CFDataGetBytePtr(mpData)) : nullptr; |
} // cstring |
// Accessor, if the read file was a data file |
const uint8_t* File::bytes() const |
{ |
return (mpData != nullptr) ? CFDataGetBytePtr(mpData) : nullptr; |
} // bytes |
// Length of the data or the string |
const CFIndex File::length() const |
{ |
return mnLength; |
} // length |
// Options used for reading the property list |
const CFOptionFlags File::options() const |
{ |
return mnOptions; |
} // options |
// Options used for reading the property list |
const CFPropertyListFormat File::format() const |
{ |
return mnFormat; |
} // format |
// Domain mask for searching for a file |
const CFSearchPathDomainMask File::domain() const |
{ |
return mnDomain; |
} // domain |
// Directory enumerated type for seaching for a file |
const CFSearchPathDirectory File::directory() const |
{ |
return mnDirectory; |
} // directory |
// File's representation as data |
CFDataRef File::data() const |
{ |
return mpData; |
} // data |
// Property list |
CFPropertyListRef File::plist() const |
{ |
return mpPList; |
} // plist |
// Error associated with creating a property list |
CFStringRef File::error() const |
{ |
return mpError; |
} // error |
// File's url |
CFURLRef File::url() const |
{ |
return mpURL; |
} // url |
#pragma mark - |
#pragma mark Public - Strings |
// Create a text string from the contents of a file |
std::string File::string() |
{ |
std::string string; |
const UInt8 *pBytes = CFDataGetBytePtr(mpData); |
if(pBytes != nullptr) |
{ |
string = reinterpret_cast<const char*>(pBytes); |
} // if |
return string; |
} // string |
// Create a cf string from the contents of a file |
CFStringRef File::cfstring() |
{ |
CFStringRef string = nullptr; |
const UInt8 *pBytes = CFDataGetBytePtr(mpData); |
if(pBytes != nullptr) |
{ |
CFIndex numBytes = CFDataGetLength(mpData); |
string = CFStringCreateWithBytes(kCFAllocatorDefault, pBytes, numBytes, kCFStringEncodingUTF8, true); |
} // if |
return string; |
} // cfstring |
#pragma mark - |
#pragma mark Public - Query |
// Query for if the file was a property list |
const bool File::isPList() const |
{ |
return (mpPList != nullptr) ? bool(CFPropertyListIsValid(mpPList, mnFormat)) : false; |
} // isPList |
#pragma mark - |
#pragma mark Public - Write |
// Write to the original location |
bool File::write() |
{ |
return CFFileWrite(mpURL, mpData); |
} // write |
// Write the file to a location using an absolute pathname |
bool File::write(CFStringRef pPathname) |
{ |
CFURLRef pURL = CFFileCreateURL(pPathname); |
bool bSuccess = pURL != nullptr; |
if(bSuccess) |
{ |
bSuccess = write(pURL); |
} // if |
return bSuccess; |
} // write |
// Write the file to the application's bundle |
bool File::write(CFStringRef pName, CFStringRef pExt) |
{ |
CFURLRef pURL = CFFileCreateURL(pName, pExt); |
bool bSuccess = pURL != nullptr; |
if(bSuccess) |
{ |
bSuccess = write(pURL); |
} // if |
return bSuccess; |
} // write |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-12-10