#include <security_utilities/cfclass.h>
#include <security_utilities/seccfobject.h>
#include <security_utilities/threading.h>
CFClass::CFClass(const char *name, CFAllocator *anAllocator)
{
if (anAllocator)
{
allocator = anAllocator->allocator;
finalize = NULL;
}
else
{
allocator = NULL;
finalize = finalizeType;
}
version = 0;
className = name;
init = NULL;
copy = NULL;
equal = equalType;
hash = hashType;
copyFormattingDesc = copyFormattingDescType;
copyDebugDesc = copyDebugDescType;
typeID = _CFRuntimeRegisterClass(this);
assert(typeID != _kCFRuntimeNotATypeID);
}
void
CFClass::finalizeType(CFTypeRef cf) throw()
{
SecCFObject *obj = SecCFObject::optional(cf);
if (!obj->isNew())
{
try {
obj->~SecCFObject();
} catch (...) {}
}
}
Boolean
CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2) throw()
{
return SecCFObject::optional(cf1)->equal(*SecCFObject::optional(cf2));
}
CFHashCode
CFClass::hashType(CFTypeRef cf) throw()
{
return SecCFObject::optional(cf)->hash();
}
CFStringRef
CFClass::copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict) throw()
{
return SecCFObject::optional(cf)->copyFormattingDesc(dict);
}
CFStringRef
CFClass::copyDebugDescType(CFTypeRef cf) throw()
{
return SecCFObject::optional(cf)->copyDebugDesc();
}
CFAllocator::CFAllocator(Mutex &lock) :
mLock(lock)
{
mContext.version = 0;
mContext.info = this;
mContext.retain = NULL;
mContext.release = NULL;
mContext.copyDescription = NULL;
mContext.allocate = allocate;
mContext.reallocate = reallocate;
mContext.deallocate = deallocate;
mContext.preferredSize = preferredSize;
allocator = CFAllocatorCreate(NULL, &mContext);
}
void *
CFAllocator::allocate(CFIndex allocSize, CFOptionFlags hint, void *info) throw()
{
return malloc(allocSize);
}
void *
CFAllocator::reallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info) throw()
{
return realloc(ptr, newsize);
}
void
CFAllocator::deallocate(void *ptr, void *info) throw()
{
CFAllocator &allocator = *reinterpret_cast<CFAllocator *>(info);
CFTypeRef cf = reinterpret_cast<CFTypeRef>(reinterpret_cast<intptr_t>(ptr) + sizeof(CFAllocatorRef));
allocator.mLock.lock();
CFIndex rc = CFGetRetainCount(cf);
if (rc == 1)
{
CFClass::finalizeType(cf);
allocator.mLock.unlock();
free(ptr);
}
else
{
allocator.mLock.unlock();
CFRetain(allocator.allocator);
CFRelease(cf);
}
}
CFIndex
CFAllocator::preferredSize(CFIndex size, CFOptionFlags hint, void *info) throw()
{
return size;
}