cmData.h/c : Initial implementation of serialization functions.

Not yet tested.
This commit is contained in:
kpl 2013-10-21 22:17:24 -07:00
parent c1289070d2
commit 341bde7a7c
2 changed files with 183 additions and 63 deletions

194
cmData.c
View File

@ -10,12 +10,6 @@ cmDtRC_t _cmDataErrNo = kOkDtRC;
cmData_t cmDataNull = { kInvalidDtId,0,NULL,NULL,0 }; cmData_t cmDataNull = { kInvalidDtId,0,NULL,NULL,0 };
typedef struct
{
cmDataFmtId_t tid;
unsigned cnt;
} cmDataSerialHdr_t;
cmDtRC_t _cmDataSetError( unsigned err ) cmDtRC_t _cmDataSetError( unsigned err )
{ {
_cmDataErrNo = err; _cmDataErrNo = err;
@ -62,7 +56,7 @@ cmData_t* _cmDataAllocNode( cmData_t* parent, cmDataFmtId_t tid )
unsigned _cmDataByteCount( const cmData_t* p ) unsigned _cmDataByteCount( const cmData_t* p )
{ {
unsigned n = sizeof(cmDataSerialHdr_t); unsigned n = 0;
switch( p->tid ) switch( p->tid )
{ {
@ -1866,7 +1860,7 @@ cmData_t* cmDataRecdAllocIdA( cmData_t* parent, ... )
return p; return p;
} }
cmDtRC_t _cmDataRecdParseV(cmData_t* p, bool idFl, cmErr_t* err, va_list vl ) cmDtRC_t _cmDataRecdParseV(cmData_t* p, bool idFl, cmErr_t* err, unsigned errRC, va_list vl )
{ {
bool contFl = true; bool contFl = true;
cmDtRC_t rc = kOkDtRC; cmDtRC_t rc = kOkDtRC;
@ -1889,148 +1883,178 @@ cmDtRC_t _cmDataRecdParseV(cmData_t* p, bool idFl, cmErr_t* err, va_list vl )
cmDataFmtId_t typeId = va_arg(vl,unsigned); cmDataFmtId_t typeId = va_arg(vl,unsigned);
void* v = va_arg(vl,void*); void* v = va_arg(vl,void*);
cmData_t* np = NULL; cmData_t* np = NULL;
bool optFl = cmIsFlag(typeId,kOptArgDtFl);
cmDtRC_t rc0 = kOkDtRC;
typeId = cmClrFlag(typeId,kOptArgDtFl);
if( idFl ) if( idFl )
np = cmDataRecdValueFromLabel( p, label ); np = cmDataRecdValueFromLabel( p, label );
else else
np = cmDataRecdValueFromId( p, id ); np = cmDataRecdValueFromId( p, id );
// if the field was not found
if( np == NULL )
{
if(optFl)
continue;
if( err != NULL )
{
if( idFl )
cmErrMsg(err,errRC,"The required field (id=%i) was not found.",id);
else
cmErrMsg(err,errRC,"The required field '%s' was not found.",cmStringNullGuard(label));
}
rc = kMissingFieldDtRC;
}
switch(typeId) switch(typeId)
{ {
case kNullDtId: case kNullDtId:
break; break;
case kUCharDtId: case kUCharDtId:
rc = cmDataGetUChar(np,(unsigned char*)v); rc0 = cmDataGetUChar(np,(unsigned char*)v);
break; break;
case kCharDtId: case kCharDtId:
rc = cmDataGetChar(np,(char*)v); rc0 = cmDataGetChar(np,(char*)v);
break; break;
case kUShortDtId: case kUShortDtId:
rc = cmDataGetUShort(np,(unsigned short*)v); rc0 = cmDataGetUShort(np,(unsigned short*)v);
break; break;
case kShortDtId: case kShortDtId:
rc = cmDataGetShort(np,(short*)v); rc0 = cmDataGetShort(np,(short*)v);
break; break;
case kUIntDtId: case kUIntDtId:
rc = cmDataGetUInt(np,(unsigned int*)v); rc0 = cmDataGetUInt(np,(unsigned int*)v);
break; break;
case kIntDtId: case kIntDtId:
rc = cmDataGetInt(np,(int*)v); rc0 = cmDataGetInt(np,(int*)v);
break; break;
case kULongDtId: case kULongDtId:
rc = cmDataGetULong(np,(unsigned long*)v); rc0 = cmDataGetULong(np,(unsigned long*)v);
break; break;
case kLongDtId: case kLongDtId:
rc = cmDataGetLong(np,(long*)v); rc0 = cmDataGetLong(np,(long*)v);
break; break;
case kFloatDtId: case kFloatDtId:
rc = cmDataGetFloat(np,(float*)v); rc0 = cmDataGetFloat(np,(float*)v);
break; break;
case kDoubleDtId: case kDoubleDtId:
rc = cmDataGetDouble(np,(double*)v); rc0 = cmDataGetDouble(np,(double*)v);
break; break;
case kStrDtId: case kStrDtId:
rc = cmDataGetStr(np,(char**)v); rc0 = cmDataGetStr(np,(char**)v);
break; break;
case kConstStrDtId: case kConstStrDtId:
rc = cmDataGetConstStr(np,(const char**)v); rc0 = cmDataGetConstStr(np,(const char**)v);
break; break;
case kUCharPtrDtId: case kUCharPtrDtId:
rc = cmDataGetUCharPtr(np,(unsigned char**)v); rc0 = cmDataGetUCharPtr(np,(unsigned char**)v);
break; break;
case kCharPtrDtId: case kCharPtrDtId:
rc = cmDataGetCharPtr(np,(char**)v); rc0 = cmDataGetCharPtr(np,(char**)v);
break; break;
case kUShortPtrDtId: case kUShortPtrDtId:
rc = cmDataGetUShortPtr(np,(unsigned short**)v); rc0 = cmDataGetUShortPtr(np,(unsigned short**)v);
break; break;
case kShortPtrDtId: case kShortPtrDtId:
rc = cmDataGetShortPtr(np,(short**)v); rc0 = cmDataGetShortPtr(np,(short**)v);
break; break;
case kUIntPtrDtId: case kUIntPtrDtId:
rc = cmDataGetUIntPtr(np,(unsigned int**)v); rc0 = cmDataGetUIntPtr(np,(unsigned int**)v);
break; break;
case kIntPtrDtId: case kIntPtrDtId:
rc = cmDataGetIntPtr(np,(int**)v); rc0 = cmDataGetIntPtr(np,(int**)v);
break; break;
case kULongPtrDtId: case kULongPtrDtId:
rc = cmDataGetULongPtr(np,(unsigned long**)v); rc0 = cmDataGetULongPtr(np,(unsigned long**)v);
break; break;
case kLongPtrDtId: case kLongPtrDtId:
rc = cmDataGetLongPtr(np,(long**)v); rc0 = cmDataGetLongPtr(np,(long**)v);
break; break;
case kFloatPtrDtId: case kFloatPtrDtId:
rc = cmDataGetFloatPtr(np,(float**)v); rc0 = cmDataGetFloatPtr(np,(float**)v);
break; break;
case kDoublePtrDtId: case kDoublePtrDtId:
rc = cmDataGetDoublePtr(np,(double**)v); rc0 = cmDataGetDoublePtr(np,(double**)v);
break; break;
case kVoidPtrDtId: case kVoidPtrDtId:
rc = cmDataGetVoidPtr(np,(void**)v); rc0 = cmDataGetVoidPtr(np,(void**)v);
break; break;
case kListDtId: case kListDtId:
case kPairDtId: case kPairDtId:
case kRecordDtId: case kRecordDtId:
if( np->tid != typeId ) if( np->tid != typeId )
_cmDataSetError(kCvtErrDtRC); rc0 = _cmDataSetError(kCvtErrDtRC);
else else
*(cmData_t**)v = np; *(cmData_t**)v = np;
break; break;
default: default:
_cmDataSetError(kVarArgErrDtRC); rc0 = _cmDataSetError(kVarArgErrDtRC);
assert(0); assert(0);
} }
if( rc0 != kOkDtRC && err!=NULL)
{
if( idFl )
cmErrMsg(err,errRC,"Unable to convert field (id=%i) to requested type.",id);
else
cmErrMsg(err,errRC,"Unable to convert field '%s' to requisted type.",cmStringNullGuard(label));
rc = rc0;
}
} }
return rc; return rc;
} }
cmDtRC_t cmDataRecdParseLabelV(cmData_t* p, cmErr_t* err, va_list vl ) cmDtRC_t cmDataRecdParseLabelV(cmData_t* p, cmErr_t* err, unsigned errRC, va_list vl )
{ return _cmDataRecdParseV(p,false,err,vl); } { return _cmDataRecdParseV(p,false,err,errRC,vl); }
cmDtRC_t cmDataRecdParseLabel(cmData_t* p, cmErr_t* err, ... ) cmDtRC_t cmDataRecdParseLabel(cmData_t* p, cmErr_t* err, unsigned errRC, ... )
{ {
va_list vl; va_list vl;
va_start(vl,err); va_start(vl,errRC);
cmDtRC_t rc = cmDataRecdParseLabelV(p,err,vl); cmDtRC_t rc = cmDataRecdParseLabelV(p,err,errRC,vl);
va_end(vl); va_end(vl);
return rc; return rc;
} }
cmDtRC_t cmDataRecdParseIdV(cmData_t* p, cmErr_t* err, va_list vl ) cmDtRC_t cmDataRecdParseIdV(cmData_t* p, cmErr_t* err, unsigned errRC, va_list vl )
{ return _cmDataRecdParseV(p,true,err,vl); } { return _cmDataRecdParseV(p,true,err,errRC,vl); }
cmDtRC_t cmDataRecdParseId(cmData_t* p, cmErr_t* err, ... ) cmDtRC_t cmDataRecdParseId(cmData_t* p, cmErr_t* err, unsigned errRC, ... )
{ {
va_list vl; va_list vl;
va_start(vl,err); va_start(vl,errRC);
cmDtRC_t rc = cmDataRecdParseIdV(p,err,vl); cmDtRC_t rc = cmDataRecdParseIdV(p,err,errRC,vl);
va_end(vl); va_end(vl);
return rc; return rc;
} }
@ -2038,6 +2062,23 @@ cmDtRC_t cmDataRecdParseId(cmData_t* p, cmErr_t* err, ... )
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
unsigned _cmDataSerializeNodeByteCount( const cmData_t* p )
{
unsigned n = 0;
// all serialized data ele's begin with a cmDataFmtId_t
n += sizeof(cmDataFmtId_t);
// arrays then have a count of bytes and structures have a child count
if( cmDataIsPtr(p) || cmDataIsStruct(p) )
n += sizeof(unsigned);
// then the data itself takes a variable number of bytes
n += _cmDataByteCount(p);
return n;
}
unsigned cmDataSerializeByteCount( const cmData_t* p ) unsigned cmDataSerializeByteCount( const cmData_t* p )
{ {
unsigned bn = 0; unsigned bn = 0;
@ -2051,14 +2092,79 @@ unsigned cmDataSerializeByteCount( const cmData_t* p )
for(; dp != NULL; dp=dp->sibling ) for(; dp != NULL; dp=dp->sibling )
bn += cmDataSerializeByteCount(dp->sibling); bn += cmDataSerializeByteCount(dp->sibling);
// //
return _cmDataByteCount(p) + bn; return bn + _cmDataSerializeNodeByteCount(p);
}
char* _cmDataSerializeWriteArray( cmData_t* np, char* dp, const char* ep )
{
unsigned byteCnt = _cmDataByteCount(np);
*((unsigned*)dp) = byteCnt;
dp += sizeof(unsigned);
memcpy(dp,np->u.vp,byteCnt);
dp += byteCnt;
return dp;
}
char* _cmDataSerializeWriteStruct( cmData_t* np, char* dp, const char* ep )
{
*((unsigned*)dp) = cmDataChildCount(np);
dp += sizeof(unsigned);
return dp;
} }
char* _cmDataSerializeWrite( cmData_t* np, char* dp, const char* ep )
{
assert( dp + _cmDataSerializeNodeByteCount(np) <= ep );
*((cmDataFmtId_t*)dp) = np->tid;
dp += sizeof(cmDataFmtId_t);
switch( np->tid )
{
case kNullDtId: break;
case kUCharDtId: *((unsigned char*)dp) = cmDataUChar(np); dp+=sizeof(unsigned char); break;
case kCharDtId: *((char*)dp) = cmDataChar(np); dp+=sizeof(char); break;
case kUShortDtId: *((unsigned short*)dp) = cmDataUShort(np); dp+=sizeof(unsigned short); break;
case kShortDtId: *((short*)dp) = cmDataShort(np); dp+=sizeof(short); break;
case kUIntDtId: *((unsigned int*)dp) = cmDataUInt(np); dp+=sizeof(unsigned int); break;
case kIntDtId: *((int*)dp) = cmDataInt(np); dp+=sizeof(int); break;
case kULongDtId: *((unsigned long*)dp) = cmDataULong(np); dp+=sizeof(unsigned long); break;
case kLongDtId: *((long*)dp) = cmDataLong(np); dp+=sizeof(long); break;
case kFloatDtId: *((float*)dp) = cmDataFloat(np); dp+=sizeof(float); break;
case kDoubleDtId: *((double*)dp) = cmDataDouble(np); dp+=sizeof(double); break;
case kStrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kConstStrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kUCharPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kCharPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kUShortPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kShortPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kUIntPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kIntPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kULongPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kLongPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kFloatPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kDoublePtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kVoidPtrDtId: dp = _cmDataSerializeWriteArray(np,dp,ep); break;
case kListDtId: dp = _cmDataSerializeWriteStruct(np,dp,ep); break;
case kPairDtId: dp = _cmDataSerializeWriteStruct(np,dp,ep); break;
case kRecordDtId: dp = _cmDataSerializeWriteStruct(np,dp,ep); break;
default:
{ assert(0); }
}
return dp;
}
cmDtRC_t cmDataSerialize( const cmData_t* p, void* buf, unsigned bufByteCnt ) cmDtRC_t cmDataSerialize( const cmData_t* p, void* buf, unsigned bufByteCnt )
{ {
return kOkDtRC; return kOkDtRC;
} }

View File

@ -10,6 +10,7 @@ extern "C" {
kOkDtRC = cmOkRC, kOkDtRC = cmOkRC,
kCvtErrDtRC, kCvtErrDtRC,
kVarArgErrDtRC, kVarArgErrDtRC,
kMissingFieldDtRC,
kEolDtRC kEolDtRC
}; };
@ -32,7 +33,6 @@ extern "C" {
kMinValDtId, kMinValDtId,
kNullDtId = kMinValDtId, kNullDtId = kMinValDtId,
kUCharDtId, kUCharDtId,
kCharDtId, kCharDtId,
kUShortDtId, kUShortDtId,
@ -66,8 +66,9 @@ extern "C" {
kListDtId = kMinStructDtId, // children nodes are array elements, cnt=child count kListDtId = kMinStructDtId, // children nodes are array elements, cnt=child count
kPairDtId, // key/value pairs, cnt=2, first child is key, second is value kPairDtId, // key/value pairs, cnt=2, first child is key, second is value
kRecordDtId, // children nodes are pairs, cnt=pair count kRecordDtId, // children nodes are pairs, cnt=pair count
kMaxStructDtId kMaxStructDtId,
kOptArgDtFl = 0x80000000
} cmDataFmtId_t; } cmDataFmtId_t;
enum enum
@ -232,7 +233,9 @@ extern "C" {
cmDtRC_t cmDataGetDoublePtr( const cmData_t* p, double** v ); cmDtRC_t cmDataGetDoublePtr( const cmData_t* p, double** v );
// Set the value of an existing scalar data object. // Set the value and type of an existing scalar object.
// These functions begin by releasing any resources held by *p
// prior to resetting the type and value of the object.
cmData_t* cmDataSetNull( cmData_t* p ); cmData_t* cmDataSetNull( cmData_t* p );
cmData_t* cmDataSetChar( cmData_t* p, char v ); cmData_t* cmDataSetChar( cmData_t* p, char v );
cmData_t* cmDataSetUChar( cmData_t* p, unsigned char v ); cmData_t* cmDataSetUChar( cmData_t* p, unsigned char v );
@ -247,8 +250,10 @@ extern "C" {
cmData_t* cmDataSetStr( cmData_t* p, cmChar_t* s ); cmData_t* cmDataSetStr( cmData_t* p, cmChar_t* s );
cmData_t* cmDataSetConstStr( cmData_t* p, const cmChar_t* s ); cmData_t* cmDataSetConstStr( cmData_t* p, const cmChar_t* s );
// Set the value of an existing data object to an external array. // Set the type and value of an existing data object to an external array.
// 'vp' is assigned as the data space for the object and therefore must remain // These functions begin by releasing any resources help by *p.
// The array pointed to by 'vp' is not copied or duplicated.
// 'vp' is simply assigned as the data space for the object and therefore must remain
// valid for the life of the object. // valid for the life of the object.
cmData_t* cmDataSetVoidPtr( cmData_t* p, void* vp, unsigned cnt ); cmData_t* cmDataSetVoidPtr( cmData_t* p, void* vp, unsigned cnt );
cmData_t* cmDataSetCharPtr( cmData_t* p, char* vp, unsigned cnt ); cmData_t* cmDataSetCharPtr( cmData_t* p, char* vp, unsigned cnt );
@ -263,7 +268,9 @@ extern "C" {
cmData_t* cmDataSetDoublePtr( cmData_t* p, double* vp, unsigned cnt ); cmData_t* cmDataSetDoublePtr( cmData_t* p, double* vp, unsigned cnt );
// Set the value of an existing array based data object. // Set the value of an existing array based data object.
// Dynamically allocate the internal array and copy the array data into it. // These functions begin by releasing any resources help by *p
// and then dynamically allocate the internal array and copy
// the array data into it.
cmData_t* cmDataSetStrAlloc( cmData_t* p, const cmChar_t* s ); cmData_t* cmDataSetStrAlloc( cmData_t* p, const cmChar_t* s );
cmData_t* cmDataSetConstStrAlloc( cmData_t* p, const cmChar_t* s ); cmData_t* cmDataSetConstStrAlloc( cmData_t* p, const cmChar_t* s );
cmData_t* cmDataSetVoidAllocPtr( cmData_t* p, const void* vp, unsigned cnt ); cmData_t* cmDataSetVoidAllocPtr( cmData_t* p, const void* vp, unsigned cnt );
@ -393,7 +400,6 @@ extern "C" {
cmData_t* cmDataPairKey( cmData_t* p ); cmData_t* cmDataPairKey( cmData_t* p );
unsigned cmDataPairKeyId( cmData_t* p ); unsigned cmDataPairKeyId( cmData_t* p );
const cmChar_t* cmDataPairKeyLabel( cmData_t* p ); const cmChar_t* cmDataPairKeyLabel( cmData_t* p );
cmData_t* cmDataPairValue( cmData_t* p ); cmData_t* cmDataPairValue( cmData_t* p );
// Set the value of an existing pair node. // Set the value of an existing pair node.
@ -404,8 +410,7 @@ extern "C" {
cmData_t* cmDataPairSetValue( cmData_t* p, cmData_t* value ); cmData_t* cmDataPairSetValue( cmData_t* p, cmData_t* value );
// Set the key of an existing pair node. // Set the key of an existing pair node.
// // The previous key is unlinked and freed.
// Returns 'p'.
cmData_t* cmDataPairSetKey( cmData_t* p, cmData_t* key ); cmData_t* cmDataPairSetKey( cmData_t* p, cmData_t* key );
cmData_t* cmDataPairSetKeyId( cmData_t* p, unsigned id ); cmData_t* cmDataPairSetKeyId( cmData_t* p, unsigned id );
// The data space for the 'label' string is dynamically allocated. // The data space for the 'label' string is dynamically allocated.
@ -491,10 +496,10 @@ extern "C" {
cmData_t* cmRecdAppendPair( cmData_t* p, cmData_t* pair ); cmData_t* cmRecdAppendPair( cmData_t* p, cmData_t* pair );
// Var-args fmt: // Var-args format:
// <label|id> <typeId> <value> {<cnt>} // <label|id> <typeId> <value> {<cnt>}
// scalar types: <value> is literal,<cnt> is not included // scalar types: <value> is literal,<cnt> is not included
// null type has no <value> or <cnt> // null type: has no <value> or <cnt>
// ptr types: <value> is pointer, <cnt> is element count // ptr types: <value> is pointer, <cnt> is element count
// struct types: <value> is cmData_t, <cnt> is not included // struct types: <value> is cmData_t, <cnt> is not included
// Indicate the end of argument list by setting <typeId> to kInvalidDtId. // Indicate the end of argument list by setting <typeId> to kInvalidDtId.
@ -506,11 +511,20 @@ extern "C" {
cmData_t* cmDataRecdAllocIdA( cmData_t* parent, ... ); cmData_t* cmDataRecdAllocIdA( cmData_t* parent, ... );
// Extract the data in a record to C variables. // Extract the data in a record to C variables.
// <label|id> <typeId> <pointer> // The var-args list must be NULL terminated.
cmDtRC_t cmDataRecdParseLabelV(cmData_t* p, cmErr_t* err, va_list vl ); // The <'id' | 'label'> identify a pair.
cmDtRC_t cmDataRecdParseLabel( cmData_t* p, cmErr_t* err, ... ); // The <typeId> indicates the C type of 'pointer'.
cmDtRC_t cmDataRecdParseIdV( cmData_t* p, cmErr_t* err, va_list vl ); // The actual field type must be convertable into this pointer type or the
cmDtRC_t cmDataRecdParseId( cmData_t* p, cmErr_t* err, ... ); // function will fail.
// 'err' is an application supplied error object to be used if a required
// field is missing. 'errRC' is the client result code to be passed with
// the error report. See cmErrMsg(). Both 'err' and 'errRC' are optional.
// Set kOptArgDtFl on 'typeId' to indicate that a field is optional.
// <label|id> (<typeId> | kOptArgDtFl) <pointer>
cmDtRC_t cmDataRecdParseLabelV(cmData_t* p, cmErr_t* err, unsigned errRC, va_list vl );
cmDtRC_t cmDataRecdParseLabel( cmData_t* p, cmErr_t* err, unsigned errRC, ... );
cmDtRC_t cmDataRecdParseIdV( cmData_t* p, cmErr_t* err, unsigned errRC, va_list vl );
cmDtRC_t cmDataRecdParseId( cmData_t* p, cmErr_t* err, unsigned errRC, ... );
unsigned cmDataSerializeByteCount( const cmData_t* p ); unsigned cmDataSerializeByteCount( const cmData_t* p );
cmDtRC_t cmDataSerialize( const cmData_t* p, void* buf, unsigned bufByteCnt ); cmDtRC_t cmDataSerialize( const cmData_t* p, void* buf, unsigned bufByteCnt );