#include <Security/SecureObjectSync/SOSViewManager.h>
#include <Security/SecureObjectSync/SOSInternal.h>
#if 0
struct __OpaqueSOSViewManager {
CFRuntimeBase _base;
CFMutableDictionaryRef views;
};
const CFStringRef kSOSContextChildInfoKey = CFSTR("cntx");
const CFStringRef kSOSFunctionChildInfoKey = CFSTR("fctn");
const CFStringRef kSOSViewNamesChildInfoKey = CFSTR("vwns");
static CFStringRef SOSViewManagerCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
SOSViewManagerRef vmgr = (SOSViewManagerRef)cf;
CFStringRef desc = CFStringCreateWithFormat(kCFAllocatorDefault, formatOptions, CFSTR("<ViewManager %@ >"), vmgr->views);
return desc;
}
static void SOSViewManagerDestroy(CFTypeRef cf) {
SOSViewManagerRef vmgr = (SOSViewManagerRef)cf;
CFReleaseSafe(vmgr->views);
}
CFGiblisFor(SOSViewManager);
static SOSViewManagerRef SOSViewManagerCreate(CFAllocatorRef allocator, CFErrorRef *error) {
SOSViewManagerRef vmgr = NULL;
vmgr = CFTypeAllocate(SOSViewManager, struct __OpaqueSOSViewManager, allocator);
if (vmgr)
vmgr->views = CFDictionaryCreateMutableForCFTypes(allocator);
return vmgr;
}
CFGiblisGetSingleton(SOSViewManagerRef, SOSGetViewManager, sSOSViewManager, ^{
*sSOSViewManager = SOSViewManagerCreate(kCFAllocatorDefault, NULL);
});
static CFStringRef CFStringCreateWithViewNames(CFArrayRef viewNames) {
CFIndex count = CFArrayGetCount(viewNames);
CFMutableArrayRef mvn = CFArrayCreateMutableCopy(kCFAllocatorDefault, count, viewNames);
CFArraySortValues(mvn, CFRangeMake(0, count), (CFComparatorFunction)CFStringCompare, 0);
CFStringRef string = CFStringCreateByCombiningStrings(kCFAllocatorDefault, mvn, CFSTR(":"));
CFRelease(mvn);
return string;
}
static SOSViewRef SOSViewManangerCopyViewWithName(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFStringRef viewName, bool isConcrete, CFErrorRef *error) {
SOSViewRef view = (SOSViewRef)CFDictionaryGetValue(vmgr->views, viewName);
if (view) {
if (isConcrete)
SOSViewSetConcrete(view, true);
CFRetain(view);
} else {
view = SOSViewCreate(CFGetAllocator(vmgr), isConcrete, NULL, error);
if (view) {
CFDictionarySetValue(vmgr->views, viewName, view);
}
}
if (view) {
if (isConcrete)
CFDictionarySetValue(referencedViews, viewName, kCFBooleanTrue);
else if (!CFDictionaryContainsKey(referencedViews, viewName))
CFDictionarySetValue(referencedViews, viewName, kCFBooleanFalse);
}
return view;
}
static SOSViewRef SOSViewManangerCopyCompositeViewWithNames(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFArrayRef viewNames, CFErrorRef *error) {
CFStringRef compositeName = CFStringCreateWithViewNames(viewNames);
SOSViewRef compositeView = (SOSViewRef)CFDictionaryGetValue(vmgr->views, compositeName);
if (compositeView) {
CFDictionarySetValue(referencedViews, compositeName, kCFBooleanTrue);
CFRetain(compositeView);
} else {
compositeView = SOSViewCreate(CFGetAllocator(vmgr), true, NULL, error);
if (compositeView) {
CFStringRef viewName;
CFArrayForEachC(viewNames, viewName) {
SOSViewRef parent = SOSViewManangerCopyViewWithName(vmgr, referencedViews, viewName, false, error);
if (!parent) {
CFReleaseNull(compositeView);
break;
}
SOSViewAddChild(parent, compositeView);
SOSManifestRef pmf = SOSViewCopyManifest(parent, error);
SOSViewUpdateManifest(compositeView, kSOSDataSourceSOSTransaction, NULL, pmf, error);
CFReleaseSafe(pmf);
}
CFDictionarySetValue(vmgr->views, viewName, compositeView);
}
}
CFReleaseSafe(compositeName);
return compositeView;
}
static bool SOSViewManangerAddChildWithInfo(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFDictionaryRef childInfo, CFErrorRef *error) {
CFArrayRef viewNames = (CFArrayRef)CFDictionaryGetValue(childInfo, kSOSViewNamesChildInfoKey);
CFIndex count = CFArrayGetCount(viewNames);
if (count == 1) {
CFStringRef key = CFArrayGetValueAtIndex(viewNames, 0);
SOSViewRef view = SOSViewManangerCopyViewWithName(vmgr, referencedViews, key, true, error);
if (view) count++; } else if (count > 1) {
SOSViewRef view = SOSViewManangerCopyCompositeViewWithNames(vmgr, referencedViews, viewNames, error);
if (view) count++; }
return true;
}
struct SOSViewManagerContext {
SOSViewManagerRef vmgr;
CFDictionaryRef referencedViews;
};
static void SOSViewManagerUpdateView(const void *key, const void *value, void *context) {
struct SOSViewManagerContext *vmc = context;
CFBooleanRef isConcrete = CFDictionaryGetValue(vmc->referencedViews, key);
if (!isConcrete) {
CFDictionaryRemoveValue(vmc->vmgr->views, key);
} else if (CFBooleanGetValue(isConcrete) == 0) {
SOSViewRef view = (SOSViewRef)CFDictionaryGetValue(vmc->vmgr->views, key);
SOSViewSetConcrete(view, false);
}
}
bool SOSViewManagerSetChildren(SOSViewManagerRef vmgr, CFArrayRef children, CFErrorRef *error) {
bool ok = true;
CFMutableDictionaryRef referencedViews = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault);
CFDictionaryRef childInfo;
CFArrayForEachC(children, childInfo) {
ok &= SOSViewManangerAddChildWithInfo(vmgr, referencedViews, childInfo, error);
}
struct SOSViewManagerContext vmc = {
.vmgr = vmgr,
.referencedViews = referencedViews,
};
CFDictionaryApplyFunction(vmgr->views, SOSViewManagerUpdateView, &vmc);
CFRetainSafe(referencedViews);
return ok;
}
#endif