#include <security_utilities/cfclass.h>
#include <security_utilities/seccfobject.h>
#include <security_utilities/threading.h>
#include <CoreFoundation/CFString.h>
#include <sys/time.h>
#include <auto_zone.h>
#include <objc/objc-auto.h>
CFClass::CFClass(const char *name)
{
version = 0;
className = name;
init = NULL;
copy = NULL;
finalize = finalizeType;
equal = equalType;
hash = hashType;
copyFormattingDesc = copyFormattingDescType;
copyDebugDesc = copyDebugDescType;
version |= _kCFRuntimeCustomRefCount; refcount = refCountForType;
typeID = _CFRuntimeRegisterClass(this);
assert(typeID != _kCFRuntimeNotATypeID);
}
uint32_t
CFClass::cleanupObject(intptr_t op, CFTypeRef cf, bool &zap)
{
zap = false;
bool isGC = CF_IS_COLLECTABLE(cf);
uint32_t currentCount;
SecCFObject *obj = SecCFObject::optional(cf);
uint32_t oldCount;
currentCount = obj->updateRetainCount(op, &oldCount);
if (isGC)
{
auto_zone_t* zone = objc_collectableZone();
if (op == -1 && oldCount == 0)
{
auto_zone_release(zone, (void*) cf);
}
else if (op == 1 && oldCount == 0 && currentCount == 1)
{
auto_zone_retain(zone, (void*) cf);
}
else if (op == -1 && oldCount == 1 && currentCount == 0)
{
obj->aboutToDestruct();
auto_zone_release(zone, (void*) cf);
}
else if (op == 0)
{
return currentCount;
}
return 0;
}
if (op == 0)
{
return currentCount;
}
else if (currentCount == 0)
{
if (obj->mayDelete())
{
finalizeType(cf);
zap = true; return 0;
}
else
{
return currentCount;
}
}
else
{
return 0;
}
}
uint32_t
CFClass::refCountForType(intptr_t op, CFTypeRef cf) throw()
{
uint32_t result = 0;
bool zap = false;
try
{
SecCFObject *obj = SecCFObject::optional(cf);
Mutex* mutex = obj->getMutexForObject();
if (mutex == NULL)
{
result = cleanupObject(op, cf, zap);
}
else
{
StLock<Mutex> _(*mutex);
result = cleanupObject(op, cf, zap);
}
if (zap) {
delete obj; }
}
catch (...)
{
}
return result;
}
void
CFClass::finalizeType(CFTypeRef cf) throw()
{
SecCFObject *obj = SecCFObject::optional(cf);
bool isCollectable = CF_IS_COLLECTABLE(cf);
try
{
Mutex* mutex = obj->getMutexForObject();
if (mutex == NULL)
{
obj->aboutToDestruct(); }
else
{
StLock<Mutex> _(*mutex);
if (obj->isNew())
{
obj->aboutToDestruct(); return;
}
obj->aboutToDestruct(); }
}
catch(...)
{
}
if (isCollectable)
{
delete obj;
}
}
Boolean
CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) throw()
{
try {
return SecCFObject::optional(cf1)->equal(*SecCFObject::optional(cf2));
} catch (...) {
return false;
}
}
CFHashCode
CFClass::hashType(CFTypeRef cf) throw()
{
try {
return SecCFObject::optional(cf)->hash();
} catch (...) {
return 666;
}
}
CFStringRef
CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw()
{
try {
return SecCFObject::optional(cf)->copyFormattingDesc(dict);
} catch (...) {
return CFSTR("Exception thrown trying to format object");
}
}
CFStringRef
CFClass::copyDebugDescType(CFTypeRef cf) throw()
{
try {
return SecCFObject::optional(cf)->copyDebugDesc();
} catch (...) {
return CFSTR("Exception thrown trying to format object");
}
}