#include "IrIASService.h"
#include "CListIterator.h"
#include "CBuffer.h"
#include "IrDALog.h"
#if (hasTracing > 0 && hasIASServiceTracing > 0)
enum tracecodes {
kLogServiceNew = 1,
kLogServiceFree,
kLogClassNew,
kLogClassFree,
kLogAttrNew,
kLogAttrFree,
kLogNamedListFree,
kLogElementNew,
kLogElementFree
};
static
EventTraceCauseDesc TraceEvents[] = {
{kLogServiceNew, "IrService: service new, obj="},
{kLogServiceFree, "IrService: service free, obj="},
{kLogClassNew, "IrService: class new, obj="},
{kLogClassFree, "IrService: class free, obj="},
{kLogAttrNew, "IrService: attr new, obj="},
{kLogAttrFree, "IrService: attr free, obj="},
{kLogNamedListFree, "IrService: named list free, obj="},
{kLogElementNew, "IrService: element new, obj="},
{kLogElementFree, "IrService: element free, obj="}
};
#define XTRACE(x, y, z) IrDALogAdd( x, y, z, TraceEvents, true )
#else
#define XTRACE(x, y, z) ((void)0)
#endif
#pragma mark
#define super TIASNamedList
OSDefineMetaClassAndStructors(TIASService, TIASNamedList);
TIASService *
TIASService::tIASService(void)
{
TIASService *obj = new TIASService;
XTRACE(kLogServiceNew, (int)obj >> 16, (short)obj);
if (obj && !obj->Init()) { obj->release();
obj = nil;
}
return obj;
}
void TIASService::free()
{
long index;
XTRACE(kLogServiceFree, (int)this >> 16, (short)this);
for (index = 0; index < this->GetArraySize(); index++) {
TIASClass* theClass = (TIASClass*)this->At(index);
theClass->release();
}
super::free();
}
IrDAErr TIASService::AddIntegerEntry(const UChar* className, const UChar* attributeName, ULong intValue)
{
TIASElement* theEntry;
theEntry = TIASElement::tIASElement(intValue); require(theEntry, Fail_Element_New);
return AddAttributeEntry(className, attributeName, theEntry);
Fail_Element_New:
return kIrDAErrNoMemory;
}
IrDAErr TIASService::AddStringEntry(const UChar* className, const UChar* attributeName,
const UChar* stringValue, const UChar charSet, const ULong length)
{
TIASElement *theEntry;
theEntry = TIASElement::tIASElement(stringValue, charSet, length); require(theEntry, Fail_Element_New);
return AddAttributeEntry(className, attributeName, theEntry);
Fail_Element_New:
return kIrDAErrNoMemory;
}
IrDAErr TIASService::AddNBytesEntry(const UChar* className, const UChar* attributeName, const UChar* aFewBytes, ULong length)
{
TIASElement* theEntry;
theEntry = TIASElement::tIASElement(aFewBytes, length); require(theEntry, Fail_Element_New);
return AddAttributeEntry(className, attributeName, theEntry);
Fail_Element_New:
return kIrDAErrNoMemory;
}
IrDAErr TIASService::AddAttributeEntry(const UChar* className, const UChar* attributeName, TIASElement* theEntry)
{
IrDAErr result = kIrDAErrNoMemory;
ULong flags;
TIASAttribute *theAttr;
theAttr = AddAttribute(className, attributeName, flags);
XREQUIRE(theAttr, Fail_ClassAttr_New);
result = theAttr->Insert(theEntry);
XREQUIRENOT(result, Fail_Entry_Insert);
return noErr;
Fail_Entry_Insert:
RemoveAttribute(className, attributeName, flags);
Fail_ClassAttr_New:
theEntry->release();
return result;
}
TIASAttribute* TIASService::AddAttribute(const UChar* className, const UChar* attributeName, ULong& flags)
{
IrDAErr result;
TIASClass* theClass;
TIASAttribute* theAttr;
theClass = AddClass(className, flags);
XREQUIRE(theClass, Fail_Class_New);
theAttr = theClass->FindAttribute(attributeName);
if (theAttr != nil) {
return theAttr;
}
theAttr = TIASAttribute::tIASAttribute(attributeName);
require(theAttr, Fail_Attribute_New);
result = theClass->Insert(theAttr);
XREQUIRENOT(result, Fail_Attribute_Insert);
flags |= kIASAddedAttribute;
return theAttr;
Fail_Attribute_Insert:
theAttr->release();
Fail_Attribute_New:
RemoveClass(className, flags);
Fail_Class_New:
return nil;
}
TIASClass* TIASService::AddClass(const UChar* className, ULong& flags)
{
IrDAErr result;
TIASClass *theClass;
flags = 0;
theClass = FindClass(className);
if (theClass != nil) {
return theClass;
}
theClass = TIASClass::tIASClass(className);
require(theClass, Fail_Class_New);
result = this->Insert(theClass);
XREQUIRENOT(result, Fail_Class_Insert);
flags |= kIASAddedClass;
return theClass;
Fail_Class_Insert:
theClass->release();
Fail_Class_New:
return nil;
}
IrDAErr TIASService::RemoveClass(const UChar* className, ULong flags)
{
TIASClass *theClass;
theClass = FindClass(className);
if (theClass && (flags & kIASDeleteClass)) {
this->Remove(theClass);
theClass->release();
}
return noErr;
}
IrDAErr TIASService::RemoveAttribute(const UChar* className, const UChar* attributeName, ULong flags)
{
TIASClass* theClass;
TIASAttribute* theAttr;
theClass = FindClass(className);
if (theClass) {
theAttr = theClass->FindAttribute(attributeName);
if (theAttr && (flags & kIASDeleteAttribute)) {
theClass->Remove(theAttr);
theAttr->release();
}
if (flags & kIASDeleteClass) {
this->Remove(theClass);
theClass->release();
}
}
return noErr;
}
TIASClass* TIASService::FindClass(const UChar* className)
{
return (TIASClass*)this->Search(className);
}
TIASAttribute* TIASService::FindAttribute(const UChar* className, const UChar* attributeName)
{
TIASClass* theClass;
TIASAttribute* theAttr = nil;
theClass = FindClass(className);
if (theClass) {
theAttr = theClass->FindAttribute(attributeName);
}
return theAttr;
}
#pragma mark
#undef super
#define super TIASNamedList
OSDefineMetaClassAndStructors(TIASClass, TIASNamedList);
TIASClass *
TIASClass::tIASClass(const UChar *name)
{
TIASClass *obj = new TIASClass;
XTRACE(kLogClassNew, (int)obj >> 16, (short)obj);
if (obj && !obj->Init(name)) {
obj->release();
obj = nil;
}
return obj;
}
void TIASClass::free()
{
long index;
XTRACE(kLogClassFree, (int)this >> 16, (short)this);
for (index = 0; index < this->GetArraySize(); index++) {
TIASAttribute* theAttr = (TIASAttribute*)this->At(index);
theAttr->release();
}
super::free();
}
IrDAErr TIASClass::Insert(TIASAttribute* attribute)
{
return CList::Insert((void*)attribute);
}
TIASAttribute* TIASClass::FindAttribute(const UChar* attributeName)
{
return (TIASAttribute*)this->Search(attributeName);
}
#pragma mark
#undef super
#define super TIASNamedList
OSDefineMetaClassAndStructors(TIASAttribute, TIASNamedList);
TIASAttribute *
TIASAttribute::tIASAttribute(const UChar *name)
{
TIASAttribute *obj = new TIASAttribute;
XTRACE(kLogAttrNew, (int)obj >> 16, (short)obj);
if (obj && !obj->Init(name)) {
obj->release();
obj = nil;
}
return obj;
}
TIASAttribute *
TIASAttribute::tIASAttribute(CBuffer *buffer)
{
TIASAttribute *obj = new TIASAttribute;
XTRACE(kLogAttrNew, (int)obj >> 16, (short)obj);
if (obj && !obj->InitFromBuffer(buffer)) {
obj->release();
obj = nil;
}
return obj;
}
void TIASAttribute::free()
{
long index;
XTRACE(kLogAttrFree, (int)this >> 16, (short)this);
for (index = 0; index < this->GetArraySize(); index++) {
TIASElement* theElement = (TIASElement*)this->At(index);
theElement->release();
}
super::free();
}
IrDAErr TIASAttribute::Insert(TIASElement* element)
{
return CList::Insert((void*)element);
}
void TIASAttribute::AddInfoToBuffer(CBuffer* buffer)
{
long index;
ULong arraySize = this->GetArraySize();
buffer->Put((int)((arraySize >> 8) & 0xFF)); buffer->Put((int)((arraySize >> 0) & 0xFF));
for (index = 0; index < this->GetArraySize(); index++) {
TIASElement* theElement = (TIASElement*)this->At(index);
theElement->AddInfoToBuffer(buffer);
}
}
Boolean TIASAttribute::InitFromBuffer(CBuffer* buffer)
{
ULong entryIndex;
ULong listLength;
UByte listLenBuf[2]; TIASElement* element;
if (!super::Init()) return false;
if (buffer->Getn(listLenBuf, sizeof(listLenBuf)) != sizeof(listLenBuf)) {
return false;
}
listLength = (ULong)(listLenBuf[0] * 256) + (ULong)listLenBuf[1];
for (entryIndex = 0; entryIndex < listLength; entryIndex++) {
IrDAErr result;
element = TIASElement::tIASElement(buffer);
require(element, Fail);
result = this->Insert(element);
if (result != noErr) {
element->release();
return false;
}
}
return true;
Fail:
return false;
}
#pragma mark
#undef super
#define super CList
OSDefineMetaClassAndStructors(TIASNamedList, CList);
void TIASNamedList::free()
{
XTRACE(kLogNamedListFree, (int)this >> 16, (short)this);
if (fName != nil) {
IOFree(fName, fNameLen);
fName = nil;
}
super::free();
}
Boolean TIASNamedList::Init(const UChar *theName)
{
fName = nil;
if (!super::init()) return false;
fNameLen = strlen((const char*)theName) + 1;
if (fNameLen) {
fName = (UChar*)IOMalloc(strlen((const char*)theName) + 1);
require(fName, Fail);
}
strcpy((char*)fName, (const char*)theName);
return true;
Fail:
return false;
}
Boolean TIASNamedList::Init(void)
{
fName = nil;
return super::init();
}
void* TIASNamedList::Search(const UChar* matchName)
{
CListIterator *iter = CListIterator::cListIterator(this);
TIASNamedList* item;
void* result = nil;
int review_consider_putting_in_dynamic_cast;
for (item = (TIASNamedList*)iter->FirstItem(); iter->More(); item = (TIASNamedList*)iter->NextItem()) {
if (strcmp((const char*)(item->fName), (const char*)matchName) == 0) {
result = (void*)item;
break;
}
}
iter->release();
return result;
}
#pragma mark
#undef super
#define super OSObject
OSDefineMetaClassAndStructors(TIASElement, OSObject);
TIASElement * TIASElement::tIASElement(ULong theValue)
{
TIASElement *obj = new TIASElement;
XTRACE(kLogElementNew, (int)obj >> 16, (short)obj);
if (obj && !obj->init_with_long(theValue)) {
obj->release();
obj = nil;
}
return obj;
}
TIASElement * TIASElement::tIASElement(const UChar* theBytes, ULong length)
{
TIASElement *obj = new TIASElement;
XTRACE(kLogElementNew, (int)obj >> 16, (short)obj);
if (obj && !obj->init_with_nbytes(theBytes, length)) {
obj->release();
obj = nil;
}
return obj;
}
TIASElement * TIASElement::tIASElement(const UChar* theString, UChar charSet, ULong length)
{
TIASElement *obj = new TIASElement;
XTRACE(kLogElementNew, (int)obj >> 16, (short)obj);
if (obj && !obj->init_with_string(theString, charSet, length)) {
obj->release();
obj = nil;
}
return obj;
}
TIASElement * TIASElement::tIASElement(CBuffer* buffer)
{
TIASElement *obj = new TIASElement;
XTRACE(kLogElementNew, (int)obj >> 16, (short)obj);
if (obj && !obj->init_with_buffer(buffer)) {
obj->release();
obj = nil;
}
return obj;
}
void TIASElement::free()
{
int len;
XTRACE(kLogElementFree, (int)this >> 16, (short)this);
if (nameOrBytes && (nameOrBytes != (UByte*)&valueOrBytes)) { len = length;
if (type == kIASValueString) len += 2;
IOFree(nameOrBytes, len);
nameOrBytes = nil;
}
super::free();
}
Boolean TIASElement::init_with_long(ULong theValue)
{
type = kIASValueMissing;
length = 0;
valueOrBytes = 0;
nameOrBytes = nil;
characterSet = kIASCharSetAscii;
if (!super::init()) return false;
return SetInteger(theValue);
}
Boolean TIASElement::init_with_nbytes(const UChar* theBytes, ULong length)
{
type = kIASValueMissing;
length = 0;
valueOrBytes = 0;
nameOrBytes = nil;
characterSet = kIASCharSetAscii;
if (!super::init()) return false;
return SetNBytes(theBytes, length);
}
Boolean TIASElement::init_with_string(const UChar* theString, UChar charSet, ULong length)
{
type = kIASValueMissing;
length = 0;
valueOrBytes = 0;
nameOrBytes = nil;
characterSet = kIASCharSetAscii;
if (!super::init()) return false;
return SetString(theString, charSet, length);
}
Boolean TIASElement::init_with_buffer(CBuffer* buffer)
{
type = kIASValueMissing;
length = 0;
valueOrBytes = 0;
nameOrBytes = nil;
characterSet = kIASCharSetAscii;
if (!super::init()) return false;
return ExtractInfoFromBuffer(buffer);
}
Boolean TIASElement::SetInteger(ULong theValue)
{
type = kIASValueInteger;
length = 4;
valueOrBytes = theValue;
nameOrBytes = (UByte*)&valueOrBytes;
return true;
}
Boolean TIASElement::SetNBytes(const UChar * theBytes, ULong theBytesLength)
{
type = kIASValueNBytes;
length = theBytesLength;
nameOrBytes = (UByte*)IOMalloc(length);
require(nameOrBytes, Fail);
BlockMove(theBytes, nameOrBytes, length);
return true;
Fail:
return false;
}
Boolean TIASElement::SetString(const UChar* theString, const UChar charSet, const ULong len)
{
type = kIASValueString;
if (charSet != kIASCharSetUniCode) length = (ULong)strlen((const char*)theString);
else
length = len;
valueOrBytes = 0;
characterSet = charSet;
nameOrBytes = (UByte*)IOMalloc((unsigned int)(length+2));
require(nameOrBytes, Fail);
BlockMove(theString, nameOrBytes, length); nameOrBytes[length] = 0;
nameOrBytes[length+1] = 0;
return true;
Fail:
return false;
}
IrDAErr TIASElement::GetInteger(ULong *theValue)
{
if (type != kIASValueInteger) {
return kIrDAErrGeneric; }
*theValue = valueOrBytes;
return noErr;
}
IrDAErr TIASElement::GetNBytes(UByte **theBytes, ULong *theLength)
{
if (type != kIASValueNBytes) {
return kIrDAErrGeneric; }
*theBytes = nameOrBytes; *theLength = length;
return noErr;
}
IrDAErr TIASElement::GetString(UByte **theString, UByte *charSet, ULong *len)
{
if (type != kIASValueString) {
return kIrDAErrGeneric; }
*theString = nameOrBytes;
if (charSet != nil) *charSet = characterSet;
if (len != nil) *len = length;
return noErr;
}
void TIASElement::AddInfoToBuffer(CBuffer* buffer)
{
UByte header[5];
UByte* pHdr = &header[0];
*pHdr++ = 0;
*pHdr++ = 0;
*pHdr++ = type;
XASSERT(length < 256);
if (type == kIASValueNBytes) {
*pHdr++ = 0; *pHdr++ = (UByte)length; }
else if (type == kIASValueString) {
*pHdr++ = characterSet; *pHdr++ = (UByte)length; }
buffer->Putn(header, pHdr - header);
buffer->Putn(nameOrBytes, length);
}
Boolean TIASElement::ExtractInfoFromBuffer(CBuffer* buffer)
{
UByte entryHeader[3]; UByte lengthInfo[2]; UByte charSet; ULong length;
ULong intValue;
Boolean rc;
unsigned char buf[1024];
if (buffer->Getn(entryHeader, sizeof(entryHeader)) != sizeof(entryHeader)) {
return false;
}
switch(entryHeader[2] ) {
case kIASValueMissing:
rc = true;
break;
case kIASValueInteger:
if (buffer->Getn((UByte*)&intValue, sizeof(intValue)) != sizeof(intValue)) {
return kIrDAErrGeneric; }
rc = SetInteger(intValue);
break;
case kIASValueNBytes:
if (buffer->Getn(lengthInfo, sizeof(lengthInfo)) != sizeof(lengthInfo)) {
return false;
}
length = lengthInfo[0] << 8 | lengthInfo[1]; check(length <= 1024); check(length <= sizeof(buf)); if ((UInt32)buffer->Getn(buf, length) != length)
return false;
rc = SetNBytes(buf, length);
break;
case kIASValueString:
if (buffer->Getn(lengthInfo, sizeof(lengthInfo)) != sizeof(lengthInfo)) {
return kIrDAErrGeneric; }
charSet = lengthInfo[0]; length = lengthInfo[1]; if ((UInt32)buffer->Getn(buf, length) != length)
return false;
buf[length] = 0; rc = SetString(buf, charSet, length); break;
default:
rc = false;
break;
}
return rc;
}