#include <sys/cdefs.h>
__BEGIN_DECLS
#include <vm/vm_kern.h>
__END_DECLS
#include <libkern/c++/OSContainers.h>
#include <libkern/c++/OSLib.h>
#include <libkern/c++/OSDictionary.h>
#include <libkern/OSSerializeBinary.h>
#include <IOKit/IOLib.h>
#define super OSObject
OSDefineMetaClassAndStructors(OSSerialize, OSObject)
OSMetaClassDefineReservedUnused(OSSerialize, 0);
OSMetaClassDefineReservedUnused(OSSerialize, 1);
OSMetaClassDefineReservedUnused(OSSerialize, 2);
OSMetaClassDefineReservedUnused(OSSerialize, 3);
OSMetaClassDefineReservedUnused(OSSerialize, 4);
OSMetaClassDefineReservedUnused(OSSerialize, 5);
OSMetaClassDefineReservedUnused(OSSerialize, 6);
OSMetaClassDefineReservedUnused(OSSerialize, 7);
char * OSSerialize::text() const
{
return data;
}
void OSSerialize::clearText()
{
if (binary)
{
length = sizeof(kOSSerializeBinarySignature);
bzero(&data[length], capacity - length);
endCollection = true;
}
else
{
bzero((void *)data, capacity);
length = 1;
}
tag = 0;
tags->flushCollection();
}
bool OSSerialize::previouslySerialized(const OSMetaClassBase *o)
{
char temp[16];
OSString *tagString;
if (binary) return (binarySerialize(o));
tagString = (OSString *)tags->getObject((const OSSymbol *) o);
if (tagString) {
addString("<reference IDREF=\"");
addString(tagString->getCStringNoCopy());
addString("\"/>");
return true;
}
snprintf(temp, sizeof(temp), "%u", tag++);
tagString = OSString::withCString(temp);
tags->setObject((const OSSymbol *) o, tagString); tagString->release();
return false;
}
bool OSSerialize::addXMLStartTag(const OSMetaClassBase *o, const char *tagString)
{
if (binary)
{
printf("class %s: xml serialize\n", o->getMetaClass()->getClassName());
return (false);
}
if (!addChar('<')) return false;
if (!addString(tagString)) return false;
if (!addString(" ID=\"")) return false;
if (!addString(((OSString *)tags->getObject((const OSSymbol *)o))->getCStringNoCopy()))
return false;
if (!addChar('\"')) return false;
if (!addChar('>')) return false;
return true;
}
bool OSSerialize::addXMLEndTag(const char *tagString)
{
if (!addChar('<')) return false;
if (!addChar('/')) return false;
if (!addString(tagString)) return false;
if (!addChar('>')) return false;
return true;
}
bool OSSerialize::addChar(const char c)
{
if (binary)
{
printf("xml serialize\n");
return (false);
}
if (length >= capacity && length >=ensureCapacity(capacity+capacityIncrement))
return false;
data[length - 1] = c;
length++;
return true;
}
bool OSSerialize::addString(const char *s)
{
bool rc = false;
while (*s && (rc = addChar(*s++))) ;
return rc;
}
bool OSSerialize::initWithCapacity(unsigned int inCapacity)
{
if (!super::init())
return false;
tags = OSDictionary::withCapacity(32);
if (!tags) {
return false;
}
tag = 0;
length = 1;
capacity = (inCapacity) ? round_page_32(inCapacity) : round_page_32(1);
capacityIncrement = capacity;
kern_return_t rc = kmem_alloc(kernel_map, (vm_offset_t *)&data, capacity, IOMemoryTag(kernel_map));
if (rc) {
tags->release();
tags = 0;
return false;
}
bzero((void *)data, capacity);
OSCONTAINER_ACCUMSIZE(capacity);
return true;
}
OSSerialize *OSSerialize::withCapacity(unsigned int inCapacity)
{
OSSerialize *me = new OSSerialize;
if (me && !me->initWithCapacity(inCapacity)) {
me->release();
return 0;
}
return me;
}
unsigned int OSSerialize::getLength() const { return length; }
unsigned int OSSerialize::getCapacity() const { return capacity; }
unsigned int OSSerialize::getCapacityIncrement() const { return capacityIncrement; }
unsigned int OSSerialize::setCapacityIncrement(unsigned int increment)
{
capacityIncrement = (increment)? increment : 256;
return capacityIncrement;
}
unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity)
{
char *newData;
if (newCapacity <= capacity)
return capacity;
newCapacity = round_page_32(newCapacity);
kern_return_t rc = kmem_realloc(kernel_map,
(vm_offset_t)data,
capacity,
(vm_offset_t *)&newData,
newCapacity,
VM_KERN_MEMORY_IOKIT);
if (!rc) {
OSCONTAINER_ACCUMSIZE(newCapacity);
kmem_free(kernel_map, (vm_offset_t)data, capacity);
OSCONTAINER_ACCUMSIZE(-((size_t)capacity));
bzero(&newData[capacity], newCapacity - capacity);
data = newData;
capacity = newCapacity;
}
return capacity;
}
void OSSerialize::free()
{
if (tags)
tags->release();
if (data) {
kmem_free(kernel_map, (vm_offset_t)data, capacity);
OSCONTAINER_ACCUMSIZE( -((size_t)capacity) );
}
super::free();
}
OSDefineMetaClassAndStructors(OSSerializer, OSObject)
OSSerializer * OSSerializer::forTarget( void * target,
OSSerializerCallback callback, void * ref )
{
OSSerializer * thing;
thing = new OSSerializer;
if( thing && !thing->init()) {
thing->release();
thing = 0;
}
if( thing) {
thing->target = target;
thing->ref = ref;
thing->callback = callback;
}
return( thing );
}
bool OSSerializer::serialize( OSSerialize * s ) const
{
return( (*callback)(target, ref, s) );
}