#include "misc.h"
#include "SecCFRelease.h"
char *utf8(CFStringRef s) {
CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(s), kCFStringEncodingUTF8) + 1;
CFIndex used = 0;
UInt8 *buf = (UInt8 *)malloc(sz);
if (!buf) {
return NULL;
}
CFStringGetBytes(s, CFRangeMake(0, CFStringGetLength(s)), kCFStringEncodingUTF8, '?', FALSE, buf, sz, &used);
buf[used] = 0;
return (char*)buf;
}
void CFfprintf(FILE *f, const char *format, ...) {
va_list ap;
va_start(ap, format);
CFStringRef fmt = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8);
CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, ap);
va_end(ap);
CFReleaseNull(fmt);
CFIndex sz = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
sz += 1;
CFIndex used = 0;
unsigned char *buf;
bool needs_free = false;
if (sz < 1024) {
buf = alloca(sz);
} else {
buf = malloc(sz);
needs_free = true;
}
if (buf) {
CFStringGetBytes(str, CFRangeMake(0, CFStringGetLength(str)), kCFStringEncodingUTF8, '?', FALSE, buf, sz, &used);
} else {
buf = (unsigned char *)"malloc failue during CFfprintf\n";
needs_free = false;
}
fwrite(buf, 1, used, f);
if (needs_free) {
free(buf);
}
CFReleaseNull(str);
}
CFErrorRef fancy_error(CFStringRef domain, CFIndex code, CFStringRef description) {
const void *v_ekey = kCFErrorDescriptionKey;
const void *v_description = description;
CFErrorRef err = CFErrorCreateWithUserInfoKeysAndValues(NULL, domain, code, &v_ekey, &v_description, 1);
CFAutorelease(err);
return err;
}
static
void add_t2ca(CFMutableDictionaryRef t2ca, CFStringRef t, CFStringRef a) {
CFMutableSetRef ca = (CFMutableSetRef)CFDictionaryGetValue(t2ca, t);
if (!ca) {
ca = CFSetCreateMutable(NULL, 0, &kCFCopyStringSetCallBacks);
CFDictionarySetValue(t2ca, t, ca);
}
CFSetAddValue(ca, a);
}
void CFSafeRelease(CFTypeRef object) {
if (object) {
CFReleaseNull(object);
}
}
void graphviz(FILE *f, SecTransformRef tr) {
CFDictionaryRef d = SecTransformCopyExternalRepresentation(tr);
CFfprintf(f, "digraph TR {\n\tnode [shape=plaintext];\n\n");
CFIndex i, j;
CFArrayRef transforms = CFDictionaryGetValue(d, CFSTR("TRANSFORMS"));
CFArrayRef connections = CFDictionaryGetValue(d, CFSTR("ARRAY"));
CFMutableDictionaryRef t2ca = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
for(i = 0; i < CFArrayGetCount(connections); i++) {
CFDictionaryRef c = CFArrayGetValueAtIndex(connections, i);
CFStringRef t_from = CFDictionaryGetValue(c, CFSTR("FROM_NAME"));
CFStringRef t_to = CFDictionaryGetValue(c, CFSTR("TO_NAME"));
CFStringRef a_from = CFDictionaryGetValue(c, CFSTR("FROM_ATTRIBUTE"));
CFStringRef a_to = CFDictionaryGetValue(c, CFSTR("TO_ATTRIBUTE"));
add_t2ca(t2ca, t_from, a_from);
add_t2ca(t2ca, t_to, a_to);
}
for(i = 0; i < CFArrayGetCount(transforms); i++) {
CFDictionaryRef t = CFArrayGetValueAtIndex(transforms, i);
CFStringRef name = CFDictionaryGetValue(t, CFSTR("NAME"));
CFfprintf(f, "\tsubgraph \"cluster_%@\"{\n", name);
CFMutableSetRef ca = (CFMutableSetRef)CFDictionaryGetValue(t2ca, name);
if (ca) {
CFIndex cnt = CFSetGetCount(ca);
CFStringRef *attrs = malloc(cnt * sizeof(CFStringRef));
CFSetGetValues(ca, (const void **)attrs);
for(j = 0; j < cnt; j++) {
CFfprintf(f, "\t\t\"%@#%@\" [label=\"%@\"];\n", name, attrs[j], attrs[j]);
}
CFfprintf(f, "\t\t\"%@\" [fontcolor=blue, fontsize=20];\n\t}\n");
free(attrs);
}
}
CFfprintf(f, "\n");
for(i = 0; i < CFArrayGetCount(connections); i++) {
CFDictionaryRef c = CFArrayGetValueAtIndex(connections, i);
CFStringRef t_from = CFDictionaryGetValue(c, CFSTR("FROM_NAME"));
CFStringRef t_to = CFDictionaryGetValue(c, CFSTR("TO_NAME"));
CFStringRef a_from = CFDictionaryGetValue(c, CFSTR("FROM_ATTRIBUTE"));
CFStringRef a_to = CFDictionaryGetValue(c, CFSTR("TO_ATTRIBUTE"));
CFfprintf(f, "\t\"%@#%@\" -> \"%@#%@\";\n", t_from, a_from, t_to, a_to);
}
CFfprintf(f, "}\n");
CFfprintf(f, "\n/*\n%@\n/*\n", d);
}