cwFlowValue.h/cpp,cwFlowTypes.h : Initial flow::list_t implementation
This commit is contained in:
parent
f1a85bae5d
commit
af103abe97
@ -106,6 +106,8 @@ namespace cw
|
|||||||
struct variable_str* src_var; // pointer to this input variables source link (or null if it uses the local_value)
|
struct variable_str* src_var; // pointer to this input variables source link (or null if it uses the local_value)
|
||||||
value_t* value; // pointer to the value associated with this variable
|
value_t* value; // pointer to the value associated with this variable
|
||||||
|
|
||||||
|
const list_t* value_list; // list of valid values for this variable or nullptr if not applicable
|
||||||
|
|
||||||
struct variable_str* var_link; // instance.varL list link
|
struct variable_str* var_link; // instance.varL list link
|
||||||
struct variable_str* ch_link; // list of channels that share this variable (rooted on 'any' channel - in order by channel number)
|
struct variable_str* ch_link; // list of channels that share this variable (rooted on 'any' channel - in order by channel number)
|
||||||
|
|
||||||
@ -546,7 +548,6 @@ namespace cw
|
|||||||
// Disconnect an in_var from it's source
|
// Disconnect an in_var from it's source
|
||||||
void var_disconnect( variable_t* in_var );
|
void var_disconnect( variable_t* in_var );
|
||||||
|
|
||||||
|
|
||||||
// Get the count of 'mult' vars associated with this var label.
|
// Get the count of 'mult' vars associated with this var label.
|
||||||
unsigned var_mult_count( proc_t* proc, const char* var_label );
|
unsigned var_mult_count( proc_t* proc, const char* var_label );
|
||||||
|
|
||||||
|
209
cwFlowValue.cpp
209
cwFlowValue.cpp
@ -1814,6 +1814,215 @@ cw::rc_t cw::flow::recd_array_destroy( recd_array_t*& recd_array_ref )
|
|||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// List
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace cw {
|
||||||
|
namespace flow {
|
||||||
|
rc_t _list_destroy( list_t*& list_ref )
|
||||||
|
{
|
||||||
|
if( list_ref != nullptr )
|
||||||
|
{
|
||||||
|
for(unsigned i=0; i<list_ref->eleN; ++i)
|
||||||
|
{
|
||||||
|
mem::release(list_ref->eleA[i].label);
|
||||||
|
value_release(&list_ref->eleA[i].value );
|
||||||
|
}
|
||||||
|
mem::release(list_ref);
|
||||||
|
}
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::list_create( list_t*& list_ref, const object_t* cfg )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
bool labelOnlyListFl = false;
|
||||||
|
|
||||||
|
if( !cfg->is_list() && !cfg->is_dict() )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidDataTypeRC,"The cfg. given to a flow list is not a JSON list or dictionary.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cfg->child_count() == 0 )
|
||||||
|
cwLogWarning("The cfg. list used to form a flow list is empty.");
|
||||||
|
|
||||||
|
if((rc = list_create(list_ref, cfg->child_count())) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
if( list_ref->eleAllocN == 0 )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
if( cfg->is_list() )
|
||||||
|
labelOnlyListFl = true;
|
||||||
|
|
||||||
|
for(unsigned i=0; i<list_ref->eleAllocN; ++i)
|
||||||
|
{
|
||||||
|
const object_t* ele = cfg->child_ele(i);
|
||||||
|
const char* label = nullptr;
|
||||||
|
value_t value;
|
||||||
|
|
||||||
|
// if this is a label-only list ...
|
||||||
|
if( labelOnlyListFl )
|
||||||
|
{
|
||||||
|
// this is a label-only list and so all elements must be strings
|
||||||
|
if( ele->is_string()==false )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kSyntaxErrorRC,"The list element at index '%i' is not a string.",i);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the element label
|
||||||
|
if( ele->value(label) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kSyntaxErrorRC,"Could not parse the list element at index '%i'.",i);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... then the value is the list element index
|
||||||
|
value_set(&value,i);
|
||||||
|
|
||||||
|
}
|
||||||
|
else // ... otherwise this is (label,value) dictioanry
|
||||||
|
{
|
||||||
|
// verify that the list element is a (label,element) pair.
|
||||||
|
if( !ele->is_pair() )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kSyntaxErrorRC,"The list dictionary element at index '%i' is not a (label,value) pair.",i);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate the dictionary label
|
||||||
|
if( ele->pair_label() == nullptr )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kSyntaxErrorRC,"The list dictionary element is missing it's label at index '%i'.",i);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the dict value to a flow value
|
||||||
|
if((rc = value_from_cfg(ele->pair_value(),value)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Unable to parse the dict. element value field for '%s' at index '%i'.",ele->pair_label(),i);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the conversion did not result in a numeric or string data type
|
||||||
|
if( cwIsFlag(value.tflag,kCfgTFl) )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"List element value field at index '%i' is not a numeric or string type.",i);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
label = ele->pair_label();
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the element to the list
|
||||||
|
if((rc = list_append( list_ref, label, value )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"List append failed at index '%i'.",i);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if( rc != kOkRC )
|
||||||
|
_list_destroy(list_ref);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::list_create( list_t*& list_ref, unsigned count )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
if((rc = list_destroy(list_ref)) != kOkRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
|
||||||
|
list_ref = mem::allocZ< list_t >();
|
||||||
|
list_ref->eleA = mem::allocZ< list_ele_t >( count );
|
||||||
|
list_ref->eleAllocN = count;
|
||||||
|
list_ref->eleN = 0;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::list_destroy( list_t*& list_ref )
|
||||||
|
{
|
||||||
|
return _list_destroy(list_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::flow::list_append( list_t* list, const char* label, const value_t& value )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if( textLength(label) == 0 )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"List elements must have a valid label.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( list->eleN >= list->eleAllocN )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kBufTooSmallRC,"Cannot append '%s' to a full list.",label);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( list->eleN == 0 )
|
||||||
|
list->eleA[0].value.tflag = value.tflag;
|
||||||
|
else
|
||||||
|
list->eleA[list->eleN].value.tflag = list->eleA[0].value.tflag;
|
||||||
|
|
||||||
|
if((rc = value_from_value( value, list->eleA[list->eleN].value )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Value conversion failed. All value types must be convertiable to type of the first list value.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->eleA[list->eleN].label = mem::duplStr(label);
|
||||||
|
|
||||||
|
list->eleN += 1;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if( rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"List append failed.");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* cw::flow::list_ele_label( const list_t* list, unsigned index )
|
||||||
|
{
|
||||||
|
assert( list != nullptr );
|
||||||
|
|
||||||
|
if( index >= list->eleN )
|
||||||
|
{
|
||||||
|
cwLogError(kInvalidArgRC,"The list index '%i' is invalid for a list of length '%i'.",index,list->eleN);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list->eleA[ index ].label;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cw::flow::list_ele_index( const list_t* list, const char* label )
|
||||||
|
{
|
||||||
|
assert( list != nullptr );
|
||||||
|
|
||||||
|
for(unsigned i=0; i<list->eleN; ++i)
|
||||||
|
if( textIsEqual(list->eleA[i].label,label) )
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return kInvalidIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
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;
|
||||||
|
@ -424,6 +424,81 @@ namespace cw
|
|||||||
// function does very little to verify that the actually are.
|
// function does very little to verify that the actually are.
|
||||||
rc_t recd_copy( const recd_type_t* src_recd_type, const recd_t* src_recdA, unsigned src_recdN, recd_array_t* dest_recd_array );
|
rc_t recd_copy( const recd_type_t* src_recd_type, const recd_t* src_recdA, unsigned src_recdN, recd_array_t* dest_recd_array );
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// List
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct list_ele_str
|
||||||
|
{
|
||||||
|
char* label;
|
||||||
|
value_t value;
|
||||||
|
} list_ele_t;
|
||||||
|
|
||||||
|
typedef struct list_str
|
||||||
|
{
|
||||||
|
unsigned tflag; // all elements of the list share the same value type.
|
||||||
|
list_ele_t* eleA;
|
||||||
|
unsigned eleAllocN;
|
||||||
|
unsigned eleN;
|
||||||
|
|
||||||
|
} list_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Cfg: [ <label0>, <label1> ... <labelN> ] (value is the same as the element index)
|
||||||
|
// or
|
||||||
|
// [ (<label0>,<value0> ... (<labelN>,<valueN>) ]
|
||||||
|
rc_t list_create( list_t*& list_ref, const object_t* cfg );
|
||||||
|
rc_t list_create( list_t*& list_ref, unsigned count );
|
||||||
|
|
||||||
|
rc_t list_destroy( list_t*& list_ref );
|
||||||
|
|
||||||
|
rc_t list_append( list_t* list, const char* label, const value_t& value );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
rc_t list_append( list_t* list, const char* label, const T& v )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
value_t value;
|
||||||
|
value.tflag = kInvalidTFl;
|
||||||
|
if((rc = value_set(&value,v)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
if((rc = list_append(list,label,value)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* list_ele_label( const list_t* list, unsigned index );
|
||||||
|
unsigned list_ele_index( const list_t* list, const char* label );
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
rc_t list_ele_value( const list_t* list, unsigned index, T& v )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
if( index >= list->eleN )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"The list element index '%i' is invalid on a list of length '%i'.",index,list->eleN);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = value_get(&list->eleA[index].value,v)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Read of list element value at index '%i' failed.",index,list->eleN);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
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