cwFlowValue.h/cpp : Implemented recd_fmt_t to alloc spec. of 'record' in class desc.
Implemented recd_get()/set() for multiple fields at once. Moved value_from_value() and value_from_cfg() into cwFlowValue from cwFlowType
This commit is contained in:
parent
c450378d78
commit
e3423e775e
673
cwFlowValue.cpp
673
cwFlowValue.cpp
@ -70,124 +70,187 @@ namespace cw
|
|||||||
if( f->group_fl )
|
if( f->group_fl )
|
||||||
_recd_type_destroy_field_list(f->u.group_fieldL);
|
_recd_type_destroy_field_list(f->u.group_fieldL);
|
||||||
|
|
||||||
|
mem::release(f->doc);
|
||||||
mem::release(f->label);
|
mem::release(f->label);
|
||||||
mem::release(f);
|
mem::release(f);
|
||||||
|
|
||||||
f = f0;
|
f = f0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _recd_type_add_field( recd_field_t*& fieldL_ref, const char* field_label, recd_field_t*& new_field_ref )
|
unsigned _recd_field_list_set_index( recd_field_t* fld, unsigned index )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
for(recd_field_t* f=fld; f!=nullptr; f=f->link)
|
||||||
recd_field_t* f = nullptr;
|
if( f->group_fl )
|
||||||
recd_field_t* new_field = nullptr;
|
index = _recd_field_list_set_index(f->u.group_fieldL,index);
|
||||||
|
else
|
||||||
|
f->u.index = index++;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* _recd_field_index_to_label(const recd_field_t* fld, unsigned field_idx)
|
||||||
|
{
|
||||||
|
const char* label = nullptr;
|
||||||
|
|
||||||
new_field_ref = nullptr;
|
for(const recd_field_t* f=fld; f!=nullptr; f=f->link)
|
||||||
|
if( f->group_fl )
|
||||||
if( textLength(field_label) == 0 )
|
label = _recd_field_index_to_label(f->u.group_fieldL,field_idx);
|
||||||
{
|
else
|
||||||
rc = cwLogError(kInvalidArgRC,"A blank msg field was encountered.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(f=fieldL_ref; f!=nullptr; f=f->link)
|
|
||||||
{
|
|
||||||
if( textIsEqual(field_label,f->label))
|
|
||||||
{
|
{
|
||||||
rc = cwLogError(kInvalidArgRC,"A duplicate msg field '%s' has been encountered.", field_label);
|
if(f->u.index == field_idx )
|
||||||
goto errLabel;
|
label = f->label;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the new field to the end of the list
|
|
||||||
if( f->link == nullptr )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_field = mem::allocZ<recd_field_t>();
|
|
||||||
new_field->label = mem::duplStr(field_label);
|
|
||||||
|
|
||||||
if( f == nullptr )
|
return label;
|
||||||
fieldL_ref = new_field;
|
|
||||||
else
|
|
||||||
f->link = new_field;
|
|
||||||
|
|
||||||
new_field_ref = new_field;
|
|
||||||
|
|
||||||
|
|
||||||
errLabel:
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
rc_t _recd_type_add_value_field( recd_field_t*& fieldL_ref, const char* field_label, unsigned index )
|
|
||||||
{
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
recd_field_t* new_field = nullptr;
|
|
||||||
|
|
||||||
if((rc = _recd_type_add_field( fieldL_ref, field_label, new_field )) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"Record add value field '%s' failed.",cwStringNullGuard(field_label));
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_field->group_fl = false;
|
|
||||||
new_field->u.index = index;
|
|
||||||
|
|
||||||
errLabel:
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc_t _recd_type_add_group_field( recd_field_t*& fieldL_ref, const char* field_label, recd_field_t*& new_field_ref )
|
|
||||||
{
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if((rc = _recd_type_add_field( fieldL_ref, field_label, new_field_ref )) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"Record add group field '%s' failed.",cwStringNullGuard(field_label));
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_field_ref->group_fl = true;
|
|
||||||
|
|
||||||
errLabel:
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rc_t _recd_type_add_value_fields( recd_type_t* recd_type, recd_field_t*& fieldL_ref, const char* field_labels )
|
rc_t _recd_field_list_from_cfg( recd_field_t*& field_list_ref, const object_t* field_dict_cfg )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
const char* s0 = field_labels;
|
|
||||||
|
|
||||||
while(s0 != nullptr)
|
if( !field_dict_cfg->is_dict() )
|
||||||
{
|
{
|
||||||
s0 = nextNonWhiteChar(s0);
|
rc = cwLogError(kSyntaxErrorRC,"The field cfg. is not a dictionary.");
|
||||||
|
goto errLabel;
|
||||||
const char* s1 = nextWhiteChar(s0);
|
|
||||||
|
|
||||||
unsigned sn = s1==nullptr ? textLength(s0) : s1-s0;
|
|
||||||
char s[sn+1];
|
|
||||||
strncpy(s,s0,sn);
|
|
||||||
s[sn] = 0;
|
|
||||||
|
|
||||||
if((rc = _recd_type_add_value_field(fieldL_ref, s, recd_type->fieldN)) != kOkRC )
|
|
||||||
{
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
recd_type->fieldN += 1;
|
|
||||||
|
|
||||||
s0 = s1;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned row_cnt = field_dict_cfg->child_count();
|
||||||
|
|
||||||
errLabel:
|
for(unsigned i=0; i<row_cnt; ++i)
|
||||||
|
{
|
||||||
|
const object_t* pair = field_dict_cfg->child_ele(i);
|
||||||
|
recd_field_t* field = nullptr;
|
||||||
|
const char* type_label = nullptr;
|
||||||
|
const char* doc_string = nullptr;
|
||||||
|
const object_t* val_cfg = nullptr;
|
||||||
|
|
||||||
|
// parse the required fields
|
||||||
|
if((rc = pair->pair_value()->getv("type",type_label,
|
||||||
|
"doc",doc_string)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Error parsing the field '%s'.",cwStringNullGuard(pair->pair_label()));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate the field record
|
||||||
|
field = mem::allocZ<recd_field_t>();
|
||||||
|
|
||||||
|
// add the new field to the end of the field list
|
||||||
|
if( field_list_ref == nullptr )
|
||||||
|
field_list_ref = field;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recd_field_t* f = field_list_ref;
|
||||||
|
while( f->link != nullptr )
|
||||||
|
f = f->link;
|
||||||
|
|
||||||
|
assert(f!=nullptr);
|
||||||
|
f->link = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
field->label = mem::duplStr(pair->pair_label());
|
||||||
|
field->doc = mem::duplStr(doc_string);
|
||||||
|
|
||||||
|
if( textIsEqual(type_label,"group") )
|
||||||
|
{
|
||||||
|
const object_t* field_dict;
|
||||||
|
|
||||||
|
field->group_fl = true;
|
||||||
|
|
||||||
|
// get the group 'fields' dictionary
|
||||||
|
if((rc = pair->pair_value()->getv("fields",field_dict)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"The field group '%s' does not have a field list.",pair->pair_label());
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursively read the group field list
|
||||||
|
if((rc = _recd_field_list_from_cfg(field->u.group_fieldL,field_dict)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"The creation of field group '%s' failed.",pair->pair_label());
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
// validate the value type flag
|
||||||
|
if((field->value.tflag = value_type_label_to_flag( type_label )) == kInvalidTFl )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kSyntaxErrorRC,"The value type label '%s' is not valid on the field specifier '%s'.",cwStringNullGuard(type_label),cwStringNullGuard(pair->pair_label()));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the optional default value
|
||||||
|
if((val_cfg = pair->pair_value()->find("value")) != nullptr )
|
||||||
|
{
|
||||||
|
value_t v;
|
||||||
|
v.tflag = kInvalidTFl;
|
||||||
|
|
||||||
|
// parse the value into 'v'
|
||||||
|
if((rc = value_from_cfg(val_cfg,v)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"The default value parse failed for the field '%s'.",cwStringNullGuard(pair->pair_label()));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the value from 'v' into field->value
|
||||||
|
if((rc = value_from_value(v,field->value)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"The default value assignment failed for the field '%s'.",cwStringNullGuard(pair->pair_label()));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _recd_set_value_type( recd_field_t* fieldL, recd_t* r )
|
||||||
|
{
|
||||||
|
recd_field_t* f = fieldL;
|
||||||
|
for(; f!=nullptr; f=f->link)
|
||||||
|
if( f->group_fl )
|
||||||
|
_recd_set_value_type( f->u.group_fieldL, r );
|
||||||
|
else
|
||||||
|
r->valA[ f->u.index ].tflag = f->value.tflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _recd_set_default_value( recd_field_t* fieldL, recd_t* r )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
recd_field_t* f = fieldL;
|
||||||
|
|
||||||
|
for(; f!=nullptr; f=f->link)
|
||||||
|
{
|
||||||
|
if( f->group_fl )
|
||||||
|
_recd_set_default_value( f->u.group_fieldL, r );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(f->value.tflag != kInvalidTFl)
|
||||||
|
{
|
||||||
|
if((rc = value_from_value( f->value, r->valA[f->u.index] )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Set default value failed on the field '%s'.",cwStringNullGuard(f->label));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const recd_field_t* _find_field( const recd_field_t* fieldL, const char* label, unsigned label_charN, bool group_fl )
|
const recd_field_t* _find_field( const recd_field_t* fieldL, const char* label, unsigned label_charN, bool group_fl )
|
||||||
{
|
{
|
||||||
for(const recd_field_t* f = fieldL; f!=nullptr; f=f->link)
|
for(const recd_field_t* f = fieldL; f!=nullptr; f=f->link)
|
||||||
@ -779,7 +842,137 @@ void cw::flow::value_duplicate( value_t& dst, const value_t& src )
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::value_from_cfg( const object_t* cfg, value_t& value_ref )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
switch( cfg->type->id )
|
||||||
|
{
|
||||||
|
case kCharTId:
|
||||||
|
case kUInt8TId:
|
||||||
|
case kUInt16TId:
|
||||||
|
case kUInt32TId:
|
||||||
|
value_ref.tflag = kUIntTFl;
|
||||||
|
if((rc = cfg->value(value_ref.u.u)) != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Conversion to uint failed.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kInt8TId:
|
||||||
|
case kInt16TId:
|
||||||
|
case kInt32TId:
|
||||||
|
value_ref.tflag = kIntTFl;
|
||||||
|
if((rc = cfg->value(value_ref.u.i)) != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Conversion to int failed.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kInt64TId:
|
||||||
|
case kUInt64TId:
|
||||||
|
rc = cwLogError(kInvalidArgRC,"The flow system does not currently implement 64bit integers.");
|
||||||
|
goto errLabel;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFloatTId:
|
||||||
|
value_ref.tflag = kFloatTFl;
|
||||||
|
if((rc = cfg->value(value_ref.u.f)) != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Conversion to float failed.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kDoubleTId:
|
||||||
|
value_ref.tflag = kDoubleTFl;
|
||||||
|
if((rc = cfg->value(value_ref.u.d)) != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Conversion to double failed.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kBoolTId:
|
||||||
|
value_ref.tflag = kBoolTFl;
|
||||||
|
if((rc = cfg->value(value_ref.u.b)) != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Conversion to bool failed.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kStringTId:
|
||||||
|
case kCStringTId:
|
||||||
|
value_ref.tflag = kStringTFl;
|
||||||
|
if((rc = cfg->value(value_ref.u.s)) != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Conversion to string failed.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
value_ref.tflag = kCfgTFl;
|
||||||
|
value_ref.u.cfg = cfg;
|
||||||
|
|
||||||
|
}
|
||||||
|
errLabel:
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::value_from_value( const value_t& src, value_t& dst )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if( dst.tflag == kInvalidTFl || dst.tflag & src.tflag)
|
||||||
|
{
|
||||||
|
dst = src;
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we only get here if conversion is necessary
|
||||||
|
|
||||||
|
switch( src.tflag )
|
||||||
|
{
|
||||||
|
case kInvalidTFl:
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The src operand does not have a valid type.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kBoolTFl:
|
||||||
|
rc = value_set(&dst,src.u.b);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kUIntTFl:
|
||||||
|
rc = value_set(&dst,src.u.u);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kIntTFl:
|
||||||
|
rc = value_set(&dst,src.u.i);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFloatTFl:
|
||||||
|
rc = value_set(&dst,src.u.f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kDoubleTFl:
|
||||||
|
rc = value_set(&dst,src.u.d);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kBoolMtxTFl:
|
||||||
|
case kUIntMtxTFl:
|
||||||
|
case kIntMtxTFl:
|
||||||
|
case kFloatMtxTFl:
|
||||||
|
case kDoubleMtxTFl:
|
||||||
|
rc = cwLogError(kNotImplementedRC,"Matrix conversion is not implemented for value to value conversion.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kABufTFl:
|
||||||
|
case kFBufTFl:
|
||||||
|
case kMBufTFl:
|
||||||
|
case kRBufTFl:
|
||||||
|
case kStringTFl:
|
||||||
|
case kTimeTFl:
|
||||||
|
case kCfgTFl:
|
||||||
|
case kMidiTFl:
|
||||||
|
rc = cwLogError(kOpFailRC,"Value conversion failed during value to value assignement.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
rc = cwLogError(kInvalidArgRC,"An unknown source operand data type 0x%x was encountered.",src.tflag);
|
||||||
|
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void cw::flow::value_print( const value_t* v, bool info_fl )
|
void cw::flow::value_print( const value_t* v, bool info_fl )
|
||||||
{
|
{
|
||||||
if( v == nullptr )
|
if( v == nullptr )
|
||||||
@ -1394,6 +1587,21 @@ cw::rc_t cw::flow::value_get( const value_t* val, midi::ch_msg_t*& valRef )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::value_get( const value_t* val, const midi::ch_msg_t*& valRef )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if( cwIsFlag(val->tflag & kTypeMask, kMidiTFl) )
|
||||||
|
valRef = val->u.midi;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valRef = nullptr;
|
||||||
|
rc = cwLogError(kTypeMismatchRC,"The type %s (0x%x) could not be converted to a MIDI record.",_typeFlagToLabel(val->tflag),val->tflag);
|
||||||
|
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
cw::rc_t cw::flow::value_set(value_t* val, midi::ch_msg_t* v )
|
cw::rc_t cw::flow::value_set(value_t* val, midi::ch_msg_t* v )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
@ -1406,7 +1614,7 @@ cw::rc_t cw::flow::value_set(value_t* val, midi::ch_msg_t* v )
|
|||||||
|
|
||||||
case kInvalidTFl:
|
case kInvalidTFl:
|
||||||
val->u.midi=v;
|
val->u.midi=v;
|
||||||
val->tflag = kCfgTFl;
|
val->tflag = kMidiTFl;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1417,17 +1625,74 @@ cw::rc_t cw::flow::value_set(value_t* val, midi::ch_msg_t* v )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::flow::recd_type_create( recd_type_t*& recd_type_ref, const recd_type_t* base, const char* fields_str )
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
{
|
//
|
||||||
rc_t rc = kOkRC;
|
// Record
|
||||||
recd_type_t* recd_type = mem::allocZ<recd_type_t>();
|
//
|
||||||
|
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::recd_format_create( recd_fmt_t*& recd_fmt_ref, const object_t* cfg )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
recd_fmt_t* recd_fmt = nullptr;
|
||||||
|
|
||||||
|
recd_fmt_ref = nullptr;
|
||||||
|
|
||||||
|
recd_fmt = mem::allocZ<recd_fmt_t>();
|
||||||
|
|
||||||
|
if((rc = recd_type_create(recd_fmt->recd_type,nullptr,cfg)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
recd_fmt->alloc_cnt = 32; // TODO: this should not be hard coded
|
||||||
|
|
||||||
|
if((rc =cfg->getv_opt("alloc_cnt",recd_fmt->alloc_cnt)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Error parsing record format 'alloc_cnt'.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
recd_fmt_ref = recd_fmt;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if(rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Record format creation failed.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw::flow::recd_format_destroy( recd_fmt_t*& recd_fmt_ref )
|
||||||
|
{
|
||||||
|
if( recd_fmt_ref != nullptr )
|
||||||
|
{
|
||||||
|
recd_type_destroy(recd_fmt_ref->recd_type);
|
||||||
|
mem::release(recd_fmt_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::recd_type_create( recd_type_t*& recd_type_ref, const recd_type_t* base, const object_t* cfg )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
const object_t* fields_dict = nullptr;;
|
||||||
|
|
||||||
|
recd_type_t* recd_type = mem::allocZ<recd_type_t>();
|
||||||
|
|
||||||
recd_type_ref = nullptr;
|
recd_type_ref = nullptr;
|
||||||
|
|
||||||
if((rc = recd_type_add_value_fields( recd_type, fields_str )) != kOkRC )
|
// get the fields list
|
||||||
|
if((rc = cfg->getv("fields",fields_dict)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"The 'fields' dictionary was not found in the record 'fmt' specifier.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the fields list
|
||||||
|
if((rc = _recd_field_list_from_cfg(recd_type->fieldL,fields_dict)) != kOkRC )
|
||||||
{
|
{
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assign the index to the value fields and update recd_type.fieldN
|
||||||
|
recd_type->fieldN = _recd_field_list_set_index(recd_type->fieldL, 0 );
|
||||||
|
|
||||||
recd_type->base = base;
|
recd_type->base = base;
|
||||||
recd_type_ref = recd_type;
|
recd_type_ref = recd_type;
|
||||||
@ -1451,34 +1716,6 @@ void cw::flow::recd_type_destroy( recd_type_t*& recd_type_ref )
|
|||||||
mem::release(recd_type_ref);
|
mem::release(recd_type_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::flow::recd_type_add_value_fields( recd_type_t* recd_type, const char* field_labels )
|
|
||||||
{
|
|
||||||
return _recd_type_add_value_fields( recd_type, recd_type->fieldL, field_labels );
|
|
||||||
}
|
|
||||||
|
|
||||||
cw::rc_t cw::flow::recd_type_add_group( recd_type_t* recd_type, const char* group_label, const char* field_labels )
|
|
||||||
{
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
recd_field_t* f = nullptr;
|
|
||||||
|
|
||||||
if((rc = _recd_type_add_group_field( recd_type->fieldL, group_label, f )) != kOkRC )
|
|
||||||
{
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((rc = _recd_type_add_value_fields( recd_type, f->u.group_fieldL, field_labels )) != kOkRC )
|
|
||||||
{
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
errLabel:
|
|
||||||
|
|
||||||
if( rc !=kOkRC )
|
|
||||||
rc = cwLogError(rc,"Record group add failed.");
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned cw::flow::recd_type_max_field_count( const recd_type_t* recd_type )
|
unsigned cw::flow::recd_type_max_field_count( const recd_type_t* recd_type )
|
||||||
{
|
{
|
||||||
@ -1502,31 +1739,63 @@ errLabel:
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* cw::flow::recd_type_field_index_to_label( const recd_type_t* recd_type, unsigned field_idx )
|
||||||
|
{
|
||||||
|
const char* label = nullptr;
|
||||||
|
|
||||||
|
if( field_idx >= recd_type->fieldN )
|
||||||
|
label = recd_type_field_index_to_label(recd_type->base, field_idx - recd_type->fieldN );
|
||||||
|
else
|
||||||
|
label = _recd_field_index_to_label(recd_type->fieldL,field_idx);
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void cw::flow::recd_type_print( const recd_type_t* recd_type )
|
void cw::flow::recd_type_print( const recd_type_t* recd_type )
|
||||||
{
|
{
|
||||||
_recd_type_print(recd_type,recd_type);
|
_recd_type_print(recd_type,recd_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::flow::recd_print( const recd_type_t* rt, const recd_t* r )
|
cw::rc_t cw::flow::recd_init( const recd_type_t* recd_type, const recd_t* base, recd_t* r )
|
||||||
{ return _recd_print( rt, r ); }
|
{
|
||||||
|
r->base = base;
|
||||||
|
return _recd_set_default_value( recd_type->fieldL, r );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::recd_print( const recd_type_t* recd_type, const recd_t* r )
|
||||||
|
{ return _recd_print( recd_type, r ); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::flow::recd_array_create( recd_array_t*& recd_array_ref, recd_type_t* recd_type, unsigned allocRecdN )
|
cw::rc_t cw::flow::recd_array_create( recd_array_t*& recd_array_ref, recd_type_t* recd_type, const recd_type_t* base, unsigned allocRecdN )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
recd_array_t* recd_array = mem::allocZ<recd_array_t>();
|
recd_array_t* recd_array = mem::allocZ<recd_array_t>();
|
||||||
|
|
||||||
recd_array_ref = nullptr;
|
recd_array_ref = nullptr;
|
||||||
|
|
||||||
recd_array->type = recd_type;
|
recd_array->type = mem::allocZ<recd_type_t>();
|
||||||
|
recd_array->type->fieldL = recd_type->fieldL;
|
||||||
|
recd_array->type->fieldN = recd_type->fieldN;
|
||||||
|
recd_array->type->base = base;
|
||||||
|
|
||||||
recd_array->valA = mem::allocZ<value_t>(recd_array->type->fieldN * allocRecdN);
|
recd_array->valA = mem::allocZ<value_t>(recd_array->type->fieldN * allocRecdN);
|
||||||
recd_array->recdA = mem::allocZ<recd_t>(allocRecdN);
|
recd_array->recdA = mem::allocZ<recd_t>(allocRecdN);
|
||||||
recd_array->allocRecdN = allocRecdN;
|
recd_array->allocRecdN = allocRecdN;
|
||||||
|
|
||||||
|
|
||||||
|
// for each record
|
||||||
for(unsigned i=0; i<allocRecdN; ++i)
|
for(unsigned i=0; i<allocRecdN; ++i)
|
||||||
|
{
|
||||||
|
// set the value array for this record
|
||||||
recd_array->recdA[i].valA = recd_array->valA + (i*recd_array->type->fieldN);
|
recd_array->recdA[i].valA = recd_array->valA + (i*recd_array->type->fieldN);
|
||||||
|
|
||||||
|
// set the value type of all records in the array
|
||||||
|
_recd_set_value_type( recd_array->type->fieldL, recd_array->recdA + i );
|
||||||
|
}
|
||||||
|
|
||||||
recd_array_ref = recd_array;
|
recd_array_ref = recd_array;
|
||||||
|
|
||||||
//if( rc != kOkRC )
|
//if( rc != kOkRC )
|
||||||
@ -1539,6 +1808,7 @@ cw::rc_t cw::flow::recd_array_destroy( recd_array_t*& recd_array_ref )
|
|||||||
{
|
{
|
||||||
if( recd_array_ref != nullptr )
|
if( recd_array_ref != nullptr )
|
||||||
{
|
{
|
||||||
|
mem::release(recd_array_ref->type);
|
||||||
mem::release(recd_array_ref->valA);
|
mem::release(recd_array_ref->valA);
|
||||||
mem::release(recd_array_ref->recdA);
|
mem::release(recd_array_ref->recdA);
|
||||||
mem::release(recd_array_ref);
|
mem::release(recd_array_ref);
|
||||||
@ -1547,100 +1817,125 @@ cw::rc_t cw::flow::recd_array_destroy( recd_array_t*& recd_array_ref )
|
|||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::flow::value_test( const test::test_args_t& args )
|
cw::rc_t cw::flow::value_test( const test::test_args_t& args )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
recd_type_t* rt0 = nullptr;
|
object_t* cfg0 = nullptr;
|
||||||
recd_type_t* rt1 = nullptr;
|
object_t* cfg1 = nullptr;
|
||||||
recd_array_t* ra0 = nullptr;
|
recd_fmt_t* fmt0 = nullptr;
|
||||||
recd_array_t* ra1 = nullptr;
|
recd_fmt_t* fmt1 = nullptr;
|
||||||
|
recd_array_t* ra0 = nullptr;
|
||||||
|
recd_array_t* ra1 = nullptr;
|
||||||
|
|
||||||
if((rc = recd_type_create( rt0, nullptr, "a b c" )) != kOkRC )
|
const char* s0 = "{ alloc_cnt:3, fields: {"
|
||||||
{
|
"a: { type:bool, doc:\"A floater.\" },"
|
||||||
rc = cwLogError(rc,"rt0 create failed.");
|
"b: { type:uint, value:1, doc:\"My uint.\" },"
|
||||||
goto errLabel;
|
"c: { type:uint, value:2, doc:\"My other uint.\" }"
|
||||||
}
|
"g0: { type:group, doc:\"A group.\""
|
||||||
|
"fields:{ a:{type:int, value:0, doc:\"My int.\" }"
|
||||||
|
" b:{type:bool, value:true, doc:\"My flag.\" }"
|
||||||
|
" c:{type:double, value:1, doc:\"Another field.\" }"
|
||||||
|
"}}"
|
||||||
|
"}}";
|
||||||
|
|
||||||
|
const char* s1 = "{ alloc_cnt:3, fields: {"
|
||||||
|
"d: { type:double, doc:\"d doc.\" },"
|
||||||
|
"e: { type:uint, value:-1, doc:\"e doc.\" },"
|
||||||
|
"f: { type:uint, value:-1, doc:\"f doc.\" }"
|
||||||
|
"g1: { type:group, doc:\"A group.\""
|
||||||
|
"fields:{ a:{type:int, value:0, doc:\"My int.\" }"
|
||||||
|
" b:{type:bool, value:true, doc:\"My flag.\" }"
|
||||||
|
" c:{type:uint, value:1, doc:\"Another field.\" }"
|
||||||
|
"}}"
|
||||||
|
"}}";
|
||||||
|
|
||||||
if((rc = recd_type_add_group( rt0, "g0", "a b c" )) != kOkRC )
|
if((rc = objectFromString(s0,cfg0)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"rt.g0 group create failed.");
|
rc = cwLogError(rc,"cfg0 parse failed.");
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((rc = recd_type_create( rt1, rt0, "d e f" )) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"rt0 create failed.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((rc = recd_type_add_group( rt1, "g1", "a b c" )) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"rt.g0 group create failed.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
recd_type_print( rt0 );
|
|
||||||
recd_type_print( rt1 );
|
|
||||||
|
|
||||||
if((rc = recd_array_create(ra0,rt0,10)) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = cwLogError(rc,"ra0 alloc failed.");
|
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((rc = recd_array_create(ra1,rt1,10)) != kOkRC )
|
if((rc = objectFromString(s1,cfg1)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"ra1 alloc failed.");
|
rc = cwLogError(rc,"cfg1 parse failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if((rc = recd_format_create( fmt0, cfg0 )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"fmt0 create failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = recd_format_create( fmt1, cfg1 )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"fmt1 create failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = recd_array_create( ra0, fmt0->recd_type, nullptr, fmt0->alloc_cnt )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"recd array 0 create failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = recd_array_create( ra1, fmt1->recd_type, fmt0->recd_type, fmt1->alloc_cnt )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"recd array 0 create failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for(unsigned i=0; i<ra0->allocRecdN; ++i)
|
for(unsigned i=0; i<ra0->allocRecdN; ++i)
|
||||||
{
|
{
|
||||||
recd_t* r = ra0->recdA + i;
|
recd_t* r = ra0->recdA + i;
|
||||||
rc_t rc0 = recd_set( ra0->type, nullptr, r, recd_type_field_index(ra0->type,"a"), 0*i);
|
|
||||||
rc_t rc1 = recd_set( ra0->type, nullptr, r, recd_type_field_index(ra0->type,"b"), 1*i);
|
|
||||||
rc_t rc2 = recd_set( ra0->type, nullptr, r, recd_type_field_index(ra0->type,"c"), 2*i);
|
|
||||||
rc_t rc3 = recd_set( ra0->type, nullptr, r, recd_type_field_index(ra0->type,"g0.a"), 4.0*i);
|
|
||||||
rc_t rc4 = recd_set( ra0->type, nullptr, r, recd_type_field_index(ra0->type,"g0.b"), 5.0*i);
|
|
||||||
rc_t rc5 = recd_set( ra0->type, nullptr, r, recd_type_field_index(ra0->type,"g0.c"), 6.0*i);
|
|
||||||
|
|
||||||
if((rc = rcSelect(rc0,rc1,rc2,rc3,rc4,rc5)) != kOkRC )
|
if((rc = recd_set( ra0->type, nullptr, r,
|
||||||
|
recd_type_field_index(ra0->type,"a"), 0.0f*i,
|
||||||
|
recd_type_field_index(ra0->type,"g0.a"), 4.0*i,
|
||||||
|
recd_type_field_index(ra0->type,"g0.b"), 5*i,
|
||||||
|
recd_type_field_index(ra0->type,"g0.c"), 6*i)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"recd_set() failed on ra0.");
|
cwLogError(rc,"recd_set() failed on ra0.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i=0; i<ra0->allocRecdN; ++i)
|
for(unsigned i=0; i<ra0->allocRecdN; ++i)
|
||||||
recd_print(ra0->type,ra0->recdA+i);
|
recd_print(ra0->type,ra0->recdA+i);
|
||||||
|
|
||||||
|
|
||||||
for(unsigned i=0; i<ra1->allocRecdN; ++i)
|
for(unsigned i=0; i<ra1->allocRecdN; ++i)
|
||||||
{
|
{
|
||||||
recd_t* r = ra1->recdA + i;
|
recd_t* r = ra1->recdA + i;
|
||||||
recd_t* r_base = ra0->recdA + i;
|
recd_t* r_base = ra0->recdA + i;
|
||||||
rc_t rc0 = recd_set( ra1->type, r_base, r, recd_type_field_index(ra1->type,"d"), 0*i*2);
|
|
||||||
rc_t rc1 = recd_set( ra1->type, r_base, r, recd_type_field_index(ra1->type,"e"), 1*i*2);
|
|
||||||
rc_t rc2 = recd_set( ra1->type, r_base, r, recd_type_field_index(ra1->type,"f"), 2*i*2);
|
|
||||||
rc_t rc3 = recd_set( ra1->type, r_base, r, recd_type_field_index(ra1->type,"g1.a"), 4.0*i*2);
|
|
||||||
rc_t rc4 = recd_set( ra1->type, r_base, r, recd_type_field_index(ra1->type,"g1.b"), 5.0*i*2);
|
|
||||||
rc_t rc5 = recd_set( ra1->type, r_base, r, recd_type_field_index(ra1->type,"g1.c"), 6.0*i*2);
|
|
||||||
|
|
||||||
if((rc = rcSelect(rc0,rc1,rc2,rc3,rc4,rc5)) != kOkRC )
|
if((rc = recd_set( ra1->type, r_base, r,
|
||||||
|
recd_type_field_index(ra1->type,"d"), 0.0f*i,
|
||||||
|
recd_type_field_index(ra1->type,"g1.a"), 4.0*i*2,
|
||||||
|
recd_type_field_index(ra1->type,"g1.b"), 5*i*2,
|
||||||
|
recd_type_field_index(ra1->type,"g1.c"), 6*i*2)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"recd_set() failed on ra1.");
|
cwLogError(rc,"recd_set() failed on ra1.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i=0; i<ra1->allocRecdN; ++i)
|
for(unsigned i=0; i<ra1->allocRecdN; ++i)
|
||||||
recd_print(ra1->type,ra1->recdA+i);
|
recd_print(ra1->type,ra1->recdA+i);
|
||||||
|
|
||||||
recd_array_destroy(ra0);
|
|
||||||
recd_array_destroy(ra1);
|
recd_array_destroy( ra0 );
|
||||||
recd_type_destroy(rt0);
|
recd_array_destroy( ra1 );
|
||||||
recd_type_destroy(rt1);
|
|
||||||
|
recd_format_destroy( fmt0 );
|
||||||
|
recd_format_destroy( fmt1 );
|
||||||
|
|
||||||
|
cfg0->free();
|
||||||
|
cfg1->free();
|
||||||
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
182
cwFlowValue.h
182
cwFlowValue.h
@ -83,7 +83,7 @@ namespace cw
|
|||||||
|
|
||||||
kTypeMask = 0x0003ffff,
|
kTypeMask = 0x0003ffff,
|
||||||
|
|
||||||
kRuntimeTFl = 0x80000000,
|
kRuntimeTFl = 0x80000000, // The type of the value associated with this variable will be set by the proc instances during instantiation
|
||||||
|
|
||||||
kNumericTFl = kBoolTFl | kUIntTFl | kIntTFl | kFloatTFl | kDoubleTFl,
|
kNumericTFl = kBoolTFl | kUIntTFl | kIntTFl | kFloatTFl | kDoubleTFl,
|
||||||
kMtxTFl = kBoolMtxTFl | kUIntMtxTFl | kIntMtxTFl | kFloatMtxTFl | kDoubleMtxTFl,
|
kMtxTFl = kBoolMtxTFl | kUIntMtxTFl | kIntMtxTFl | kFloatMtxTFl | kDoubleMtxTFl,
|
||||||
@ -100,38 +100,13 @@ namespace cw
|
|||||||
} u;
|
} u;
|
||||||
} mtx_t;
|
} mtx_t;
|
||||||
|
|
||||||
typedef struct recd_field_str
|
struct recd_type_str;
|
||||||
{
|
struct recd_str;
|
||||||
bool group_fl; // set if this field record is a group
|
|
||||||
char* label; // field or group label
|
|
||||||
union
|
|
||||||
{
|
|
||||||
unsigned index; // index into recd_t.valA of the value associated with this field
|
|
||||||
struct recd_field_str* group_fieldL;
|
|
||||||
} u;
|
|
||||||
|
|
||||||
struct recd_field_str* link;
|
|
||||||
} recd_field_t;
|
|
||||||
|
|
||||||
typedef struct recd_type_str
|
|
||||||
{
|
|
||||||
recd_field_t* fieldL; // linked list of field spec's
|
|
||||||
unsigned fieldN; // length of fieldL list (fieldN + base->fieldN) is total field count
|
|
||||||
const struct recd_type_str* base;
|
|
||||||
} recd_type_t;
|
|
||||||
|
|
||||||
struct value_str;
|
|
||||||
typedef struct recd_str
|
|
||||||
{
|
|
||||||
struct value_str* valA; // varA[ fieldN ] array of field values
|
|
||||||
const struct recd_str* base; // base record fields
|
|
||||||
} recd_t;
|
|
||||||
|
|
||||||
typedef struct rbuf_str
|
typedef struct rbuf_str
|
||||||
{
|
{
|
||||||
const recd_type_t* type; // all msgs are formed from this type
|
const struct recd_type_str* type; // all msgs are formed from this type
|
||||||
const recd_t* recdA; // recdA[ recdN ]
|
const struct recd_str* recdA; // recdA[ recdN ]
|
||||||
unsigned recdN; //
|
unsigned recdN; //
|
||||||
} rbuf_t;
|
} rbuf_t;
|
||||||
|
|
||||||
typedef struct value_str
|
typedef struct value_str
|
||||||
@ -200,10 +175,10 @@ namespace cw
|
|||||||
void mbuf_destroy( mbuf_t*& buf );
|
void mbuf_destroy( mbuf_t*& buf );
|
||||||
mbuf_t* mbuf_duplicate( const mbuf_t* src );
|
mbuf_t* mbuf_duplicate( const mbuf_t* src );
|
||||||
|
|
||||||
rbuf_t* rbuf_create( const recd_type_t* type=nullptr, const recd_t* recdA=nullptr, unsigned recdN=0 );
|
rbuf_t* rbuf_create( const struct recd_type_str* type=nullptr, const struct recd_str* recdA=nullptr, unsigned recdN=0 );
|
||||||
void rbuf_destroy( rbuf_t*& buf );
|
void rbuf_destroy( rbuf_t*& buf );
|
||||||
rbuf_t* rbuf_duplicate( const rbuf_t* src );
|
rbuf_t* rbuf_duplicate( const rbuf_t* src );
|
||||||
void rbuf_setup( rbuf_t* rbuf, recd_type_t* type, recd_t* recdA, unsigned recdN );
|
void rbuf_setup( rbuf_t* rbuf, struct recd_type_str* type, struct recd_str* recdA, unsigned recdN );
|
||||||
|
|
||||||
|
|
||||||
inline bool value_is_abuf( const value_t* v ) { return v->tflag & kABufTFl; }
|
inline bool value_is_abuf( const value_t* v ) { return v->tflag & kABufTFl; }
|
||||||
@ -215,6 +190,14 @@ namespace cw
|
|||||||
void value_release( value_t* v );
|
void value_release( value_t* v );
|
||||||
void value_duplicate( value_t& dst, const value_t& src );
|
void value_duplicate( value_t& dst, const value_t& src );
|
||||||
|
|
||||||
|
// For all numeric types this function set's the type of 'value_ref' to the type of cfg.
|
||||||
|
// For all other types sets the type of 'value_ref' to kCfgTFl and stores 'cfg' to value_ref.u.cfg;
|
||||||
|
rc_t value_from_cfg( const object_t* cfg, value_t& value_ref );
|
||||||
|
|
||||||
|
// Assigns src to dst. If dst has a value type then src is converted to this type.
|
||||||
|
// If the conversion is not possible then the function fail.s
|
||||||
|
rc_t value_from_value( const value_t& src, value_t& dst );
|
||||||
|
|
||||||
void value_print( const value_t* value, bool info_fl=false);
|
void value_print( const value_t* value, bool info_fl=false);
|
||||||
|
|
||||||
rc_t value_get( const value_t* val, bool& valRef );
|
rc_t value_get( const value_t* val, bool& valRef );
|
||||||
@ -255,6 +238,7 @@ namespace cw
|
|||||||
rc_t value_set( value_t* val, const object_t* v );
|
rc_t value_set( value_t* val, const object_t* v );
|
||||||
|
|
||||||
rc_t value_get( const value_t* val, midi::ch_msg_t*& valRef );
|
rc_t value_get( const value_t* val, midi::ch_msg_t*& valRef );
|
||||||
|
rc_t value_get( const value_t* val, const midi::ch_msg_t*& valRef );
|
||||||
rc_t value_set( value_t* val, midi::ch_msg_t* v );
|
rc_t value_set( value_t* val, midi::ch_msg_t* v );
|
||||||
|
|
||||||
|
|
||||||
@ -264,30 +248,76 @@ namespace cw
|
|||||||
// Record
|
// Record
|
||||||
//
|
//
|
||||||
|
|
||||||
|
typedef struct recd_field_str
|
||||||
|
{
|
||||||
|
bool group_fl; // set if this field record is a group
|
||||||
|
char* label; // field or group label
|
||||||
|
value_t value; // default value for this field
|
||||||
|
char* doc; // documentation field for this field
|
||||||
|
union
|
||||||
|
{
|
||||||
|
unsigned index; // index into recd_t.valA of the value associated with this field
|
||||||
|
struct recd_field_str* group_fieldL;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
struct recd_field_str* link;
|
||||||
|
} recd_field_t;
|
||||||
|
|
||||||
|
typedef struct recd_type_str
|
||||||
|
{
|
||||||
|
recd_field_t* fieldL; // linked list of field spec's
|
||||||
|
unsigned fieldN; // length of fieldL list (fieldN + base->fieldN) is total field count
|
||||||
|
const struct recd_type_str* base; // base recd type that this field inherits from
|
||||||
|
} recd_type_t;
|
||||||
|
|
||||||
|
typedef struct recd_fmt_str
|
||||||
|
{
|
||||||
|
unsigned alloc_cnt; // count of records to pre-allocate
|
||||||
|
recd_type_t* recd_type; // record type for this variable
|
||||||
|
} recd_fmt_t;
|
||||||
|
|
||||||
typedef struct recd_array_str
|
typedef struct recd_array_str
|
||||||
{
|
{
|
||||||
recd_type_t* type;
|
recd_type_t* type; // recd_type_t of this record array
|
||||||
value_t* valA; // valA[ allocRecdN * type->fieldN ]
|
value_t* valA; // valA[ allocRecdN * type->fieldN ]
|
||||||
recd_t* recdA;
|
struct recd_str* recdA; // recdA[ allocRecdN ]
|
||||||
unsigned allocRecdN;
|
unsigned allocRecdN; //
|
||||||
} recd_array_t;
|
} recd_array_t;
|
||||||
|
|
||||||
rc_t recd_type_create( recd_type_t*& recd_type_ref, const recd_type_t* base_type, const char* fields_string=nullptr );
|
typedef struct recd_str
|
||||||
void recd_type_destroy( recd_type_t*& recd_type );
|
{
|
||||||
|
struct value_str* valA; // varA[ recd_type_t.fieldN ] array of field values
|
||||||
|
const struct recd_str* base; // Pointer to the records inherited fields.
|
||||||
|
} recd_t;
|
||||||
|
|
||||||
rc_t recd_type_add_value_fields( recd_type_t* recd_type, const char* field_labels );
|
|
||||||
rc_t recd_type_add_group( recd_type_t* recd_type, const char* group_label, const char* field_labels );
|
// Create/destroy a recd_format_t object.
|
||||||
|
rc_t recd_format_create( recd_fmt_t*& recd_fmt_ref, const object_t* cfg );
|
||||||
|
void recd_format_destroy( recd_fmt_t*& recd_fmt_ref );
|
||||||
|
|
||||||
|
// Create a recd_type_t instance from a cfg. description.
|
||||||
|
rc_t recd_type_create( recd_type_t*& recd_type_ref, const recd_type_t* base_type, const object_t* cfg );
|
||||||
|
void recd_type_destroy( recd_type_t*& recd_type );
|
||||||
|
|
||||||
// Count of fields combined local and base record types.
|
// Count of fields combined local and base record types.
|
||||||
rc_t recd_type_max_field_count( const recd_type_t* recd_type );
|
rc_t recd_type_max_field_count( const recd_type_t* recd_type );
|
||||||
|
|
||||||
// use '.' notation to separate groups from fields.
|
// Get the field index associated with a named field.
|
||||||
|
// Use '.' notation to separate groups from fields.
|
||||||
// Note if this is a 'local' field then the high bit in the returned index will be set.
|
// Note if this is a 'local' field then the high bit in the returned index will be set.
|
||||||
unsigned recd_type_field_index( const recd_type_t* recd_type, const char* field_label);
|
unsigned recd_type_field_index( const recd_type_t* recd_type, const char* field_label);
|
||||||
|
|
||||||
|
// Given a field index return the field label.
|
||||||
|
const char* recd_type_field_index_to_label( const recd_type_t* recd_type, unsigned field_idx );
|
||||||
|
|
||||||
|
// Set the record base pointer and the value of all fields with default values.
|
||||||
|
rc_t recd_init( const recd_type_t* recd_type, const recd_t* base, recd_t* r );
|
||||||
|
|
||||||
|
// Print the recd_type info. to the console.
|
||||||
void recd_type_print( const recd_type_t* recd_type );
|
void recd_type_print( const recd_type_t* recd_type );
|
||||||
|
|
||||||
|
|
||||||
|
// Read the value from a single record field
|
||||||
template< typename T >
|
template< typename T >
|
||||||
rc_t recd_get( const recd_type_t* type, const recd_t* recd, unsigned field_idx, T& val_ref )
|
rc_t recd_get( const recd_type_t* type, const recd_t* recd, unsigned field_idx, T& val_ref )
|
||||||
{
|
{
|
||||||
@ -297,6 +327,27 @@ namespace cw
|
|||||||
return recd_get( type->base, recd->base, field_idx - type->fieldN, val_ref );
|
return recd_get( type->base, recd->base, field_idx - type->fieldN, val_ref );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline rc_t _recd_get(const recd_type_t* recd_type, recd_t* r ) { return kOkRC; }
|
||||||
|
|
||||||
|
template< typename T1, typename... ARGS >
|
||||||
|
rc_t _recd_get( const recd_type_t* recd_type, const recd_t* recd, unsigned field_idx, T1& val, ARGS&&... args )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if((rc = recd_get(recd_type,recd,field_idx,val)) != kOkRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return _recd_get(recd_type,recd,std::forward<ARGS>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the value of multiple record fields.
|
||||||
|
template< typename T1, typename... ARGS >
|
||||||
|
rc_t recd_get( const recd_type_t* recd_type, const recd_t* recd, unsigned field_idx, T1& val, ARGS&&... args )
|
||||||
|
{
|
||||||
|
return _recd_get(recd_type,recd,field_idx,val,args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the base record pointer for a record with an inherited base
|
||||||
inline rc_t recd_set_base( const recd_type_t* type, recd_t* recd, const recd_t* base )
|
inline rc_t recd_set_base( const recd_type_t* type, recd_t* recd, const recd_t* base )
|
||||||
{
|
{
|
||||||
// if we are setting base then the type must have a base type
|
// if we are setting base then the type must have a base type
|
||||||
@ -318,9 +369,50 @@ namespace cw
|
|||||||
return value_set( recd->valA + field_idx, val );
|
return value_set( recd->valA + field_idx, val );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline rc_t _recd_set( const recd_type_t* recd_type, recd_t* recd ) { return kOkRC; }
|
||||||
|
|
||||||
|
template< typename T1, typename... ARGS >
|
||||||
|
rc_t _recd_set( const recd_type_t* recd_type, recd_t* recd, unsigned field_idx, const T1& val, ARGS&&... args )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if( field_idx >= recd_type->fieldN )
|
||||||
|
return cwLogError(kInvalidArgRC,"Fields in the inherited record may not be set.");
|
||||||
|
|
||||||
|
if((rc = value_set( recd->valA + field_idx, val)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Field set failed on '%s'.", cwStringNullGuard(recd_type_field_index_to_label( recd_type, field_idx )));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _recd_set(recd_type,recd,std::forward<ARGS>(args)...);
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set multiple fields of a record.
|
||||||
|
template< typename T1, typename... ARGS >
|
||||||
|
rc_t recd_set( const recd_type_t* recd_type, const recd_t* base, recd_t* recd, unsigned field_idx, const T1& val, ARGS&&... args )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
if((rc = recd_init( recd_type, base, recd )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
|
||||||
|
if((rc = _recd_set(recd_type,recd,field_idx,val,args...)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a record to the console.
|
||||||
rc_t recd_print( const recd_type_t* recd_type, const recd_t* r );
|
rc_t recd_print( const recd_type_t* recd_type, const recd_t* r );
|
||||||
|
|
||||||
rc_t recd_array_create( recd_array_t*& recd_array_ref, recd_type_t* recd_type, unsigned allocRecdN );
|
// Create/destroy a buffer of records.
|
||||||
|
rc_t recd_array_create( recd_array_t*& recd_array_ref, recd_type_t* recd_type, const recd_type_t* base, unsigned allocRecdN );
|
||||||
rc_t recd_array_destroy( recd_array_t*& recd_array_ref );
|
rc_t recd_array_destroy( recd_array_t*& recd_array_ref );
|
||||||
|
|
||||||
rc_t value_test( const test::test_args_t& args );
|
rc_t value_test( const test::test_args_t& args );
|
||||||
|
Loading…
Reference in New Issue
Block a user