1/* 2 * Copyright (c) 2010-2012,2014 Apple 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 25#include "misc.h" 26 27 28// NOTE: the return may or allocate a fair bit more space then it needs. 29// Use it for short lived conversions (or strdup the result). 30char *utf8(CFStringRef s) { 31 CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), kCFStringEncodingUTF8) + 1; 32 CFIndex used = 0; 33 UInt8 *buf = (UInt8 *)malloc(sz); 34 if (!buf) { 35 return NULL; 36 } 37 CFStringGetBytes(s, CFRangeMake(0, CFStringGetLength(s)), kCFStringEncodingUTF8, '?', FALSE, buf, sz, &used); 38 buf[used] = 0; 39 40 return (char*)buf; 41} 42 43void CFfprintf(FILE *f, const char *format, ...) { 44 va_list ap; 45 va_start(ap, format); 46 47 CFStringRef fmt = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8); 48 CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, ap); 49 va_end(ap); 50 CFRelease(fmt); 51 52 CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); 53 sz += 1; 54 CFIndex used = 0; 55 unsigned char *buf; 56 bool needs_free = false; 57 if (sz < 1024) { 58 buf = alloca(sz); 59 } else { 60 buf = malloc(sz); 61 needs_free = true; 62 } 63 if (buf) { 64 CFStringGetBytes(str, CFRangeMake(0, CFStringGetLength(str)), kCFStringEncodingUTF8, '?', FALSE, buf, sz, &used); 65 } else { 66 buf = (unsigned char *)"malloc failue during CFfprintf\n"; 67 } 68 69 fwrite(buf, 1, used, f); 70 if (needs_free) { 71 free(buf); 72 } 73 74 CFRelease(str); 75} 76 77CFErrorRef fancy_error(CFStringRef domain, CFIndex code, CFStringRef description) { 78 const void *v_ekey = kCFErrorDescriptionKey; 79 const void *v_description = description; 80 CFErrorRef err = CFErrorCreateWithUserInfoKeysAndValues(NULL, domain, code, &v_ekey, &v_description, 1); 81 82 return err; 83} 84 85static 86void add_t2ca(CFMutableDictionaryRef t2ca, CFStringRef t, CFStringRef a) { 87 CFMutableSetRef ca = (CFMutableSetRef)CFDictionaryGetValue(t2ca, t); 88 if (!ca) { 89 ca = CFSetCreateMutable(NULL, 0, &kCFCopyStringSetCallBacks); 90 CFDictionarySetValue(t2ca, t, ca); 91 } 92 CFSetAddValue(ca, a); 93} 94 95void CFSafeRelease(CFTypeRef object) { 96 if (object) { 97 CFRelease(object); 98 } 99} 100 101void graphviz(FILE *f, SecTransformRef tr) { 102 CFDictionaryRef d = SecTransformCopyExternalRepresentation(tr); 103 104 CFfprintf(f, "digraph TR {\n\tnode [shape=plaintext];\n\n"); 105 CFIndex i, j; 106 CFArrayRef transforms = CFDictionaryGetValue(d, CFSTR("TRANSFORMS")); 107 CFArrayRef connections = CFDictionaryGetValue(d, CFSTR("ARRAY")); 108 109 110 // map transforms to connected attributes 111 CFMutableDictionaryRef t2ca = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 112 for(i = 0; i < CFArrayGetCount(connections); i++) { 113 CFDictionaryRef c = CFArrayGetValueAtIndex(connections, i); 114 115 CFStringRef t_from = CFDictionaryGetValue(c, CFSTR("FROM_NAME")); 116 CFStringRef t_to = CFDictionaryGetValue(c, CFSTR("TO_NAME")); 117 CFStringRef a_from = CFDictionaryGetValue(c, CFSTR("FROM_ATTRIBUTE")); 118 CFStringRef a_to = CFDictionaryGetValue(c, CFSTR("TO_ATTRIBUTE")); 119 120 add_t2ca(t2ca, t_from, a_from); 121 add_t2ca(t2ca, t_to, a_to); 122 } 123 124 125 for(i = 0; i < CFArrayGetCount(transforms); i++) { 126 CFDictionaryRef t = CFArrayGetValueAtIndex(transforms, i); 127 // NAME STATE(dict) TYPE 128 CFStringRef name = CFDictionaryGetValue(t, CFSTR("NAME")); 129 130 CFfprintf(f, "\tsubgraph \"cluster_%@\"{\n", name); 131 132 CFMutableSetRef ca = (CFMutableSetRef)CFDictionaryGetValue(t2ca, name); 133 if (ca) { 134 CFIndex cnt = CFSetGetCount(ca); 135 CFStringRef *attrs = malloc(cnt * sizeof(CFStringRef)); 136 CFSetGetValues(ca, (const void **)attrs); 137 138 for(j = 0; j < cnt; j++) { 139 CFfprintf(f, "\t\t\"%@#%@\" [label=\"%@\"];\n", name, attrs[j], attrs[j]); 140 } 141 CFfprintf(f, "\t\t\"%@\" [fontcolor=blue, fontsize=20];\n\t}\n"); 142 } 143 } 144 145 CFfprintf(f, "\n"); 146 147 for(i = 0; i < CFArrayGetCount(connections); i++) { 148 CFDictionaryRef c = CFArrayGetValueAtIndex(connections, i); 149 150 CFStringRef t_from = CFDictionaryGetValue(c, CFSTR("FROM_NAME")); 151 CFStringRef t_to = CFDictionaryGetValue(c, CFSTR("TO_NAME")); 152 CFStringRef a_from = CFDictionaryGetValue(c, CFSTR("FROM_ATTRIBUTE")); 153 CFStringRef a_to = CFDictionaryGetValue(c, CFSTR("TO_ATTRIBUTE")); 154 155 CFfprintf(f, "\t\"%@#%@\" -> \"%@#%@\";\n", t_from, a_from, t_to, a_to); 156 } 157 158 CFfprintf(f, "}\n"); 159 160 CFfprintf(f, "\n/*\n%@\n/*\n", d); 161} 162