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
601
cwFlowValue.cpp
601
cwFlowValue.cpp
@ -70,6 +70,7 @@ namespace cw
|
||||
if( f->group_fl )
|
||||
_recd_type_destroy_field_list(f->u.group_fieldL);
|
||||
|
||||
mem::release(f->doc);
|
||||
mem::release(f->label);
|
||||
mem::release(f);
|
||||
|
||||
@ -77,113 +78,175 @@ namespace cw
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
recd_field_t* f = nullptr;
|
||||
recd_field_t* new_field = nullptr;
|
||||
|
||||
new_field_ref = nullptr;
|
||||
|
||||
if( textLength(field_label) == 0 )
|
||||
{
|
||||
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);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// 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 )
|
||||
fieldL_ref = new_field;
|
||||
for(recd_field_t* f=fld; f!=nullptr; f=f->link)
|
||||
if( f->group_fl )
|
||||
index = _recd_field_list_set_index(f->u.group_fieldL,index);
|
||||
else
|
||||
f->link = new_field;
|
||||
|
||||
new_field_ref = new_field;
|
||||
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
f->u.index = index++;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
rc_t _recd_type_add_value_field( recd_field_t*& fieldL_ref, const char* field_label, unsigned index )
|
||||
const char* _recd_field_index_to_label(const recd_field_t* fld, unsigned field_idx)
|
||||
{
|
||||
rc_t rc;
|
||||
const char* label = nullptr;
|
||||
|
||||
recd_field_t* new_field = nullptr;
|
||||
|
||||
if((rc = _recd_type_add_field( fieldL_ref, field_label, new_field )) != kOkRC )
|
||||
for(const recd_field_t* f=fld; f!=nullptr; f=f->link)
|
||||
if( f->group_fl )
|
||||
label = _recd_field_index_to_label(f->u.group_fieldL,field_idx);
|
||||
else
|
||||
{
|
||||
rc = cwLogError(rc,"Record add value field '%s' failed.",cwStringNullGuard(field_label));
|
||||
goto errLabel;
|
||||
if(f->u.index == field_idx )
|
||||
label = f->label;
|
||||
}
|
||||
|
||||
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;
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
const char* s0 = field_labels;
|
||||
|
||||
while(s0 != nullptr)
|
||||
if( !field_dict_cfg->is_dict() )
|
||||
{
|
||||
s0 = nextNonWhiteChar(s0);
|
||||
|
||||
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 )
|
||||
rc = cwLogError(kSyntaxErrorRC,"The field cfg. is not a dictionary.");
|
||||
goto errLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned row_cnt = field_dict_cfg->child_count();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
recd_type->fieldN += 1;
|
||||
// allocate the field record
|
||||
field = mem::allocZ<recd_field_t>();
|
||||
|
||||
s0 = s1;
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -780,6 +843,136 @@ 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 )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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:
|
||||
val->u.midi=v;
|
||||
val->tflag = kCfgTFl;
|
||||
val->tflag = kMidiTFl;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1417,18 +1625,75 @@ 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 )
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Record
|
||||
//
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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_ref = recd_type;
|
||||
|
||||
@ -1451,34 +1716,6 @@ void cw::flow::recd_type_destroy( recd_type_t*& 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 )
|
||||
{
|
||||
@ -1502,31 +1739,63 @@ errLabel:
|
||||
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 )
|
||||
{
|
||||
_recd_type_print(recd_type,recd_type);
|
||||
}
|
||||
|
||||
cw::rc_t cw::flow::recd_print( const recd_type_t* rt, const recd_t* r )
|
||||
{ return _recd_print( rt, r ); }
|
||||
cw::rc_t cw::flow::recd_init( const recd_type_t* recd_type, const recd_t* base, recd_t* 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;
|
||||
recd_array_t* recd_array = mem::allocZ<recd_array_t>();
|
||||
|
||||
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->recdA = mem::allocZ<recd_t>(allocRecdN);
|
||||
recd_array->allocRecdN = allocRecdN;
|
||||
|
||||
|
||||
// for each record
|
||||
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);
|
||||
|
||||
// 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;
|
||||
|
||||
//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 )
|
||||
{
|
||||
mem::release(recd_array_ref->type);
|
||||
mem::release(recd_array_ref->valA);
|
||||
mem::release(recd_array_ref->recdA);
|
||||
mem::release(recd_array_ref);
|
||||
@ -1547,67 +1817,86 @@ cw::rc_t cw::flow::recd_array_destroy( recd_array_t*& recd_array_ref )
|
||||
return kOkRC;
|
||||
}
|
||||
|
||||
|
||||
cw::rc_t cw::flow::value_test( const test::test_args_t& args )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
recd_type_t* rt0 = nullptr;
|
||||
recd_type_t* rt1 = nullptr;
|
||||
object_t* cfg0 = nullptr;
|
||||
object_t* cfg1 = nullptr;
|
||||
recd_fmt_t* fmt0 = 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.\" },"
|
||||
"b: { type:uint, value:1, doc:\"My uint.\" },"
|
||||
"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 = objectFromString(s0,cfg0)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"rt0 create failed.");
|
||||
rc = cwLogError(rc,"cfg0 parse failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if((rc = recd_type_add_group( rt0, "g0", "a b c" )) != kOkRC )
|
||||
if((rc = objectFromString(s1,cfg1)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"rt.g0 group create failed.");
|
||||
rc = cwLogError(rc,"cfg1 parse failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if((rc = recd_type_create( rt1, rt0, "d e f" )) != kOkRC )
|
||||
if((rc = recd_format_create( fmt0, cfg0 )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"rt0 create failed.");
|
||||
rc = cwLogError(rc,"fmt0 create failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if((rc = recd_type_add_group( rt1, "g1", "a b c" )) != kOkRC )
|
||||
if((rc = recd_format_create( fmt1, cfg1 )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"rt.g0 group create failed.");
|
||||
rc = cwLogError(rc,"fmt1 create failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
recd_type_print( rt0 );
|
||||
recd_type_print( rt1 );
|
||||
|
||||
if((rc = recd_array_create(ra0,rt0,10)) != kOkRC )
|
||||
if((rc = recd_array_create( ra0, fmt0->recd_type, nullptr, fmt0->alloc_cnt )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"ra0 alloc failed.");
|
||||
rc = cwLogError(rc,"recd array 0 create failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
if((rc = recd_array_create(ra1,rt1,10)) != kOkRC )
|
||||
if((rc = recd_array_create( ra1, fmt1->recd_type, fmt0->recd_type, fmt1->alloc_cnt )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"ra1 alloc failed.");
|
||||
rc = cwLogError(rc,"recd array 0 create failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
|
||||
for(unsigned i=0; i<ra0->allocRecdN; ++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;
|
||||
}
|
||||
}
|
||||
@ -1615,20 +1904,19 @@ cw::rc_t cw::flow::value_test( const test::test_args_t& args )
|
||||
for(unsigned i=0; i<ra0->allocRecdN; ++i)
|
||||
recd_print(ra0->type,ra0->recdA+i);
|
||||
|
||||
|
||||
for(unsigned i=0; i<ra1->allocRecdN; ++i)
|
||||
{
|
||||
recd_t* r = ra1->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;
|
||||
}
|
||||
}
|
||||
@ -1636,11 +1924,18 @@ cw::rc_t cw::flow::value_test( const test::test_args_t& args )
|
||||
for(unsigned i=0; i<ra1->allocRecdN; ++i)
|
||||
recd_print(ra1->type,ra1->recdA+i);
|
||||
|
||||
|
||||
recd_array_destroy( ra0 );
|
||||
recd_array_destroy( ra1 );
|
||||
recd_type_destroy(rt0);
|
||||
recd_type_destroy(rt1);
|
||||
|
||||
recd_format_destroy( fmt0 );
|
||||
recd_format_destroy( fmt1 );
|
||||
|
||||
cfg0->free();
|
||||
cfg1->free();
|
||||
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
174
cwFlowValue.h
174
cwFlowValue.h
@ -83,7 +83,7 @@ namespace cw
|
||||
|
||||
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,
|
||||
kMtxTFl = kBoolMtxTFl | kUIntMtxTFl | kIntMtxTFl | kFloatMtxTFl | kDoubleMtxTFl,
|
||||
@ -100,37 +100,12 @@ namespace cw
|
||||
} u;
|
||||
} mtx_t;
|
||||
|
||||
typedef struct recd_field_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;
|
||||
|
||||
struct recd_type_str;
|
||||
struct recd_str;
|
||||
typedef struct rbuf_str
|
||||
{
|
||||
const recd_type_t* type; // all msgs are formed from this type
|
||||
const recd_t* recdA; // recdA[ recdN ]
|
||||
const struct recd_type_str* type; // all msgs are formed from this type
|
||||
const struct recd_str* recdA; // recdA[ recdN ]
|
||||
unsigned recdN; //
|
||||
} rbuf_t;
|
||||
|
||||
@ -200,10 +175,10 @@ namespace cw
|
||||
void mbuf_destroy( mbuf_t*& buf );
|
||||
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 );
|
||||
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; }
|
||||
@ -215,6 +190,14 @@ namespace cw
|
||||
void value_release( value_t* v );
|
||||
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);
|
||||
|
||||
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_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 );
|
||||
|
||||
|
||||
@ -264,30 +248,76 @@ namespace cw
|
||||
// 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
|
||||
{
|
||||
recd_type_t* type;
|
||||
recd_type_t* type; // recd_type_t of this record array
|
||||
value_t* valA; // valA[ allocRecdN * type->fieldN ]
|
||||
recd_t* recdA;
|
||||
unsigned allocRecdN;
|
||||
struct recd_str* recdA; // recdA[ allocRecdN ]
|
||||
unsigned allocRecdN; //
|
||||
} 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 );
|
||||
void recd_type_destroy( recd_type_t*& recd_type );
|
||||
typedef struct recd_str
|
||||
{
|
||||
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.
|
||||
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.
|
||||
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 );
|
||||
|
||||
|
||||
// Read the value from a single record field
|
||||
template< typename T >
|
||||
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 );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
// 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 );
|
||||
}
|
||||
|
||||
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_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 value_test( const test::test_args_t& args );
|
||||
|
Loading…
Reference in New Issue
Block a user