CFLite/CFTest/SuperString.cpp: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 8: | Line 8: | ||
* | * | ||
*/ | */ | ||
//#include "stdafx.h" | |||
#include "SuperString.h" | |||
void CCFLog::operator()(CFTypeRef valRef) { | |||
#if 1 | |||
SuperString valStr; valStr.Set_CFType(valRef); | |||
FILE *log_fileP = stdout; | |||
#if defined(__WIN32__) | |||
#ifndef __MWERKS__ // NOT using Metrowerks? | |||
// GUI APP | |||
static FILE *s_logP = NULL; | |||
if (s_logP == NULL) { | |||
#if defined(__MWERKS__) // using Metrowerks? | |||
s_logP = fopen("log.txt", "a"); | |||
#else | |||
(void)fopen_s(&s_logP, "log.txt", "a"); | |||
#endif | |||
} | |||
log_fileP = s_logP; | |||
#endif | |||
#endif | |||
# | fprintf(log_fileP, "%s%s", valStr.consoleZ(), i_crB ? "\n" : ""); | ||
fflush(log_fileP); | |||
#else | |||
fflush(stdout); | |||
CFShow(valRef); | |||
if (i_crB) { | |||
printf("\n"); | |||
} | |||
fflush(stdout); | |||
#endif | |||
} | |||
char* strrstr(const char* stringZ, const char* findZ) | char* strrstr(const char* stringZ, const char* findZ) | ||
{ | { | ||
bool firstB = true, doneB = false; | bool firstB = true, doneB = false; | ||
char *nextZ; | const char *nextZ; | ||
do { | do { | ||
| Line 204: | Line 238: | ||
} | } | ||
} | } | ||
#ifndef __WIN32__ | |||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 | |||
enum { | |||
kCFCompareDiacriticInsensitive = 128, /* If specified, ignores diacritics (o-umlaut == o) */ | |||
kCFCompareWidthInsensitive = 256, /* If specified, ignores width differences ('a' == UFF41) */ | |||
kCFCompareForcedOrdering = 512 /* If specified, comparisons are forced to return either kCFCompareLessThan or kCFCompareGreaterThan if the strings are equivalent but not strictly equal, for stability when sorting (e.g. "aaa" > "AAA" with kCFCompareCaseInsensitive specified) */ | |||
}; | |||
ushort GetSystemVers(void); | |||
#else | |||
ushort GetSystemVers(void) { | |||
return 0x1050; // fake it to be OS 10.5 | |||
} | |||
#endif | |||
#endif | |||
bool g_pref_diacritic_insensitive_searchB = true; | bool g_pref_diacritic_insensitive_searchB = true; | ||
static CFOptionFlags GetFlags_NormalizeStrings( | static CFOptionFlags GetFlags_NormalizeStrings( | ||
SuperString& str1, | SuperString& str1, | ||
| Line 229: | Line 281: | ||
== kCFCompareEqualTo; | == kCFCompareEqualTo; | ||
#else | #else | ||
s_has_diacritic_insensitive_compareB = | s_has_diacritic_insensitive_compareB = GetSystemVers() >= 0x1050; | ||
#endif | #endif | ||
| Line 266: | Line 318: | ||
CFComparisonResult compareResult = kCFCompareEqualTo; | CFComparisonResult compareResult = kCFCompareEqualTo; | ||
if (ref1 == NULL || ref2 == NULL) { | if ((ref1 == NULL) || (ref2 == NULL)) { | ||
if (ref1 == NULL ^ ref2 == NULL) { | if ((ref1 == NULL) ^ (ref2 == NULL)) { | ||
if (ref1) { | if (ref1) { | ||
compareResult = kCFCompareLessThan; | compareResult = kCFCompareLessThan; | ||
| Line 324: | Line 376: | ||
Set(uc(&buf[0])); | Set(uc(&buf[0])); | ||
return *this; | return *this; | ||
} | |||
SuperString & SuperString::pop_back(UInt32 numCharsL) | |||
{ | |||
ustring ustr(utf8()); | |||
if (!ustr.empty()) { | |||
ustr.resize(ustr.size() - numCharsL); | |||
Set(ustr.c_str()); | |||
} | |||
return *this; | |||
} | |||
#ifdef __WIN32__ | |||
#if defined(__MWERKS__) | |||
class CIsZero { | |||
public: bool operator()(const wchar_t& ch) { | |||
return ch == 0; | |||
} | |||
}; | |||
static size_t wcslen(const wchar_t *wcharZ) | |||
{ | |||
const wchar_t* it(std::find_if(&wcharZ[0], &wcharZ[512], CIsZero())); | |||
return std::distance(&wcharZ[0], it); | |||
} | |||
#endif | |||
SuperString::SuperString(const wchar_t *wcharZ) | |||
{ | |||
UTF16Vec vec((UTF16Char *)&wcharZ[0], (UTF16Char *)&wcharZ[wcslen(wcharZ)]); | |||
SetNULL(); | |||
Set(vec); | |||
} | |||
#endif | |||
void SuperString::Set_p(ConstStr255Param strZ) | |||
{ | |||
CharVec charVec; | |||
charVec.assign(&strZ[1], &strZ[strZ[0] + 1]); | |||
charVec.push_back(0); | |||
Set(&charVec[0]); | |||
} | } | ||
| Line 345: | Line 444: | ||
int AssertAlert(const char *msgZ, const char *fileZ, long lineL, bool noThrowB) | int AssertAlert(const char *msgZ, const char *fileZ, long lineL, bool noThrowB) | ||
{ | { | ||
SuperString formatStr("$$$ Assert Fail: %s, in file: '%s' at line %ld"); | SuperString formatStr("$$$ Assert Fail: %s, in file: '%s' at line %ld\n"); | ||
formatStr.ssprintf(NULL, msgZ, fileZ, lineL); | formatStr.ssprintf(NULL, msgZ, fileZ, lineL); | ||
CCFLog()(formatStr.ref()); | |||
return 1; | return 1; | ||
} | } | ||
| Line 375: | Line 474: | ||
// Log("created plist from xml"); | // Log("created plist from xml"); | ||
} else { | } else { | ||
CCFLog()("FAILED converting xml to plist\n"); | |||
} | } | ||
} else { | } else { | ||
CCFLog()("FAILED creating xml from file\n"); | |||
} | } | ||
| Line 417: | Line 516: | ||
str.append(": "); | str.append(": "); | ||
str.append((long)err); | str.append((long)err); | ||
CCFLog(crB)(str.ref()); | |||
} | } | ||
} | } | ||
</pre> | </pre> | ||
Revision as of 00:35, 18 July 2008
/*
* SuperString.cpp
* CFTest
*
* Created by David M. Cotter on 6/25/08.
* Copyright 2008 __MyCompanyName__. All rights reserved.
*
*/
//#include "stdafx.h"
#include "SuperString.h"
void CCFLog::operator()(CFTypeRef valRef) {
#if 1
SuperString valStr; valStr.Set_CFType(valRef);
FILE *log_fileP = stdout;
#if defined(__WIN32__)
#ifndef __MWERKS__ // NOT using Metrowerks?
// GUI APP
static FILE *s_logP = NULL;
if (s_logP == NULL) {
#if defined(__MWERKS__) // using Metrowerks?
s_logP = fopen("log.txt", "a");
#else
(void)fopen_s(&s_logP, "log.txt", "a");
#endif
}
log_fileP = s_logP;
#endif
#endif
fprintf(log_fileP, "%s%s", valStr.consoleZ(), i_crB ? "\n" : "");
fflush(log_fileP);
#else
fflush(stdout);
CFShow(valRef);
if (i_crB) {
printf("\n");
}
fflush(stdout);
#endif
}
char* strrstr(const char* stringZ, const char* findZ)
{
bool firstB = true, doneB = false;
const char *nextZ;
do {
if (firstB) {
nextZ = strstr(stringZ, findZ);
} else {
nextZ = strstr(&stringZ[1], findZ);
}
doneB = nextZ == NULL;
if (!doneB) {
stringZ = nextZ;
} else if (firstB) {
stringZ = NULL;
}
firstB = false;
} while (!doneB);
return const_cast<char *>(stringZ);
}
static const char * CopyLongToC(long valL)
{
static char s_bufAC[256];
sprintf(s_bufAC, "%d", valL);
return s_bufAC;
}
float CStringToFloat(const char *numF)
{
float valF = 0;
sscanf(numF, "%f", &valF);
return valF;
}
class Asciify {
public: void operator()(char &ch) {
if (ch < 32 || ch > 126) ch = '?';
}
};
/********************************************************/
bool CFStringIsEmpty(CFStringRef nameRef)
{
return nameRef == NULL || CFStringEqual(nameRef, CFSTR(""));
}
static CFStringEncoding ValidateEncoding(CFStringEncoding encoding = kCFStringEncodingInvalidId)
{
if (encoding == kCFStringEncodingInvalidId) {
encoding = kSourceFileEncoding;
}
return encoding;
}
CFStringRef CFStringCreateWithC(
const char * bufZ,
CFStringEncoding encoding)
{
if (bufZ) {
encoding = ValidateEncoding(encoding);
CFStringRef cf = NULL;
cf = CFStringCreateWithCString(kCFAllocatorDefault, bufZ, encoding);
if (!cf) cf = CFStringCreateWithCString(kCFAllocatorDefault, bufZ, kCFStringEncodingWindowsLatin1);
if (!cf) cf = CFStringCreateWithCString(kCFAllocatorDefault, bufZ, kCFStringEncodingISOLatin1);
if (!cf) cf = CFStringCreateWithCString(kCFAllocatorDefault, bufZ, kCFStringEncodingMacRoman);
CF_ASSERT(cf);
if (!cf) return NULL;
return (CFStringRef)CFRetainDebug(cf, false);
} else {
return (CFStringRef)CFRetainDebug(CFSTR(""));
}
}
CFStringRef CFStringCreateWithCu(
const UTF8Char * bufZ,
CFStringEncoding encoding)
{
return CFStringCreateWithC((const char *)bufZ, encoding);
}
static inline CFRange CFStrGetRange(CFStringRef ref)
{
return CFRangeMake(0, CFStringGetLength(ref));
}
ustring &CopyCFStringToUString(CFStringRef str, ustring &result, CFStringEncoding encoding, bool externalB)
{
result.clear();
if (str) {
#define kBufSize 256
UTF8Char utf8Buf[kBufSize];
CFRange cfRange = CFStrGetRange(str);
CFIndex resultSize;
CFIndex numChars;
encoding = ValidateEncoding(encoding);
while (cfRange.length > 0) {
numChars = CFStringGetBytes(
str, cfRange, encoding, '?', externalB,
&utf8Buf[0], kBufSize, &resultSize);
if (numChars == 0) break; // Failed to convert anything...
result.append(&utf8Buf[0], &utf8Buf[resultSize]);
cfRange.location += numChars;
cfRange.length -= numChars;
}
}
return result;
}
std::string &CopyCFStringToStd(
CFStringRef str,
std::string &stdstr,
CFStringEncoding encoding)
{
stdstr.clear();
encoding = ValidateEncoding(encoding);
if (str) {
const char *charZ = CFStringGetCStringPtr(str, encoding);
if (charZ) {
stdstr = charZ;
} else {
ustring ustr;
CopyCFStringToUString(str, ustr, encoding);
stdstr.append(ustr.begin(), ustr.end());
}
}
return stdstr;
}
// you should provide this function. stubbed out here because my CF doesn't have it
#define CFStringTransform(a, b, c, d) true
SuperString& SuperString::Normalize()
{
ScCFReleaser<CFMutableStringRef> str1;
str1.Set(CFStringCreateMutableCopy(kCFAllocatorDefault, 0, ref()));
CFStringNormalize(str1, kCFStringNormalizationFormD);
CFRange range = CFStrGetRange(str1);
if (CFStringTransform(str1, &range, kCFStringTransformStripCombiningMarks, false)) {
Set(str1);
}
// void CFStringFold(CFMutableStringRef theString, CFOptionFlags theFlags, CFLocaleRef theLocale) AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
return *this;
}
void CFStrReplaceWith(CFMutableStringRef stringRef, CFStringRef replaceStr, CFStringRef withStr)
{
ScCFReleaser<CFArrayRef> arrayRef;
arrayRef.Set(CFStringCreateArrayWithFindResults(
NULL, stringRef, replaceStr, CFStrGetRange(stringRef), kCFCompareCaseInsensitive));
if (arrayRef.Get()) {
CFRange *rangeRef;
loop_reverse (CFArrayGetCount(arrayRef)) {
rangeRef = (CFRange *)CFArrayGetValueAtIndex(arrayRef, _indexS);
CFStringReplace(stringRef, *rangeRef, withStr);
}
}
}
#ifndef __WIN32__
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
enum {
kCFCompareDiacriticInsensitive = 128, /* If specified, ignores diacritics (o-umlaut == o) */
kCFCompareWidthInsensitive = 256, /* If specified, ignores width differences ('a' == UFF41) */
kCFCompareForcedOrdering = 512 /* If specified, comparisons are forced to return either kCFCompareLessThan or kCFCompareGreaterThan if the strings are equivalent but not strictly equal, for stability when sorting (e.g. "aaa" > "AAA" with kCFCompareCaseInsensitive specified) */
};
ushort GetSystemVers(void);
#else
ushort GetSystemVers(void) {
return 0x1050; // fake it to be OS 10.5
}
#endif
#endif
bool g_pref_diacritic_insensitive_searchB = true;
static CFOptionFlags GetFlags_NormalizeStrings(
SuperString& str1,
SuperString& str2,
CFOptionFlags optionFlags = 0
| kCFCompareNonliteral
| kCFCompareLocalized)
{
if (g_pref_diacritic_insensitive_searchB) {
static bool s_diacritic_compare_inittedB = false;
static bool s_has_diacritic_insensitive_compareB;
if (!s_diacritic_compare_inittedB) {
#if defined(__WIN32__)
SuperString str_e("e");
UInt32 e_grave(CFSwapInt32HostToBig(0xC3A90000));
SuperString str_e_grave((UInt8*)&e_grave);
s_has_diacritic_insensitive_compareB = ::CFStringCompare(
str_e.ref(), str_e_grave.ref(), (CFOptionFlags)kCFCompareDiacriticInsensitive)
== kCFCompareEqualTo;
#else
s_has_diacritic_insensitive_compareB = GetSystemVers() >= 0x1050;
#endif
s_diacritic_compare_inittedB = true;
}
if (s_has_diacritic_insensitive_compareB) {
optionFlags |= (CFOptionFlags)(0
| kCFCompareDiacriticInsensitive
| kCFCompareWidthInsensitive);
} else {
str1.Normalize();
str2.Normalize();
}
}
return optionFlags;
}
bool CFStringContains(CFStringRef inRef, CFStringRef findRef, bool case_sensitiveB)
{
if (inRef == NULL || findRef == NULL) {
return false;
}
SuperString str1(inRef), str2(findRef);
CFOptionFlags optionFlags = case_sensitiveB ? kCFCompareCaseInsensitive : 0;
optionFlags = GetFlags_NormalizeStrings(str1, str2, optionFlags);
return !!CFStringFindWithOptions(str1.ref(), str2.ref(), CFStrGetRange(str1.ref()), optionFlags, NULL);
}
CFComparisonResult CFStringCompare(CFStringRef ref1, CFStringRef ref2, bool case_sensitiveB)
{
CFComparisonResult compareResult = kCFCompareEqualTo;
if ((ref1 == NULL) || (ref2 == NULL)) {
if ((ref1 == NULL) ^ (ref2 == NULL)) {
if (ref1) {
compareResult = kCFCompareLessThan;
} else {
compareResult = kCFCompareGreaterThan;
}
}
} else {
SuperString str1(ref1), str2(ref2);
CFOptionFlags optionFlags = case_sensitiveB ? 0 : kCFCompareCaseInsensitive;
optionFlags = GetFlags_NormalizeStrings(str1, str2, optionFlags);
compareResult = ::CFStringCompare(str1.ref(), str2.ref(), optionFlags);
}
return compareResult;
}
bool CFStringEqual(CFStringRef str1, CFStringRef str2, bool case_sensitiveB)
{
return CFStringCompare(str1, str2, case_sensitiveB) == kCFCompareEqualTo;
}
bool CFStringLess(CFStringRef lhs, CFStringRef rhs, bool case_sensitiveB)
{
bool lessB = CFStringCompare(lhs, rhs, case_sensitiveB) == kCFCompareLessThan;
return lessB;
}
SuperString operator+(const SuperString &lhs, SuperString rhs)
{
SuperString str(lhs);
str.append(rhs);
return str;
}
static void mt_vsnprintf(char *destZ, size_t sizeL, const char *formatZ, va_list &args)
{
vsnprintf(destZ, sizeL - 1, formatZ, args);
destZ[sizeL - 1] = 0;
}
SuperString& SuperString::ssprintf(const char *formatZ0, ...)
{
CharVec buf(2048);
va_list args;
CF_ASSERT(utf8().size() < 1024);
va_start(args, formatZ0);
mt_vsnprintf(&buf[0], buf.size(), formatZ0 ? formatZ0 : utf8Z(), args);
va_end(args);
Set(uc(&buf[0]));
return *this;
}
SuperString & SuperString::pop_back(UInt32 numCharsL)
{
ustring ustr(utf8());
if (!ustr.empty()) {
ustr.resize(ustr.size() - numCharsL);
Set(ustr.c_str());
}
return *this;
}
#ifdef __WIN32__
#if defined(__MWERKS__)
class CIsZero {
public: bool operator()(const wchar_t& ch) {
return ch == 0;
}
};
static size_t wcslen(const wchar_t *wcharZ)
{
const wchar_t* it(std::find_if(&wcharZ[0], &wcharZ[512], CIsZero()));
return std::distance(&wcharZ[0], it);
}
#endif
SuperString::SuperString(const wchar_t *wcharZ)
{
UTF16Vec vec((UTF16Char *)&wcharZ[0], (UTF16Char *)&wcharZ[wcslen(wcharZ)]);
SetNULL();
Set(vec);
}
#endif
void SuperString::Set_p(ConstStr255Param strZ)
{
CharVec charVec;
charVec.assign(&strZ[1], &strZ[strZ[0] + 1]);
charVec.push_back(0);
Set(&charVec[0]);
}
void SuperString::Set_CFType(CFTypeRef cfType)
{
CFTypeID cfTypeID(CFGetTypeID(cfType));
if (cfTypeID == CFStringGetTypeID()) {
Set((CFStringRef)cfType);
} else {
ScCFReleaser<CFStringRef> descIDRef(CFCopyTypeIDDescription(cfTypeID));
ScCFReleaser<CFStringRef> descRef(CFCopyDescription(cfType));
SuperString descIDStr(descIDRef.Get()), descStr(descRef.Get());
SuperString logStr("Type: " kLeftQuote "%s" kRightQuote ", Value: " kLeftQuote "%s" kRightQuote);
logStr.ssprintf(NULL, descIDStr.utf8Z(), descStr.utf8Z());
Set(logStr);
}
}
int AssertAlert(const char *msgZ, const char *fileZ, long lineL, bool noThrowB)
{
SuperString formatStr("$$$ Assert Fail: %s, in file: '%s' at line %ld\n");
formatStr.ssprintf(NULL, msgZ, fileZ, lineL);
CCFLog()(formatStr.ref());
return 1;
}
bool Read_PList(const CFURLRef &url, CFDictionaryRef *plistP)
{
bool successB = false;
ScCFReleaser<CFDataRef> xmlData;
*plistP = NULL;
if (CFURLCreateDataAndPropertiesFromResource(
kCFAllocatorDefault, url, xmlData.AddressOf(), NULL, NULL, NULL)
) {
//Log("created xml from file");
*plistP = (CFDictionaryRef)CFPropertyListCreateFromXMLData(
kCFAllocatorDefault,
xmlData,
kCFPropertyListImmutable,
NULL);
successB = *plistP != NULL;
if (successB) {
// Log("created plist from xml");
} else {
CCFLog()("FAILED converting xml to plist\n");
}
} else {
CCFLog()("FAILED creating xml from file\n");
}
return successB;
}
#define noErr 0
OSStatus Write_PList(
CFPropertyListRef plist,
CFURLRef urlRef)
{
OSStatus err = noErr;
ScCFReleaser<CFDataRef> xmlData;
// Convert the property list into XML data.
xmlData.Set(CFPropertyListCreateXMLData(kCFAllocatorDefault, plist));
ETRL(xmlData.Get() == NULL, "creating xml data");
if (!err) {
(void)CFURLWriteDataAndPropertiesToResource (
urlRef, // URL to use
xmlData, // data to write
NULL,
&err);
}
ETRL(err, "writing xml");
return err;
}
void LogErr(const char *utf8Z, OSStatus err, bool crB, bool unixB)
{
if (err) { // && gApp->Logging()) {
SuperString str(uc(utf8Z));
str.append(": ");
str.append((long)err);
CCFLog(crB)(str.ref());
}
}