#include <security_utilities/seccfobject.h>
#include <security_utilities/cfclass.h>
#include <security_utilities/errors.h>
#include <security_utilities/debugging.h>
#include <list>
#include <security_utilities/globalizer.h>
SecPointerBase::SecPointerBase(const SecPointerBase& p)
{
if (p.ptr)
{
CFRetain(p.ptr->operator CFTypeRef());
}
ptr = p.ptr;
}
SecPointerBase::SecPointerBase(SecCFObject *p)
{
if (p && !p->isNew())
{
CFRetain(p->operator CFTypeRef());
}
ptr = p;
}
SecPointerBase::~SecPointerBase()
{
if (ptr)
{
CFRelease(ptr->operator CFTypeRef());
}
}
SecPointerBase& SecPointerBase::operator = (const SecPointerBase& p)
{
if (p.ptr)
{
CFRetain(p.ptr->operator CFTypeRef());
}
if (ptr)
{
CFRelease(ptr->operator CFTypeRef());
}
ptr = p.ptr;
return *this;
}
void SecPointerBase::assign(SecCFObject * p)
{
if (p && !p->isNew())
{
CFRetain(p->operator CFTypeRef());
}
if (ptr)
{
CFRelease(ptr->operator CFTypeRef());
}
ptr = p;
}
void SecPointerBase::copy(SecCFObject * p)
{
if (ptr)
{
CFRelease(ptr->operator CFTypeRef());
}
ptr = p;
}
typedef std::list<CFTypeRef> DeferredObjectList;
struct DeferredObjectInfo
{
DeferredObjectList objectList;
};
ModuleNexus<DeferredObjectInfo> gDeferredObjects;
SecCFObject *
SecCFObject::optional(CFTypeRef cfTypeRef) throw()
{
if (!cfTypeRef)
return NULL;
return const_cast<SecCFObject *>(reinterpret_cast<const SecCFObject *>(reinterpret_cast<const uint8_t *>(cfTypeRef) + kAlignedRuntimeSize));
}
SecCFObject *
SecCFObject::required(CFTypeRef cfTypeRef, OSStatus error)
{
SecCFObject *object = optional(cfTypeRef);
if (!object)
MacOSError::throwMe(error);
return object;
}
void
SecCFObject::clearDeletedObjects() throw()
{
DeferredObjectList::iterator it;
it = gDeferredObjects().objectList.begin();
while (it != gDeferredObjects().objectList.end())
{
DeferredObjectList::iterator current = it++;
CFTypeRef t = *current;
CFIndex rCount = CFGetRetainCount(t);
if (rCount == 1)
{
CFRelease(t);
gDeferredObjects().objectList.erase(current);
}
}
}
void *
SecCFObject::allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc)
{
CFTypeRef p = _CFRuntimeCreateInstance(NULL, cfclass.typeID,
size + kAlignedRuntimeSize - sizeof(CFRuntimeBase), NULL);
if (p == NULL)
throw std::bad_alloc();
if (cfclass.isDeferrable)
{
gDeferredObjects().objectList.push_front(p);
CFRetain(p);
}
((SecRuntimeBase*) p)->isNew = true;
void *q = ((u_int8_t*) p) + kAlignedRuntimeSize;
#if !defined(NDEBUG)
const CFRuntimeClass *runtimeClass = _CFRuntimeGetClassWithTypeID(cfclass.typeID);
secdebug("sec", "allocated: %p: %s(%lu)", q,
runtimeClass && runtimeClass->className ? runtimeClass->className
: "SecCFObject", cfclass.typeID);
#endif
return q;
}
void
SecCFObject::operator delete(void *object) throw()
{
CFTypeRef cfType = reinterpret_cast<CFTypeRef>(reinterpret_cast<const uint8_t *>(object) - kAlignedRuntimeSize);
CFRelease(cfType);
}
SecCFObject::~SecCFObject()
{
#if !defined(NDEBUG)
CFTypeRef cfType = *this;
CFTypeID typeID = CFGetTypeID(cfType);
const CFRuntimeClass *runtimeClass = _CFRuntimeGetClassWithTypeID(typeID);
secdebug("sec", "destroyed: %p: %s(%lu)", this,
runtimeClass && runtimeClass->className ? runtimeClass->className
: "SecCFObject", typeID);
#endif
}
bool
SecCFObject::equal(SecCFObject &other)
{
return this == &other;
}
CFHashCode
SecCFObject::hash()
{
return CFHashCode(this);
}
CFStringRef
SecCFObject::copyFormattingDesc(CFDictionaryRef dict)
{
return NULL;
}
CFStringRef
SecCFObject::copyDebugDesc()
{
return NULL;
}
CFTypeRef
SecCFObject::handle(bool retain) throw()
{
CFTypeRef cfType = *this;
if (retain && !isNew()) CFRetain(cfType);
return cfType;
}