blob: 956ac35188d6c52627193237f47e41a8c21cef3d [file] [log] [blame]
/*
* CFUtils.cpp
* CFTest
*
* Created by David M. Cotter on 7/23/08.
* Copyright 2008 David M. Cotter. All rights reserved.
*
*/
#include "stdafx.h"
#if defined(_KJAMS_) && !defined(_KJAMSX_)
#include "StringUtils.h"
#include "MessageAlert.h"
#else
#ifndef _CFTEST_
#include "XConfig.h"
#endif
#include "SuperString.h"
#include <CoreFoundation/CFDateFormatter.h>
#include <CoreFoundation/CFNumberFormatter.h>
#include <CoreFoundation/CFCalendar.h>
#endif
#ifndef _CFTEST_
#if _KJ_MAC_
#include "MessageAlert.h"
#else
#include <XErrorDialogs.h>
#endif
#include "CLocalize.h"
#endif
void FilterErr(OSStatus err);
void FilterErr(OSStatus err)
{
#ifdef kDEBUG
if (err == eofErr) {
err = eofErr;
}
#endif
}
#if defined(__WIN32__)
static bool s_setLogB = false;
#endif
void CCFLog::operator()(CFTypeRef valRef) {
#define USE_CFSHOW 0
#if defined(__WIN32__)
if (!s_setLogB) {
s_setLogB = true;
// CFSetLogFile(CFSTR("CF_Log.txt"), kCFStringEncodingUTF8);
}
#endif
#if !USE_CFSHOW
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.w_strlen(), &outL, NULL);
log_fileP = NULL;
#else
// GUI APP
static FILE *s_logP = NULL;
if (s_logP == NULL) {
(void)fopen_s(&s_logP, kJams_LogFileName, "a");
}
log_fileP = s_logP;
#endif
#endif
if (log_fileP) {
#ifdef _KJAMSX_
fprintf(log_fileP, "%s", valStr.utf8Z());
fflush(log_fileP);
#else
#if _CFTEST_
fprintf(log_fileP, "%s", valStr.utf8Z());
fflush(log_fileP);
#else
Log(valStr.utf8Z());
#endif
#endif
}
#else
#ifndef __WIN32__
fflush(stdout);
#endif
CFShow(valRef);
if (i_crB) {
CFShow(CFSTR("\n"));
}
#ifndef __WIN32__
fflush(stdout);
#endif
#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);
}
/*****************************************************************************/
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,
kCFPropertyListMutableContainersAndLeaves,
NULL);
successB = *plistP != NULL;
if (successB) {
// Log("created plist from xml");
} else {
// CCFLog()(CFSTR("FAILED converting xml to plist\n"));
}
} else {
//CCFLog()(CFSTR("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;
}
OSErr CFDictionaryCreate(CFMutableDictionaryRef *dictP)
{
OSErr err = noErr;
*dictP = CFDictionaryCreateMutable(
kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (*dictP == NULL) {
err = 1;
}
return err;
}
OSErr CFArrayCreate(CFMutableArrayRef *arrayP)
{
OSErr err = noErr;
*arrayP = CFArrayCreateMutable(
kCFAllocatorDefault, 0,
&kCFTypeArrayCallBacks);
if (*arrayP == NULL) {
err = 1;
}
return err;
}
/********************************************************/
bool CCFXmlTree::CreateFromData(CFDataRef xmlData, CFURLRef dataSource, CFOptionFlags parseOptions)
{
CCFDictionary dict(NULL, false);
CFXMLTreeRef treeRef = CFXMLTreeCreateFromDataWithError(
kCFAllocatorDefault,
xmlData,
dataSource,
parseOptions,
kCFXMLNodeCurrentVersion,
dict.ImmutableAddressOf());
_inherited::adopt(treeRef);
if (treeRef == NULL) {
CCFLog(true)(dict);
}
return treeRef != NULL;
}
bool Read_XML(const CFURLRef url, CCFXmlTree& xml)
{
bool successB = false;
ScCFReleaser<CFDataRef> xmlData;
if (CFURLCreateDataAndPropertiesFromResource(
kCFAllocatorDefault, url, xmlData.AddressOf(), NULL, NULL, NULL)
) {
successB = xml.CreateFromData(xmlData.Get(), url, kCFXMLParserSkipWhitespace | kCFXMLParserReplacePhysicalEntities);
}
return successB;
}
/********************************************************/
CFMutableDictionaryRef CCFDictionary::Copy()
{
return CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, Get());
}
bool CCFDictionary::ContainsKey(CFStringRef keyRef) {
return !!CFDictionaryContainsKey(Get(), keyRef);
}
bool CCFDictionary::ContainsKey(const char *utf8Z) {
SuperString dictKey(uc(utf8Z));
return ContainsKey(dictKey.ref());
}
CFTypeRef CCFDictionary::GetValue(const char* keyZ)
{
SuperString keyStr(uc(keyZ));
return GetValue(keyStr.ref());
}
CFStringRef CCFDictionary::GetAs_String (const char *utf8Z)
{
CFStringRef stringRef((CFStringRef)GetValue(utf8Z));
if (stringRef) {
CF_ASSERT(CFGetTypeID(stringRef) == CFStringGetTypeID());
}
return stringRef;
}
CFDictionaryRef CCFDictionary::GetAs_Dict (const char *utf8Z)
{
CFDictionaryRef dictRef((CFDictionaryRef)GetValue(utf8Z));
if (dictRef) {
CF_ASSERT(CFGetTypeID(dictRef) == CFDictionaryGetTypeID());
}
return dictRef;
}
SInt32 CCFDictionary::GetAs_SInt32 (const char *utf8Z)
{
CFNumberRef valRef((CFNumberRef)GetValue(utf8Z));
SInt32 valL = 0;
if (valRef) {
CF_ASSERT(CFGetTypeID(valRef) == CFNumberGetTypeID());
CFNumberGetValue(valRef, kCFNumberSInt32Type, &valL);
}
return valL;
}
SInt16 CCFDictionary::GetAs_SInt16 (const char *utf8Z)
{
CFNumberRef valRef((CFNumberRef)GetValue(utf8Z));
SInt16 valL = 0;
if (valRef) {
CF_ASSERT(CFGetTypeID(valRef) == CFNumberGetTypeID());
CFNumberGetValue(valRef, kCFNumberSInt16Type, &valL);
}
return valL;
}
CFDateRef CCFDictionary::GetAs_Date (const char *utf8Z)
{
CFDateRef dateRef((CFDateRef)GetValue(utf8Z));
if (dateRef) {
CF_ASSERT(CFGetTypeID(dateRef) == CFDateGetTypeID());
}
return dateRef;
}
CFArrayRef CCFDictionary::GetAs_Array (const char *utf8Z)
{
CFArrayRef arrayRef((CFArrayRef)GetValue(utf8Z));
if (arrayRef) {
CF_ASSERT(CFGetTypeID(arrayRef) == CFArrayGetTypeID());
}
return arrayRef;
}
OSStatus CFWriteDataToURL(const CFURLRef urlRef, CFDataRef dataRef)
{
OSStatus err = noErr;
(void)CFURLWriteDataAndPropertiesToResource (
urlRef, // URL to use
dataRef, // data to write
NULL, // dictRef meta properties to write
&err);
return err;
}
void CCFDictionary::RemoveValue(CFStringRef key)
{
CFDictionaryRemoveValue(Get(), key);
}
void CCFDictionary::RemoveValue(const char *utf8Z)
{
RemoveValue(SuperString(uc(utf8Z)).ref());
}
/*****************************************/
Rect CCFDictionary::GetAs_Rect (const char *utf8Z)
{
Rect frameR; structclr(frameR);
CCFDictionary dict(GetAs_Dict(utf8Z), true);
if (dict.Get()) {
frameR.left = dict.GetAs_SInt16(DICT_STR_RECT_LEFT);
frameR.right = dict.GetAs_SInt16(DICT_STR_RECT_RIGHT);
frameR.top = dict.GetAs_SInt16(DICT_STR_RECT_TOP);
frameR.bottom = dict.GetAs_SInt16(DICT_STR_RECT_BOTTOM);
}
return frameR;
}
void CCFDictionary::SetValue(const char *utf8Z, const Rect& frameR)
{
CCFDictionary dict;
dict.SetValue(DICT_STR_RECT_LEFT, frameR.left);
dict.SetValue(DICT_STR_RECT_RIGHT, frameR.right);
dict.SetValue(DICT_STR_RECT_TOP, frameR.top);
dict.SetValue(DICT_STR_RECT_BOTTOM, frameR.bottom);
SetValue(utf8Z, dict.Get());
}
/*****************************************/
bool CCFDictionary::GetAs_Bool (const char *utf8Z)
{
CFBooleanRef boolRef = (CFBooleanRef)GetValue(utf8Z);
if (boolRef) {
CF_ASSERT(CFGetTypeID(boolRef) == CFBooleanGetTypeID());
}
return boolRef == kCFBooleanTrue;
}
void CCFDictionary::SetValue (const char *utf8Z, bool valB)
{
SetValue(utf8Z, valB ? kCFBooleanTrue : kCFBooleanFalse);
}
/*****************************************/
float CCFDictionary::GetAs_Float (const char *utf8Z)
{
float valF = 0;
CFNumberRef valRef((CFNumberRef)GetValue(utf8Z));
if (valRef) {
CF_ASSERT(CFGetTypeID(valRef) == CFNumberGetTypeID());
CFNumberGetValue(valRef, kCFNumberFloatType, &valF);
}
return valF;
}
void CCFDictionary::SetValue (const char *utf8Z, float valF)
{
ScCFReleaser<CFNumberRef> numberRef(CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &valF));
SetValue(utf8Z, numberRef.Get());
}
/*****************************************/
RGBColor CCFDictionary::GetAs_Color (const char *utf8Z)
{
RGBColor valR = { 0, 0, 0 };
CCFDictionary dict(GetAs_Dict(utf8Z), true);
if (dict.Get()) {
valR.red = (UInt16)GetAs_UInt32(DICT_STR_COLOR_RED);
valR.green = (UInt16)GetAs_UInt32(DICT_STR_COLOR_GREEN);
valR.blue = (UInt16)GetAs_UInt32(DICT_STR_COLOR_BLUE);
}
return valR;
}
void CCFDictionary::SetValue(const char *utf8Z, const RGBColor& value)
{
CCFDictionary dict;
dict.SetValue(DICT_STR_COLOR_RED, (UInt32)value.red);
dict.SetValue(DICT_STR_COLOR_GREEN, (UInt32)value.green);
dict.SetValue(DICT_STR_COLOR_BLUE, (UInt32)value.blue);
SetValue(utf8Z, dict.Get());
}
/*****************************************/
CFNumberRef CFNumberCreateWithSInt32(SInt32 valL)
{
return CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &valL);
}
void CCFDictionary::SetValue(CFStringRef keyRef, SInt32 value)
{
ScCFReleaser<CFNumberRef> numberRef(CFNumberCreateWithSInt32(value));
SetValue(keyRef, numberRef.Get());
}
void CCFDictionary::SetValue(const char *utf8Z, SInt32 value)
{
ScCFReleaser<CFNumberRef> numberRef(CFNumberCreateWithSInt32(value));
SetValue(utf8Z, numberRef.Get());
}
void CCFDictionary::SetValue(const char *utf8Z, SInt16 value)
{
ScCFReleaser<CFNumberRef> numberRef(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &value));
SetValue(utf8Z, numberRef.Get());
}
void CCFDictionary::SetValue(const char *utf8Z, CFTypeRef val)
{
SuperString keyStr(uc(utf8Z));
SetValue(keyStr.ref(), val);
}
void CCFDictionary::SetValue(const char *utf8Z, const SuperString& value)
{
SetValue(utf8Z, value.ref());
}
/**********************************************************************/
#ifndef __WIN32__
CFDateRef CFDateCreateWithLongDateTime(const LongDateTime &ldt)
{
CFDateRef dateRef = NULL;
if (ldt != 0) {
OSStatus err = noErr;
CFAbsoluteTime absT;
err = UCConvertLongDateTimeToCFAbsoluteTime(ldt, &absT);
if (!err) {
dateRef = CFDateCreate(kCFAllocatorDefault, absT);
}
}
return dateRef;
}
LongDateTime CFDateToLongDateTime(CFDateRef dateRef)
{
LongDateTime ldt; structclr(ldt);
if (dateRef) {
CFAbsoluteTime absT = CFDateGetAbsoluteTime(dateRef);
UCConvertCFAbsoluteTimeToLongDateTime(absT, &ldt);
}
return ldt;
}
#endif
CFDateRef CFDateCreateWithGregorian(const CFGregorianDate& gregDate)
{
ScCFReleaser<CFCalendarRef> calendarRef(CFCalendarCopyCurrent());
ScCFReleaser<CFTimeZoneRef> timeZoneRef(CFCalendarCopyTimeZone(calendarRef));
return CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(gregDate, timeZoneRef));
}
CFStringRef CFStringCreateWithDate(CFDateRef dateRef, bool showTimeB)
{
ScCFReleaser<CFLocaleRef> localeRef(CFLocaleCopyCurrent());
ScCFReleaser<CFDateFormatterRef> formatterRef(CFDateFormatterCreate(
kCFAllocatorDefault, localeRef,
kCFDateFormatterShortStyle, showTimeB ? kCFDateFormatterShortStyle : kCFDateFormatterNoStyle));
CFStringRef ref(CFDateFormatterCreateStringWithDate(
kCFAllocatorDefault, formatterRef, dateRef));
return (CFStringRef)CFRetainDebug(ref, false); // don't retain, just track that it's existing refcount
}
CFStringRef CFStringCreateWithNumber(CFNumberRef numRef)
{
ScCFReleaser<CFLocaleRef> localeRef(CFLocaleCopyCurrent());
ScCFReleaser<CFNumberFormatterRef> formatterRef(CFNumberFormatterCreate(
kCFAllocatorDefault, localeRef, kCFNumberFormatterNoStyle));
CFStringRef ref(CFNumberFormatterCreateStringWithNumber(
kCFAllocatorDefault, formatterRef, numRef));
return (CFStringRef)CFRetainDebug(ref, false);
}
/*
CFStringRef CFCopyBundleResourcesFSPath()
{
ScCFReleaser<CFBundleRef> exeRef(CFBundleGetMainBundle(), true);
ScCFReleaser<CFURLRef> exeUrlRef(CFBundleCopyBundleURL(exeRef));
SuperString dirStr(CFURLCopyFileSystemPath(exeUrlRef, kCFURLPlatformPathStyle));
dirStr.append(kCFURLPlatformPathSeparator "Contents" kCFURLPlatformPathSeparator "Resources");
return dirStr.Retain();
}
*/
/**********************************************************************/
#if _KJ_MAC_
#include "CApp.h"
int AssertAlert(const char *msgZ, const char *fileZ, long lineL, bool noThrowB)
{
bool incB = MPTaskIsPreemptive(NULL);
if (incB) {
++gApp->i_callbackL;
noThrowB = true;
}
bool mainB = gApp->i_callbackL == 0;
if (incB) {
--gApp->i_callbackL;
}
SuperString formatStr(SSLocalize("Assert Fail: %s, in file: '%s' at line %ld", "eeeks!"));
formatStr.ssprintf(NULL, msgZ, fileZ, lineL);
if (mainB) {
MessageAlert(formatStr.utf8Z());
} else {
PostAlert(formatStr.utf8Z());
#ifdef kDEBUG
static bool s_showB = true;
if (s_showB) {
Debugger();
}
#endif
}
if (!mainB && !noThrowB) {
ETX(ERR_Assert_Failed);
}
return 1;
}
#else
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());
ReportErr(formatStr.utf8Z(), -1);
return 1;
}
#endif