CFLite/CFTest/SuperString.cpp: Difference between revisions

From kJams Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
 
(One intermediate revision by the same user not shown)
Line 5: Line 5:
  *
  *
  *  Created by David M. Cotter on 6/25/08.
  *  Created by David M. Cotter on 6/25/08.
  *  Copyright 2008 __MyCompanyName__. All rights reserved.
  *  Copyright 2008 David M. Cotter. All rights reserved.
  *
  *
  */
  */
#include "stdafx.h"


#include "SuperString.h"
#ifndef KJAMS
#include "SuperString.h"
#else
#include "CApp.h"
#include "CPreferences.h"
#include "StringUtils.h"
#include "MessageAlert.h"
#endif
 
 
void CCFLog::operator()(CFTypeRef valRef) {
#if 1
SuperString valStr; valStr.Set_CFType(valRef);
FILE *log_fileP = stdout;
 
if (i_crB) {
valStr.append("\n");
}
 
#if defined(__WIN32__)
 
#ifdef __MWERKS__
// console app
static HANDLE consoleH = NULL;
if (!consoleH) {
consoleH = GetStdHandle(STD_OUTPUT_HANDLE);
}
unsigned long outL;
WriteConsoleW(consoleH, valStr.w_str(), valStr.uni().i_lengthL, &outL, NULL);
log_fileP = NULL;
#else
// GUI APP
static FILE *s_logP = NULL;
 
if (s_logP == NULL) {
(void)fopen_s(&s_logP, "log.txt", "a");
}
log_fileP = s_logP;
#endif
#endif
 
if (log_fileP) {
#ifdef KJAMS
Log(valStr.utf8Z(), false);
#else
fprintf(log_fileP, "%s", valStr.utf8Z());
fflush(log_fileP);
#endif
}
#else
fflush(stdout);
CFShow(valRef);
if (i_crB) {
printf("\n");
}
fflush(stdout);
#endif
}
 
void CCFLog::operator()(CFStringRef keyRef, CFTypeRef valRef) {
SuperString keyStr(keyRef);
keyStr.append(": ");
{
bool wasB = i_crB;
i_crB = false;
operator()(keyStr.ref());
i_crB = wasB;
}
 
operator()(valRef);
}
 
#ifndef KJAMS
void LogErr(const char *utf8Z, OSStatus err, bool crB, bool unixB)
{
if (err) { // && gApp->Logging()) {
SuperString keyStr(uc(utf8Z));
SuperString valStr((long)err);
CCFLog logger(crB);
logger(keyStr.ref(), valStr.ref());
}
}
#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 37: Line 130:
}
}


static const char * CopyLongToC(long valL)
const char * CopyLongToC(long valL)
{
{
static char s_bufAC[256];
static char s_bufAC[256];
Line 54: Line 147:


class Asciify {
class Asciify {
public: void operator()(char &ch) {
public: void operator()(char &ch) {
if (ch < 32 || ch > 126) ch = '?';
if (ch < 32 || ch > 126) ch = '?';
}
}
};
};


Line 63: Line 156:
{
{
return nameRef == NULL || CFStringEqual(nameRef, CFSTR(""));
return nameRef == NULL || CFStringEqual(nameRef, CFSTR(""));
}
CFStringEncoding s_file_encoding = kCFStringEncodingInvalidId;
void SetDefaultEncoding(CFStringEncoding encoding)
{
s_file_encoding = encoding;
}
}


Line 68: Line 167:
{
{
if (encoding == kCFStringEncodingInvalidId) {
if (encoding == kCFStringEncodingInvalidId) {
encoding = kSourceFileEncoding;
encoding = s_file_encoding;
CF_ASSERT(encoding != kCFStringEncodingInvalidId);
}
}
Line 75: Line 176:


CFStringRef CFStringCreateWithC(
CFStringRef CFStringCreateWithC(
const char * bufZ,  
const char * bufZ,  
CFStringEncoding encoding)
CFStringEncoding encoding)
{
{
if (bufZ) {
if (bufZ) {
Line 98: Line 199:


CFStringRef CFStringCreateWithCu(
CFStringRef CFStringCreateWithCu(
const UTF8Char * bufZ,  
const UTF8Char * bufZ,  
CFStringEncoding encoding)
CFStringEncoding encoding)
{
{
return CFStringCreateWithC((const char *)bufZ, encoding);
return CFStringCreateWithC((const char *)bufZ, encoding);
Line 141: Line 242:


std::string &CopyCFStringToStd(
std::string &CopyCFStringToStd(
  CFStringRef str,  
CFStringRef str,  
  std::string &stdstr,  
std::string &stdstr,  
  CFStringEncoding encoding)
CFStringEncoding encoding)
{
{
stdstr.clear();
stdstr.clear();
Line 163: Line 264:
return stdstr;
return stdstr;
}
char *OSTypeToChar(OSType osType, char *bufZ)
{
osType = CFSwapInt32HostToBig(osType);
*((OSType *)bufZ) = osType;
bufZ[4] = 0;
return bufZ;
}
SuperString OSTypeToString(OSType osType)
{
SuperString str;
if (osType == -1) {
str.Set("-");
} else {
char bufAC[5];
str.Set(OSTypeToChar(osType, bufAC));
}
return str;
}
OSType CharToOSType(const char *bufZ)
{
OSType osType;
short lenL = strlen(bufZ);
osType = *((OSType *)(&bufZ[lenL - 4]));
osType = CFSwapInt32BigToHost(osType);
return osType;
}
}


Line 205: Line 339:
}
}


bool g_pref_diacritic_insensitive_searchB = true;
#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) */
};
#endif
 
#endif
 
#ifdef KJAMS
ushort GetSystemVers(void);
#define diacritic_insensitiveB (gApp && gApp->i_prefs && gApp->i_prefs->i_pref.diacritic_insensitive_searchB)
#else
bool g_pref_diacritic_insensitive_searchB = true;
#define diacritic_insensitiveB g_pref_diacritic_insensitive_searchB
 
#ifdef _ROSE_
unsigned short GetSystemVers(void);
#else
static unsigned short GetSystemVers(void) {
return 0x1050; // fake it to be OS 10.5
}
#endif
#endif


static CFOptionFlags GetFlags_NormalizeStrings(
static CFOptionFlags GetFlags_NormalizeStrings(
Line 214: Line 374:
| kCFCompareLocalized)
| kCFCompareLocalized)
{
{
if (g_pref_diacritic_insensitive_searchB) {
if (diacritic_insensitiveB) {
static bool s_diacritic_compare_inittedB = false;
static bool s_diacritic_compare_inittedB = false;
static bool s_has_diacritic_insensitive_compareB;
static bool s_has_diacritic_insensitive_compareB;
Line 229: Line 389:
== kCFCompareEqualTo;
== kCFCompareEqualTo;
#else
#else
s_has_diacritic_insensitive_compareB = true; // GetSystemVers() >= 0x1050;
s_has_diacritic_insensitive_compareB = GetSystemVers() >= 0x1050;
#endif
#endif
Line 266: Line 426:
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 306: Line 466:
}
}


#ifndef KJAMS
static  void mt_vsnprintf(char *destZ, size_t sizeL, const char *formatZ, va_list &args)
static  void mt_vsnprintf(char *destZ, size_t sizeL, const char *formatZ, va_list &args)
{
{
vsnprintf(destZ, sizeL - 1, formatZ, args);
vsnprintf(destZ, sizeL - 1, formatZ, args);
destZ[sizeL - 1] = 0;
destZ[sizeL - 1] = 0;
}
#endif
bool SuperString::Split(const char *splitZ, SuperString *rhsP0, bool from_endB)
{
bool splitB;
if (from_endB) {
splitB = strrstr(utf8Z(), splitZ) != NULL;
} else {
splitB = strstr(utf8Z(), splitZ) != NULL;
}
if (splitB) {
UCharVec bufAC;
bufAC.assign(utf8().begin(), utf8().end());
bufAC.push_back(0);
UTF8Char *chZ;
if (from_endB) {
chZ = (UTF8Char *)strrstr((char *)&bufAC[0], (char *)splitZ);
} else {
chZ = (UTF8Char *)strstr((char *)&bufAC[0], (char *)splitZ);
}
SuperString temp(chZ + strlen(splitZ));
*chZ = 0;
Set(&bufAC[0]);
if (rhsP0) {
rhsP0->Set(temp);
}
}
return splitB;
}
}


Line 324: Line 522:
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, CFStringEncoding encoding)
{
UCharVec charVec;
charVec.assign(&strZ[1], &strZ[strZ[0] + 1]);
charVec.push_back(0);
Set(&charVec[0], encoding);
}
}


Line 336: Line 581:
ScCFReleaser<CFStringRef> descRef(CFCopyDescription(cfType));
ScCFReleaser<CFStringRef> descRef(CFCopyDescription(cfType));
SuperString descIDStr(descIDRef.Get()), descStr(descRef.Get());
SuperString descIDStr(descIDRef.Get()), descStr(descRef.Get());
SuperString logStr("Type: " kLeftQuote "%s" kRightQuote ", Value: " kLeftQuote "%s" kRightQuote);
SuperString logStr("Type: <%s>, Value: <%s>");
logStr.ssprintf(NULL, descIDStr.utf8Z(), descStr.utf8Z());
logStr.ssprintf(NULL, descIDStr.utf8Z(), descStr.utf8Z());
Line 343: Line 588:
}
}


#ifndef KJAMS
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);
CFLog()(formatStr.ref());
CCFLog()(formatStr.ref());
return 1;
return 1;
}
}
#endif


bool Read_PList(const CFURLRef &url, CFDictionaryRef *plistP)
bool Read_PList(const CFURLRef &url, CFDictionaryRef *plistP)
Line 375: Line 622:
// Log("created plist from xml");
// Log("created plist from xml");
} else {
} else {
printf("FAILED converting xml to plist");
CCFLog()("FAILED converting xml to plist\n");
}
}
} else {
} else {
printf("FAILED creating xml from file");
CCFLog()("FAILED creating xml from file\n");
}
}
return successB;
return successB;
}
}
#define noErr 0


OSStatus Write_PList(
OSStatus Write_PList(
Line 408: Line 653:
return err;
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);
if (crB) {
str.append("\n");
}
printf(str.consoleZ());
}
}
}
</pre>
</pre>

Latest revision as of 22:30, 22 July 2008

/*
 *  SuperString.cpp
 *  CFTest
 *
 *  Created by David M. Cotter on 6/25/08.
 *  Copyright 2008 David M. Cotter. All rights reserved.
 *
 */
#include "stdafx.h"

#ifndef KJAMS
	#include "SuperString.h"
#else
	#include "CApp.h"
	#include "CPreferences.h"
	#include "StringUtils.h"
	#include "MessageAlert.h"
#endif


void CCFLog::operator()(CFTypeRef valRef) {
	#if 1
		SuperString			valStr;	valStr.Set_CFType(valRef);
		FILE				*log_fileP = stdout;

		if (i_crB) {
			valStr.append("\n");
		}

		#if defined(__WIN32__)

			#ifdef __MWERKS__
				//	console app
				static	HANDLE	consoleH = NULL;
				
				if (!consoleH) {
					consoleH = GetStdHandle(STD_OUTPUT_HANDLE);
				}
				
				unsigned long	outL;
				
				WriteConsoleW(consoleH, valStr.w_str(), valStr.uni().i_lengthL, &outL, NULL);
				
				log_fileP = NULL;
			#else
				//	GUI APP
				static	FILE	*s_logP = NULL;

				if (s_logP == NULL) {
					(void)fopen_s(&s_logP, "log.txt", "a");
				}
				
				log_fileP = s_logP;
			#endif
		#endif

		if (log_fileP) {
			
			#ifdef KJAMS
				Log(valStr.utf8Z(), false);
			#else
				fprintf(log_fileP, "%s", valStr.utf8Z());
				fflush(log_fileP);
			#endif
		}
	#else
		fflush(stdout);
		CFShow(valRef);
		if (i_crB) {
			printf("\n");
		}
		fflush(stdout);
	#endif
}

void CCFLog::operator()(CFStringRef keyRef, CFTypeRef valRef) {
	SuperString		keyStr(keyRef);
	
	keyStr.append(": ");
	
	{
		bool	wasB = i_crB;
		i_crB = false;
		
		operator()(keyStr.ref());
		i_crB = wasB;
	}

	operator()(valRef);
}

#ifndef KJAMS
void		LogErr(const char *utf8Z, OSStatus err, bool crB, bool unixB)
{
	if (err) {	//	&& gApp->Logging()) {
		SuperString		keyStr(uc(utf8Z));
		SuperString		valStr((long)err);
		CCFLog			logger(crB);
		
		logger(keyStr.ref(), valStr.ref());
	}
}
#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);
}

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(""));
}

CFStringEncoding	s_file_encoding = kCFStringEncodingInvalidId;
void				SetDefaultEncoding(CFStringEncoding encoding)
{
	s_file_encoding = encoding;
}

static CFStringEncoding	ValidateEncoding(CFStringEncoding encoding = kCFStringEncodingInvalidId)
{
	if (encoding == kCFStringEncodingInvalidId) {
		encoding = s_file_encoding;
		
		CF_ASSERT(encoding != kCFStringEncodingInvalidId);
	}
	
	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;
}

char		*OSTypeToChar(OSType osType, char *bufZ)
{
	osType = CFSwapInt32HostToBig(osType);
	*((OSType *)bufZ) = osType;
	bufZ[4] = 0;
	return bufZ;
}

SuperString		OSTypeToString(OSType osType)
{
	SuperString		str;
	
	if (osType == -1) {
		str.Set("-");
	} else {
		char	bufAC[5];
		
		str.Set(OSTypeToChar(osType, bufAC));
	}
	
	return str;
}

OSType		CharToOSType(const char *bufZ)
{
	OSType		osType;
	short		lenL = strlen(bufZ);
	
	osType = *((OSType *)(&bufZ[lenL - 4]));
	osType = CFSwapInt32BigToHost(osType);
	return osType;
}

//	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) */
		};
	#endif

#endif

#ifdef KJAMS
	ushort		GetSystemVers(void);
	#define		diacritic_insensitiveB		(gApp && gApp->i_prefs && gApp->i_prefs->i_pref.diacritic_insensitive_searchB)
#else
	bool		g_pref_diacritic_insensitive_searchB	= true;
	#define		diacritic_insensitiveB					g_pref_diacritic_insensitive_searchB

	#ifdef _ROSE_
		unsigned short		GetSystemVers(void);
	#else
		static unsigned short		GetSystemVers(void) {
			return 0x1050;	//	fake it to be OS 10.5
		}
	#endif
#endif

static CFOptionFlags		GetFlags_NormalizeStrings(
	SuperString&	str1, 
	SuperString&	str2, 
	CFOptionFlags	optionFlags = 0
		| kCFCompareNonliteral 
		| kCFCompareLocalized)
{
	if (diacritic_insensitiveB) {
		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;
}

#ifndef KJAMS
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;
}
#endif

bool	SuperString::Split(const char *splitZ, SuperString *rhsP0, bool from_endB)
{
	bool			splitB;
	
	if (from_endB) {
		splitB = strrstr(utf8Z(), splitZ) != NULL;
	} else {
		splitB = strstr(utf8Z(), splitZ) != NULL;
	}
	
	if (splitB) {
		UCharVec	bufAC;
		
		bufAC.assign(utf8().begin(), utf8().end());
		bufAC.push_back(0);
		
		UTF8Char	*chZ;
		
		if (from_endB) {
			chZ	= (UTF8Char *)strrstr((char *)&bufAC[0], (char *)splitZ);
		} else {
			chZ	= (UTF8Char *)strstr((char *)&bufAC[0], (char *)splitZ);
		}
		
		SuperString		temp(chZ + strlen(splitZ));
		*chZ = 0;
		Set(&bufAC[0]);
		
		if (rhsP0) {
			rhsP0->Set(temp);
		}
	}
	
	return splitB;
}

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, CFStringEncoding encoding)
{
	UCharVec		charVec;
	
	charVec.assign(&strZ[1], &strZ[strZ[0] + 1]);
	charVec.push_back(0);
	Set(&charVec[0], encoding);
}

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: <%s>, Value: <%s>");
		
		logStr.ssprintf(NULL, descIDStr.utf8Z(), descStr.utf8Z());
		Set(logStr);
	}
}

#ifndef KJAMS
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;
}
#endif

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;
}

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;
}