#include <libc.h>
#include "printPList_new.h"
#include "misc_util.h"
static void _indent(CFMutableStringRef string, unsigned indentLevel)
{
unsigned int i;
for (i = 0; i < indentLevel; i++) {
CFStringAppendCString(string, " ", kCFStringEncodingUTF8);
}
return;
}
static void _appendCFString(
CFMutableStringRef string,
CFStringRef aString,
Boolean withQuotes)
{
char * quote = "";
if (withQuotes) quote = "\"";
CFStringAppendFormat(string, NULL, CFSTR("%s%@%s"), quote, aString, quote);
return;
}
static void _appendCFURL(CFMutableStringRef string,
CFURLRef anURL)
{
CFURLRef absURL = NULL; CFStringRef absPath = NULL; char pathBuffer[PATH_MAX];
absURL = CFURLCopyAbsoluteURL(anURL);
if (!absURL) {
goto finish;
}
absPath = CFURLCopyFileSystemPath(anURL, kCFURLPOSIXPathStyle);
if (!absPath) {
goto finish;
}
CFURLGetFileSystemRepresentation(anURL, true, (UInt8 *)pathBuffer,
PATH_MAX);
CFStringAppendCString(string, pathBuffer, kCFStringEncodingUTF8);
finish:
if (absURL) CFRelease(absURL);
if (absPath) CFRelease(absPath);
return;
}
static void _appendPlist(
CFMutableStringRef string,
CFTypeRef plist,
CFTypeRef plistRoot,
PListStyle style,
unsigned indentLevel)
{
CFTypeID typeID = 0;
unsigned int indentIncrement = 4;
if (!plist) {
return;
}
if (plist == plistRoot) {
indentIncrement = 0;
}
typeID = CFGetTypeID(plist);
if (typeID == CFDictionaryGetTypeID()) {
CFDictionaryRef dict = (CFDictionaryRef)plist;
CFIndex count, i;
CFStringRef * keys = NULL; CFTypeRef * values = NULL; count = CFDictionaryGetCount(dict);
keys = (CFStringRef *)malloc(count * sizeof(CFStringRef));
values = (CFTypeRef *)malloc(count * sizeof(CFTypeRef));
CFDictionaryGetKeysAndValues(dict, (const void **)keys,
(const void **)values);
if (style == kPListStyleDiagnostics) {
if (plist != plistRoot) {
CFStringAppendCString(string, "\n", kCFStringEncodingUTF8);
}
} else {
CFStringAppendCString(string, "{\n", kCFStringEncodingUTF8);
}
for (i = 0; i < count; i++) {
_indent(string, indentLevel + indentIncrement);
_appendCFString(string, keys[i],
(style != kPListStyleDiagnostics));
if ( (CFBooleanGetTypeID() == CFGetTypeID(values[i])) &&
(style == kPListStyleDiagnostics) ) {
CFStringAppendFormat(string, NULL, CFSTR("\n"));
continue; }
if (style == kPListStyleDiagnostics) {
CFStringAppendCString(string, ": ", kCFStringEncodingUTF8);
} else {
CFStringAppendCString(string, " = ", kCFStringEncodingUTF8);
}
if (CFGetTypeID(values[i]) == CFStringGetTypeID()) {
CFIndex keyLength = CFStringGetLength(keys[i]);
CFIndex valueLength = CFStringGetLength(values[i]);
if (indentLevel + indentIncrement + keyLength + valueLength > 72) {
CFStringAppendCString(string, "\n", kCFStringEncodingUTF8);
_indent(string, indentLevel + (4 + indentIncrement));
}
}
_appendPlist(string, values[i], plistRoot, style, indentLevel +
indentIncrement);
if (style == kPListStyleDiagnostics && (i + 1 < count)) {
if (plist == plistRoot) {
CFStringAppendCString(string, "\n", kCFStringEncodingUTF8);
}
}
}
if (style != kPListStyleDiagnostics) {
_indent(string, indentLevel);
CFStringAppendCString(string, "}\n", kCFStringEncodingUTF8);
}
free(keys);
free(values);
} else if (typeID == CFArrayGetTypeID()) {
CFArrayRef array = (CFArrayRef)plist;
CFIndex count, i;
count = CFArrayGetCount(array);
if (style == kPListStyleDiagnostics && (plist != plistRoot)) {
if (plist != plistRoot) {
CFStringAppendCString(string, "\n", kCFStringEncodingUTF8);
}
} else {
CFStringAppendCString(string, "(\n", kCFStringEncodingUTF8);
}
for (i = 0; i < count; i++) {
_indent(string, indentLevel + indentIncrement);
_appendPlist(string, CFArrayGetValueAtIndex(array, i), plistRoot,
style, indentLevel + indentIncrement);
}
if (style != kPListStyleDiagnostics) {
_indent(string, indentLevel);
CFStringAppendCString(string, ")\n", kCFStringEncodingUTF8);
}
} else if (typeID == CFStringGetTypeID()) {
_appendCFString(string, (CFStringRef)plist,
((indentLevel > 0) && (style != kPListStyleDiagnostics)));
CFStringAppendCString(string, "\n", kCFStringEncodingUTF8);
} else if (typeID == CFURLGetTypeID()) {
_appendCFURL(string, (CFURLRef)plist);
CFStringAppendCString(string, "\n", kCFStringEncodingUTF8);
} else if (typeID == CFDataGetTypeID()) {
CFStringRef dataString = createCFStringForData((CFDataRef)plist, 16);
if (dataString) {
CFStringAppend(string, dataString);
CFStringAppendCString(string, "\n", kCFStringEncodingUTF8);
SAFE_RELEASE(dataString);
} else {
CFStringAppendCString(string, "(data object)\n", kCFStringEncodingUTF8);
}
} else if (typeID == CFNumberGetTypeID()) {
CFStringAppendFormat(string, NULL, CFSTR("%@"), (CFNumberRef)plist);
CFStringAppendCString(string, "\n", kCFStringEncodingUTF8);
} else if (typeID == CFBooleanGetTypeID()) {
CFBooleanRef booleanValue = (CFBooleanRef)plist;
CFStringAppendFormat(string, NULL, CFSTR("%s\n"),
CFBooleanGetValue(booleanValue) ? "true" : "false");
} else if (typeID == CFDateGetTypeID()) {
CFStringAppendCString(string, "(date object)\n", kCFStringEncodingUTF8);
} else {
CFStringAppendCString(string, "(unknown object)\n", kCFStringEncodingUTF8);
}
return;
}
void printPList_new(FILE * stream, CFTypeRef plist, PListStyle style)
{
CFMutableStringRef string = NULL; CFIndex bufSize;
char * c_string = NULL;
string = createCFStringForPlist_new(plist, style);
if (!string) {
goto finish;
}
bufSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(string),
kCFStringEncodingUTF8) + sizeof('\0');
c_string = (char *)malloc(bufSize);
if (!c_string) {
goto finish;
}
if (CFStringGetCString(string, c_string, bufSize, kCFStringEncodingUTF8)) {
fprintf(stream, "%s", c_string);
}
finish:
if (string) CFRelease(string);
if (c_string) free(c_string);
return;
}
void showPList_new(CFPropertyListRef plist, PListStyle style)
{
printPList_new(stdout, plist, style);
return;
}
CFMutableStringRef createCFStringForPlist_new(CFTypeRef plist, PListStyle style)
{
CFMutableStringRef string = NULL;
string = CFStringCreateMutable(kCFAllocatorDefault, 0);
if (!string) {
goto finish;
}
_appendPlist(string, plist, plist, style, 0);
finish:
return string;
}