1/* 2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * UtilitiesCFPrettyPrint.c 25 * DiskImages 26 * 27 * Created by Shantonu Sen on 8/11/04. 28 * Copyright 2004 Apple Computer, Inc. All rights reserved. 29 * 30 */ 31 32#include "UtilitiesCFPrettyPrint.h" 33 34typedef struct TAOCFDepth_Counter { 35 int depth; 36 int arrayIndex; 37 char *indent; 38 FILE *out; 39} TAOCFDepth_Counter; 40 41static void _TAOCFLabelPrettyPrint(char *label, CFTypeRef value, void *context); 42static void _TAOCFDictionaryPrettyPrint(const void *key, const void *value, void *context); 43static void _TAOCFArrayPrettyPrint(const void *value, void *context); 44static void _TAOCFTreePrettyPrint(const void *value, void *context); 45static void _TAOCFBagPrettyPrint(const void *value, void *context); 46static void _TAOCFScalarPrettyPrint(const void *value, void *context); 47static void _TAOCFPrettyPrint_recurse(CFTypeRef inRef, void *h); 48 49static char * _TAOCFGetDescriptionAsCString(CFTypeRef typeRef); 50 51static void _TAOCFLabelPrettyPrint(char *label, CFTypeRef value, void *context) { 52 TAOCFDepth_Counter *h = (TAOCFDepth_Counter *)context; 53 int i; 54 char *desc; 55 56 // we're printing at least label, so tab over 57 58 for(i=0; i< h->depth; i++) { 59 fprintf(h->out, h->indent); 60 } 61 62 fprintf(h->out, "%s", label); 63 64 if(value == NULL) { 65 // our job here is done 66 fprintf(h->out, "\n"); 67 return; 68 } 69 70 if(label && label[0]) { 71 fprintf(h->out, ":"); 72 } 73 74 if(CFGetTypeID(value) == CFDictionaryGetTypeID() 75 || CFGetTypeID(value) == CFArrayGetTypeID() 76 || CFGetTypeID(value) == CFTreeGetTypeID() 77 || CFGetTypeID(value) == CFBagGetTypeID() ) { 78 // go to next line, indent, and recurse 79 TAOCFDepth_Counter newhelper; 80 81 fprintf(h->out, "\n"); 82 83 newhelper.depth = h->depth + 1; 84 newhelper.out = h->out; 85 newhelper.arrayIndex = 0; 86 newhelper.indent = h->indent; 87 _TAOCFPrettyPrint_recurse((CFTypeRef) value, &newhelper); 88 } else { 89 // just a regular key value pair. print 90 desc = _TAOCFGetDescriptionAsCString((CFTypeRef)value); 91 if(label && label[0]) { 92 fprintf(h->out, " "); 93 } 94 if(desc) { 95 fprintf(h->out, "%s\n", desc); 96 free(desc); 97 } else { 98 fprintf(h->out, "(NULL)\n"); 99 } 100 } 101} 102 103static void _TAOCFDictionaryPrettyPrint(const void *key, const void *value, void *context) { 104 char *desc; 105 106 desc = _TAOCFGetDescriptionAsCString((CFTypeRef)key); 107 108 _TAOCFLabelPrettyPrint(desc, (CFTypeRef) value, context); 109 110 if(desc) { 111 free(desc); 112 } 113} 114 115static void _TAOCFArrayPrettyPrint(const void *value, void *context) { 116 char desc[256]; 117 118 snprintf(desc, 256, "%d", ((TAOCFDepth_Counter *)context)->arrayIndex++); 119 120 _TAOCFLabelPrettyPrint(desc, (CFTypeRef)value, context); 121} 122 123static void _TAOCFBagPrettyPrint(const void *value, void *context) { 124 125 _TAOCFLabelPrettyPrint("", (CFTypeRef)value, context); 126} 127 128static void _TAOCFTreePrettyPrint(const void *value, void *context) { 129 //char desc[256]; 130 CFTreeContext treeContext; 131 TAOCFDepth_Counter newhelper; 132 133 newhelper.depth = ((TAOCFDepth_Counter *)context)->depth + 1; 134 newhelper.out = ((TAOCFDepth_Counter *)context)->out; 135 newhelper.indent = ((TAOCFDepth_Counter *)context)->indent; 136 newhelper.arrayIndex = 0; 137 138 // snprintf(desc, 256, "%d", ((TAOCFDepth_Counter *)context)->arrayIndex++); 139 140 CFTreeGetContext((CFTreeRef)value, &treeContext); 141 142 _TAOCFLabelPrettyPrint("", (CFTypeRef)treeContext.info, context); 143 144 // It's a little non-standard to recurse here, but otherwise 145 // we couldn't print the head of the tree. 146 CFTreeApplyFunctionToChildren((CFTreeRef)value, 147 _TAOCFTreePrettyPrint, &newhelper); 148} 149 150static void _TAOCFScalarPrettyPrint(const void *value, void *context) { 151 char *desc; 152 153 desc = _TAOCFGetDescriptionAsCString((CFTypeRef)value); 154 155 _TAOCFLabelPrettyPrint(desc, NULL, context); 156 157 if(desc) { 158 free(desc); 159 } 160} 161 162 163// Used to split CFTypes into key:value form 164static void _TAOCFPrettyPrint_recurse(CFTypeRef inRef, void *h) { 165 166 if(inRef == NULL) { 167 _TAOCFScalarPrettyPrint(inRef, h); 168 } else if(CFGetTypeID(inRef) == CFDictionaryGetTypeID()) { 169 // if we have a dictionary, apply the output function 170 CFDictionaryApplyFunction((CFDictionaryRef)inRef, 171 _TAOCFDictionaryPrettyPrint, h); 172 } else if(CFGetTypeID(inRef) == CFArrayGetTypeID()) { 173 CFArrayApplyFunction((CFArrayRef)inRef, 174 CFRangeMake(0, CFArrayGetCount((CFArrayRef)inRef)), 175 _TAOCFArrayPrettyPrint, h); 176 } else if(CFGetTypeID(inRef) == CFTreeGetTypeID()) { 177 _TAOCFTreePrettyPrint(inRef, h); 178 } else if(CFGetTypeID(inRef) == CFBagGetTypeID()) { 179 CFBagApplyFunction(inRef, _TAOCFBagPrettyPrint, h); 180 } else { 181 _TAOCFScalarPrettyPrint(inRef, h); 182 } 183 184} 185 186 187void TAOCFPrettyPrint(CFTypeRef inRef) { 188 TAOCFPrettyPrintToFile(inRef, stdout); 189} 190 191void TAOCFPrettyPrintWithIndenter(CFTypeRef inRef, char *indent) { 192 TAOCFPrettyPrintToFileWithIndenter(inRef, stdout, indent); 193} 194 195void TAOCFPrettyPrintToFile(CFTypeRef inRef, FILE *out) { 196 TAOCFPrettyPrintToFileWithIndenter(inRef, out, "\t"); 197} 198 199void TAOCFPrettyPrintToFileWithIndenter(CFTypeRef inRef, FILE *out, char *indent) { 200 TAOCFDepth_Counter helper; 201 202 helper.depth = 0; 203 helper.out = out; 204 helper.arrayIndex = 0; 205 helper.indent = indent; 206 207 _TAOCFPrettyPrint_recurse(inRef, &helper); 208 209} 210 211 212static char * _TAOCFGetDescriptionAsCString(CFTypeRef typeRef) 213{ 214 char *str = NULL; 215 CFStringRef cfstr = NULL; 216 CFIndex len; 217 218// if(typeRef == NULL) typeRef = kCFNull; 219 cfstr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), typeRef); 220 if(cfstr == NULL && typeRef != NULL) cfstr = CFSTR("<error getting string representation>"); 221 222 // add one for the NULL that CFStringGetCString will append 223 len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), kCFStringEncodingUTF8) + 1; 224 str = malloc(len); 225 if (str) { 226 if (!CFStringGetCString(cfstr, str, len, kCFStringEncodingUTF8)) { 227 free(str); 228 str = NULL; 229 } 230 } 231 232 return str; 233} 234