2024-12-01 19:35:24 +00:00
//| Copyright: (C) 2020-2024 Kevin Larke <contact AT larke DOT org>
//| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
2024-04-22 20:02:40 +00:00
# include "cwCommon.h"
# include "cwLog.h"
# include "cwCommonImpl.h"
2024-05-29 16:36:57 +00:00
# include "cwTest.h"
2024-04-22 20:02:40 +00:00
# include "cwMem.h"
# include "cwText.h"
# include "cwNumericConvert.h"
# include "cwObject.h"
# include "cwAudioFile.h"
# include "cwVectOps.h"
# include "cwMtx.h"
# include "cwDspTypes.h" // real_t, sample_t
# include "cwTime.h"
# include "cwMidiDecls.h"
# include "cwFlowDecl.h"
# include "cwFlowTypes.h"
# include "cwFlowNet.h"
# include "cwFlowProc.h"
namespace cw
{
namespace flow
{
2024-05-10 19:54:21 +00:00
//=======================================================================================================
//
// network creation
//
typedef enum {
kLocalProcTypeId = 0x01 ,
kLocalVarTypeId = 0x02 ,
kRemoteProcTypeId = 0x04 ,
kRemoteVarTypeId = 0x08
} io_ele_type_id_t ;
typedef struct io_ele_str
{
io_ele_type_id_t typeId ; // See k???TypeId above
char * label ; // label of in or src id
unsigned base_sfx_id ; // Literal base_sfx_id or kInvalidId if the base_sfx_id was not given or 'is_iter_fl' is false
unsigned sfx_id ; // 'sfx_id' is only used by _io_stmt_connect_vars()
unsigned sfx_id_count ; // Literal sfx_id_count or kInvalidCnt if not given
unsigned is_iter_fl ; // This id included an '_' (underscore)
} io_ele_t ;
typedef struct io_stmt_str
{
io_ele_t in_proc_ele ; // in-proc element
io_ele_t in_var_ele ; // in-var element
io_ele_t src_proc_ele ; // src-proc element
io_ele_t src_var_ele ; // src-var element
io_ele_t * local_proc_ele ;
io_ele_t * local_var_ele ;
char * remote_net_label ;
network_t * remote_net ;
io_ele_t * remote_proc_ele ;
io_ele_t * remote_var_ele ;
bool local_proc_iter_fl ; // Is the local proc iterating (this is a poly iteration rather than a var iterator)
const io_ele_t * iter_cnt_ctl_ele ; // Pointer to the ele which is controlling the iteration count (or null if in-var is non-iterating)
unsigned iter_cnt ; // Count of iterations or 0 if in-var is non-iterating.
// in_stmt only fields
var_desc_t * local_var_desc ; // Pointer to the in-var var_desc.
bool in_create_fl ; // True if the in_var needs to be created with an sfx_id, false create the var by the default process (w/o sfx_id)
} io_stmt_t ;
typedef struct proc_inst_parse_statestr
{
char * proc_label ; //
unsigned proc_label_sfx_id ; //
const char * proc_clas_label ; //
const object_t * preset_labels ; //
const object_t * arg_cfg ; //
const object_t * log_labels ; //
const object_t * in_dict_cfg ; // cfg. node to the in-list
io_stmt_t * iStmtA ;
unsigned iStmtN ;
const object_t * out_dict_cfg ; // cfg. node to the out-list
io_stmt_t * oStmtA ;
unsigned oStmtN ;
} proc_inst_parse_state_t ;
2024-06-05 14:09:13 +00:00
void _preset_value_destroy ( preset_value_t * v )
{
mem : : release ( v ) ;
}
void _network_preset_destroy ( network_preset_t & network_preset )
{
if ( network_preset . tid = = kPresetVListTId )
{
preset_value_t * pv = network_preset . u . vlist . value_head ;
while ( pv ! = nullptr )
{
preset_value_t * pv0 = pv - > link ;
_preset_value_destroy ( pv ) ;
pv = pv0 ;
}
network_preset . u . vlist . value_head = nullptr ;
network_preset . u . vlist . value_tail = nullptr ;
}
}
void _network_preset_array_destroy ( network_t & net )
{
for ( unsigned i = 0 ; i < net . presetN ; + + i )
_network_preset_destroy ( net . presetA [ i ] ) ;
mem : : release ( net . presetA ) ;
}
2024-09-17 20:33:26 +00:00
2024-10-12 19:27:33 +00:00
rc_t _destroy_ui_net ( ui_net_t * & ui_net )
{
rc_t rc = kOkRC ;
if ( ui_net = = nullptr )
return rc ;
for ( unsigned i = 0 ; i < ui_net - > procN ; + + i )
{
2024-10-19 16:37:13 +00:00
ui_net_t * iun = ui_net - > procA [ i ] . internal_net ;
while ( iun ! = nullptr )
{
ui_net_t * iun0 = iun - > poly_link ;
_destroy_ui_net ( iun ) ;
iun = iun0 ;
}
2024-10-12 19:27:33 +00:00
mem : : release ( ui_net - > procA [ i ] . varA ) ;
2024-10-19 16:37:13 +00:00
2024-10-12 19:27:33 +00:00
}
2024-10-19 16:37:13 +00:00
2024-10-12 19:27:33 +00:00
mem : : release ( ui_net - > procA ) ;
mem : : release ( ui_net - > presetA ) ;
mem : : release ( ui_net ) ;
return rc ;
}
2024-09-17 20:33:26 +00:00
rc_t _network_destroy_one ( network_t * & net )
2024-06-05 14:09:13 +00:00
{
rc_t rc = kOkRC ;
2024-10-12 19:27:33 +00:00
if ( net = = nullptr )
return rc ;
2024-09-17 20:33:26 +00:00
2024-10-12 19:27:33 +00:00
for ( unsigned i = 0 ; i < net - > procN ; + + i )
proc_destroy ( net - > procA [ i ] ) ;
2024-06-05 14:09:13 +00:00
2024-10-12 19:27:33 +00:00
mem : : release ( net - > procA ) ;
net - > procN = 0 ;
2024-06-05 14:09:13 +00:00
2024-09-17 20:33:26 +00:00
_network_preset_array_destroy ( * net ) ;
2024-06-05 14:09:13 +00:00
2024-09-17 20:33:26 +00:00
mem : : release ( net - > preset_pairA ) ;
net - > preset_pairN = 0 ;
2024-07-08 20:57:47 +00:00
2024-09-17 20:33:26 +00:00
net_global_var_t * gv = net - > globalVarL ;
2024-07-08 20:57:47 +00:00
while ( gv ! = nullptr )
{
net_global_var_t * gv0 = gv - > link ;
mem : : release ( gv - > var_label ) ;
mem : : release ( gv - > blob ) ;
mem : : release ( gv ) ;
gv = gv0 ;
}
2024-09-17 20:33:26 +00:00
2024-10-12 19:27:33 +00:00
_destroy_ui_net ( net - > ui_net ) ;
2024-09-17 20:33:26 +00:00
mem : : release ( net ) ;
return rc ;
}
rc_t _network_destroy ( network_t * & net )
{
rc_t rc = kOkRC ;
while ( net ! = nullptr )
{
network_t * n0 = net - > poly_link ;
rc_t rc0 ;
if ( ( rc0 = _network_destroy_one ( net ) ) ! = kOkRC )
rc = cwLogError ( rc0 , " A network destroy failed. " ) ;
net = n0 ;
}
2024-06-05 14:09:13 +00:00
return rc ;
}
2024-05-10 19:54:21 +00:00
bool _is_non_null_pair ( const object_t * cfg )
{ return cfg ! = nullptr & & cfg - > is_pair ( ) & & cfg - > pair_label ( ) ! = nullptr & & cfg - > pair_value ( ) ! = nullptr ; }
// Get the count of digits at the end of a string.
unsigned _digit_suffix_char_count ( const char * s )
{
unsigned digitN = 0 ;
unsigned sn = textLength ( s ) ;
if ( sn = = 0 )
return 0 ;
const char * s0 = s + ( textLength ( s ) - 1 ) ;
// go backward from the last char until the begin-of-string or a non-digit is found
for ( ; s0 > = s ; - - s0 )
{
if ( ! isdigit ( * s0 ) )
break ;
+ + digitN ;
}
return digitN ;
}
rc_t _io_stmt_parse_proc_var_string ( char * str , const char * & in_proc_label , const char * & in_var_label )
{
rc_t rc = kOkRC ;
char * period = nullptr ;
if ( ( period = firstMatchChar ( str , ' . ' ) ) = = nullptr )
{
in_proc_label = nullptr ;
in_var_label = str ;
}
else
{
* period = ' \0 ' ;
in_proc_label = str ;
in_var_label = period + 1 ;
}
return rc ;
}
rc_t _io_stmt_parse_net_proc_var_string ( char * str , char * & src_net_label , const char * & src_proc_label , const char * & src_var_label )
{
rc_t rc = kOkRC ;
char * period0 = nullptr ;
char * period1 = nullptr ;
// locate the separator period on the src proc/var id
if ( ( period0 = firstMatchChar ( str , ' . ' ) ) = = nullptr )
{
cwLogError ( kSyntaxErrorRC , " No period separator was found in the src net/proc/var for the src specifier:%s. " , str ) ;
goto errLabel ;
}
* period0 = 0 ;
if ( ( period1 = firstMatchChar ( period0 + 1 , ' . ' ) ) ! = nullptr )
{
* period1 = 0 ;
src_var_label = period1 + 1 ; // Set a pointer to the src var label
src_proc_label = period0 + 1 ;
src_net_label = mem : : duplStr ( str ) ;
}
else
{
src_var_label = period0 + 1 ;
src_proc_label = str ;
src_net_label = nullptr ;
}
if ( textLength ( src_var_label ) = = 0 )
rc = cwLogError ( kSyntaxErrorRC , " The 'src-var' label has length 0. " ) ;
if ( textLength ( src_proc_label ) = = 0 )
rc = cwLogError ( kSyntaxErrorRC , " The 'src-proc' label has length 0. " ) ;
errLabel :
return rc ;
}
rc_t _io_stmt_parse_ele ( const char * id_str , io_ele_t & r , bool inProcFl = false )
{
rc_t rc = kOkRC ;
unsigned bufN ;
2024-04-22 20:02:40 +00:00
r . base_sfx_id = kInvalidId ;
r . sfx_id_count = kInvalidCnt ;
if ( ( bufN = textLength ( id_str ) ) = = 0 )
{
2024-05-08 14:18:43 +00:00
if ( ! inProcFl )
2024-05-19 19:24:33 +00:00
rc = cwLogError ( kSyntaxErrorRC , " A blank id string was encountered. " ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
else
{
char * underscore = nullptr ;
char * digit = nullptr ;
2024-05-08 14:18:43 +00:00
int offs = inProcFl ? 1 : 0 ;
char buf [ bufN + ( 1 + offs ) ] ;
// in-proc's don't have a leading label - add one here to please the parser
if ( inProcFl )
buf [ 0 ] = ' x ' ;
2024-04-22 20:02:40 +00:00
// copy the id string into a non-const scratch buffer
2024-05-08 14:18:43 +00:00
textCopy ( buf + offs , bufN + 1 , id_str ) ;
2024-04-22 20:02:40 +00:00
// locate the last underscore
if ( ( underscore = lastMatchChar ( buf , ' _ ' ) ) ! = nullptr )
{
* underscore = 0 ; // terminate the string prior to the underscore
for ( digit = underscore + 1 ; * digit ; digit + + )
if ( ! isdigit ( * digit ) )
break ;
// if the underscore was followed by a number
// or if the underscore was the last char
// in the string - then digit will point to
// the terminating zero - otherwise the
// underscore did not indicate an iterating id
if ( * digit ! = 0 )
{
* underscore = ' _ ' ; // replace the underscore - its part of the label
underscore = nullptr ;
}
else
{
r . is_iter_fl = true ;
// if there is a number following the underscore then this is the secInt
if ( textLength ( underscore + 1 ) )
{
// a literal iteration count was given - parse it into an integer
if ( ( rc = string_to_number ( underscore + 1 , r . sfx_id_count ) ) ! = kOkRC )
{
2024-05-19 19:24:33 +00:00
rc = cwLogError ( rc , " Unable to parse the secondary integer in the id label '%s'. " , cwStringNullGuard ( id_str ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
}
}
}
// verify that some content remains in the id string
if ( textLength ( buf ) = = 0 )
{
2024-05-19 19:24:33 +00:00
rc = cwLogError ( kSyntaxErrorRC , " Unable to parse the id string '%s'. " , cwStringNullGuard ( id_str ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
// go backward from the last char until the begin-of-string or a non-digit is found
for ( digit = buf + textLength ( buf ) - 1 ; digit > buf ; - - digit )
if ( ! isdigit ( * digit ) )
{
+ + digit ; // advance to the first digit in the number
break ;
}
// if a digit was found then this is the 'priInt'
2024-05-08 14:18:43 +00:00
if ( digit > buf & & textLength ( digit ) )
2024-04-22 20:02:40 +00:00
{
assert ( buf < = digit - 1 & & digit - 1 < = buf + bufN ) ;
// a literal base-sfx-id was given - parse it into an integer
if ( ( rc = string_to_number ( digit , r . base_sfx_id ) ) ! = kOkRC )
{
2024-05-19 19:24:33 +00:00
rc = cwLogError ( rc , " Unable to parse the primary integer in the id '%s'. " , cwStringNullGuard ( id_str ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
* digit = 0 ; // zero terminate the label
}
// verify that some content remains in the id string
if ( textLength ( buf ) = = 0 )
{
2024-05-19 19:24:33 +00:00
rc = cwLogError ( kSyntaxErrorRC , " Unexpected invalid id '%s'. " , cwStringNullGuard ( id_str ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
else
2024-05-10 19:54:21 +00:00
{
// store the label
if ( ! inProcFl )
r . label = mem : : duplStr ( buf ) ;
}
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
2024-04-22 20:02:40 +00:00
errLabel :
return rc ;
}
2024-05-10 19:54:21 +00:00
// Recursively search the tree of networks rooted on 'net' for the
// network named 'net_proc_label'.
network_t * _io_stmt_find_labeled_network ( network_t & net , const char * net_proc_label )
{
network_t * labeled_net = nullptr ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// for each proc instance in the network
2024-10-12 19:27:33 +00:00
for ( unsigned i = 0 ; i < net . procN & & labeled_net = = nullptr ; + + i )
2024-05-10 19:54:21 +00:00
{
2024-10-12 19:27:33 +00:00
proc_t * proc = net . procA [ i ] ;
2024-05-10 19:54:21 +00:00
// if this proc instance has an internal network
if ( proc - > internal_net ! = nullptr )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
// if the name of the network matches the key ...
if ( textIsEqual ( proc - > label , net_proc_label ) )
labeled_net = proc - > internal_net ; // .. we are done
else
{
// ... otherwise recurse
labeled_net = _io_stmt_find_labeled_network ( * proc - > internal_net , net_proc_label ) ;
}
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
2024-04-22 20:02:40 +00:00
}
2024-09-17 20:33:26 +00:00
if ( labeled_net = = nullptr & & net . poly_link ! = nullptr )
labeled_net = _io_stmt_find_labeled_network ( * net . poly_link , net_proc_label ) ;
2024-05-10 19:54:21 +00:00
return labeled_net ;
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
// If the local-var is iterating then the count of iterations must be controlled by exactly one
// of the 3 parts of the io-stmt: local-var,remote_proc, or remote_var. This function determines
2024-04-22 20:02:40 +00:00
// which element is used to determine the iteration count.
2024-05-10 19:54:21 +00:00
rc_t _io_stmt_determine_iter_count_ctl_ele ( network_t & net ,
proc_t * proc ,
const io_ele_t & localVar ,
const io_ele_t & remoteProc ,
const io_ele_t & remoteVar ,
const char * localLabel ,
const char * remoteLabel ,
const io_ele_t * & result_ref )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
assert ( localVar . is_iter_fl ) ;
2024-04-22 20:02:40 +00:00
rc_t rc = kOkRC ;
2024-05-10 19:54:21 +00:00
result_ref = nullptr ;
const io_ele_t * iter_cnt_ctl_ele = nullptr ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// if the local-var gives a literal count - then it determines the count
if ( localVar . sfx_id_count ! = kInvalidCnt )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
// if the local-var gives a literal count then the remote-proc cannot give one
if ( remoteProc . sfx_id_count ! = kInvalidCnt )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The %s-var provided a literal iteration count therefore the %s-proc cannot. " , localLabel , remoteLabel ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
// if the local-var gives a literal count then the remote-var cannot give one
if ( remoteVar . sfx_id_count ! = kInvalidCnt )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The %s-var provided a literal iteration count therefore the %s-var cannot. " , localLabel , remoteLabel ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
iter_cnt_ctl_ele = & localVar ;
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
else // the remote-proc or remote-var must control the iter count
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
// if the remote-proc gives a literal count - then it determines the count
if ( remoteProc . sfx_id_count ! = kInvalidCnt )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
// then the remote-var cannot give a literal count
if ( remoteVar . sfx_id_count ! = kInvalidCnt )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The %s-proc provided a literal iteration count therefore the %s-var cannot. " , remoteLabel , remoteLabel ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
iter_cnt_ctl_ele = & remoteProc ;
2024-04-22 20:02:40 +00:00
}
else
{
2024-05-10 19:54:21 +00:00
// if the remote-var gives a literal count - then it determines the count
if ( remoteVar . sfx_id_count ! = kInvalidCnt )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
iter_cnt_ctl_ele = & remoteVar ;
2024-04-22 20:02:40 +00:00
}
else // no literal count was given - we need to get the implied count
{
2024-05-10 19:54:21 +00:00
// if the remote-proc is iterating then it will provide the count
if ( remoteProc . is_iter_fl )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
// the remote-var cannot be iterating if the remote-proc is iterating
if ( remoteVar . is_iter_fl )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The %s-proc is iterating therefore the %s-var cannot. " , remoteLabel , remoteLabel ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
iter_cnt_ctl_ele = & remoteProc ;
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
else // the remote-proc isn't iterating check the remote-var
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
if ( remoteVar . is_iter_fl )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
iter_cnt_ctl_ele = & remoteVar ;
2024-04-22 20:02:40 +00:00
}
else // no iteration count control was found
{
rc = cwLogError ( kSyntaxErrorRC , " No iteration count control was specified. " ) ;
goto errLabel ;
}
}
}
}
}
errLabel :
if ( rc = = kOkRC )
2024-05-10 19:54:21 +00:00
result_ref = iter_cnt_ctl_ele ;
return rc ;
}
rc_t _io_stmt_calc_proc_ele_count ( network_t & net , const io_ele_t & proc_ele , const char * in_or_src_label , unsigned & cnt_ref )
{
rc_t rc = kOkRC ;
cnt_ref = 0 ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// if a literal proc sfx_id was given then use it otherwise use the default base-sfx-id (0)
unsigned sfx_id = proc_ele . base_sfx_id = = kInvalidCnt ? kBaseSfxId : proc_ele . base_sfx_id ;
unsigned n ;
for ( n = 0 ; proc_find ( net , proc_ele . label , sfx_id ) ! = nullptr ; + + n )
sfx_id + = 1 ;
if ( n = = 0 )
{
rc = cwLogError ( kSyntaxErrorRC , " The %s-proc '%s:%i' was not found. " , in_or_src_label , cwStringNullGuard ( proc_ele . label ) , sfx_id ) ;
goto errLabel ;
}
2024-06-09 20:18:21 +00:00
if ( proc_ele . sfx_id_count = = kInvalidCnt )
cnt_ref = n ;
else
{
if ( proc_ele . sfx_id_count > n )
{
rc = cwLogError ( kSyntaxErrorRC , " The given literal sfx-id count %i execeeds the maximimum possible value of %i on %s-proc '%s:%i' . " , proc_ele . sfx_id_count , n , in_or_src_label , cwStringNullGuard ( proc_ele . label ) , sfx_id ) ;
goto errLabel ;
}
cnt_ref = proc_ele . sfx_id_count ;
}
2024-05-10 19:54:21 +00:00
errLabel :
2024-04-22 20:02:40 +00:00
return rc ;
}
2024-05-10 19:54:21 +00:00
rc_t _io_stmt_calc_var_ele_count ( network_t & net , const io_ele_t & proc_ele , const io_ele_t & var_ele , const char * in_or_src_label , unsigned & cnt_ref )
{
rc_t rc = kOkRC ;
cnt_ref = 0 ;
2024-06-09 20:18:21 +00:00
proc_t * proc = nullptr ;
unsigned proc_sfx_id = proc_ele . base_sfx_id = = kInvalidCnt ? kBaseSfxId : proc_ele . base_sfx_id ;
2024-05-10 19:54:21 +00:00
// locate the proc which owns this var
if ( ( proc = proc_find ( net , proc_ele . label , proc_sfx_id ) ) = = nullptr )
{
cwLogError ( kSyntaxErrorRC , " The %s-proc inst instance '%s:%i' could not be found. " , in_or_src_label , cwStringNullGuard ( proc_ele . label ) , proc_sfx_id ) ;
goto errLabel ;
}
else
{
// if a starting var sfx_id was given by the id then use it otherwise use the default base-sfx-id (0)
unsigned sfx_id = var_ele . base_sfx_id = = kInvalidCnt ? kBaseSfxId : var_ele . base_sfx_id ;
unsigned n ;
for ( n = 0 ; var_exists ( proc , var_ele . label , sfx_id , kAnyChIdx ) ; + + n )
sfx_id + = 1 ;
if ( n = = 0 )
{
cwLogError ( kSyntaxErrorRC , " The %s-var '%s:%i' was not found. " , in_or_src_label , cwStringNullGuard ( var_ele . label ) , sfx_id ) ;
goto errLabel ;
}
2024-06-09 20:18:21 +00:00
if ( var_ele . sfx_id_count = = kInvalidCnt )
cnt_ref = n ;
else
{
if ( var_ele . sfx_id_count > n )
{
rc = cwLogError ( kSyntaxErrorRC , " The given literal sfx-id count %i execeeds the maximimum possible value of %i on %s-var '%s:%i-%s:%i' . " , var_ele . sfx_id_count , n , in_or_src_label , cwStringNullGuard ( proc_ele . label ) , proc_ele . sfx_id , cwStringNullGuard ( var_ele . label ) , sfx_id ) ;
goto errLabel ;
}
cnt_ref = var_ele . sfx_id_count ;
}
2024-05-10 19:54:21 +00:00
2024-06-09 20:18:21 +00:00
}
2024-05-10 19:54:21 +00:00
errLabel :
return rc ;
}
rc_t _io_stmt_determine_iter_count ( network_t & net , proc_t * proc , const char * local_label , const char * remote_label , io_stmt_t & io_stmt )
2024-04-22 20:02:40 +00:00
{
rc_t rc = kOkRC ;
2024-05-10 19:54:21 +00:00
// it has already been determined that this an iterating io-stmt
2024-04-22 20:02:40 +00:00
// and a iteration count control element has been identified.
2024-05-10 19:54:21 +00:00
assert ( io_stmt . local_var_ele - > is_iter_fl ) ;
assert ( io_stmt . iter_cnt_ctl_ele ! = nullptr ) ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
switch ( io_stmt . iter_cnt_ctl_ele - > typeId )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
case kLocalVarTypeId :
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
assert ( io_stmt . iter_cnt_ctl_ele - > sfx_id_count ! = kInvalidCnt ) ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
if ( ( io_stmt . iter_cnt = io_stmt . iter_cnt_ctl_ele - > sfx_id_count ) = = 0 )
rc = cwLogError ( rc , " The literal %s-var iteration count on '%s:%i' must be greater than zero. " , local_label , cwStringNullGuard ( io_stmt . iter_cnt_ctl_ele - > label ) , io_stmt . iter_cnt_ctl_ele - > base_sfx_id ) ;
2024-04-22 20:02:40 +00:00
break ;
2024-05-10 19:54:21 +00:00
case kRemoteProcTypeId :
if ( ( rc = _io_stmt_calc_proc_ele_count ( * io_stmt . remote_net , * io_stmt . remote_proc_ele , remote_label , io_stmt . iter_cnt ) ) ! = kOkRC )
rc = cwLogError ( rc , " Unable to determine the %s-stmt iteration count based on the iteration control %s-proc '%s'. " , local_label , remote_label , cwStringNullGuard ( io_stmt . remote_proc_ele - > label ) ) ;
2024-04-22 20:02:40 +00:00
break ;
2024-05-10 19:54:21 +00:00
case kRemoteVarTypeId :
if ( ( rc = _io_stmt_calc_var_ele_count ( * io_stmt . remote_net , * io_stmt . remote_proc_ele , * io_stmt . remote_var_ele , remote_label , io_stmt . iter_cnt ) ) ! = kOkRC )
rc = cwLogError ( rc , " Unable to determine the %s-stmt iteration count based on the iteration control %s-var '%s'. " , local_label , remote_label , cwStringNullGuard ( io_stmt . remote_var_ele - > label ) ) ;
2024-04-22 20:02:40 +00:00
break ;
default :
2024-05-10 19:54:21 +00:00
rc = cwLogError ( kInvalidStateRC , " An unknown %s-stmt element type was encountered. " , local_label ) ;
2024-04-22 20:02:40 +00:00
}
return rc ;
}
2024-05-10 19:54:21 +00:00
void _io_stmt_destroy ( io_stmt_t & s )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
if ( s . local_proc_ele ! = nullptr )
mem : : release ( s . local_proc_ele - > label ) ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
if ( s . local_var_ele ! = nullptr )
mem : : release ( s . local_var_ele - > label ) ;
mem : : release ( s . remote_net_label ) ;
if ( s . remote_proc_ele )
mem : : release ( s . remote_proc_ele - > label ) ;
if ( s . remote_var_ele )
mem : : release ( s . remote_var_ele - > label ) ;
}
void _io_stmt_array_destroy ( io_stmt_t * & io_stmtA , unsigned io_stmtN )
2024-05-08 14:18:43 +00:00
{
2024-05-10 19:54:21 +00:00
if ( io_stmtA ! = nullptr )
{
for ( unsigned i = 0 ; i < io_stmtN ; + + i )
_io_stmt_destroy ( io_stmtA [ i ] ) ;
2024-05-08 14:18:43 +00:00
2024-05-10 19:54:21 +00:00
mem : : release ( io_stmtA ) ;
2024-05-08 14:18:43 +00:00
}
}
2024-05-10 19:54:21 +00:00
rc_t _io_stmt_array_parse ( network_t & net , proc_t * proc , const char * io_label , const object_t * io_dict_cfg , io_stmt_t * & ioArray_Ref , unsigned & ioArrayN_Ref )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc_t rc = kOkRC ;
unsigned stmtAllocN = 0 ;
unsigned stmtN = 0 ;
io_stmt_t * stmtA = nullptr ;
ioArray_Ref = nullptr ;
ioArrayN_Ref = 0 ;
// if there is no io-dict-cfg
if ( io_dict_cfg = = nullptr )
2024-04-22 20:02:40 +00:00
goto errLabel ;
2024-05-10 19:54:21 +00:00
// validate the out-dict
if ( ! io_dict_cfg - > is_dict ( ) )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
cwLogError ( kSyntaxErrorRC , " The '%s' dict in proc instance '%s' is not a valid dictionary. " , io_label , proc - > label ) ;
goto errLabel ;
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
if ( io_dict_cfg - > child_count ( ) = = 0 )
goto errLabel ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
stmtAllocN = io_dict_cfg - > child_count ( ) ;
stmtA = mem : : allocZ < io_stmt_t > ( stmtAllocN ) ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// for each input variable in the 'in' set
for ( unsigned i = 0 ; i < stmtAllocN ; + + i )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
const object_t * io_stmt_pair = io_dict_cfg - > child_ele ( i ) ;
const char * s = nullptr ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// validate the stmt pair syntax
if ( io_stmt_pair = = nullptr
| | ! io_stmt_pair - > is_pair ( )
| | textLength ( io_stmt_pair - > pair_label ( ) ) = = 0
| | io_stmt_pair - > pair_value ( ) = = nullptr
| | ! io_stmt_pair - > pair_value ( ) - > is_string ( )
| | ( io_stmt_pair - > pair_value ( ) - > value ( s ) ) ! = kOkRC
| | textLength ( s ) = = 0 )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( kSyntaxErrorRC , " A syntax error was encoutered while attempting to parse the %s-stmt on the proc %s:%i. " , io_label , cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
stmtN + = 1 ;
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
ioArray_Ref = stmtA ;
ioArrayN_Ref = stmtN ;
errLabel :
if ( rc ! = kOkRC )
_io_stmt_array_destroy ( stmtA , stmtN ) ;
return rc ;
2024-04-22 20:02:40 +00:00
}
// Set 'in_stmt.src_net' based on 'in_stmt.src_net_label'
2024-05-10 19:54:21 +00:00
rc_t _io_stmt_locate_remote_net ( network_t & net , proc_t * proc , io_stmt_t & io_stmt )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc_t rc = kOkRC ;
network_t * remote_net = nullptr ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
io_stmt . remote_net = nullptr ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
if ( io_stmt . remote_net_label = = nullptr )
remote_net = & net ;
2024-04-22 20:02:40 +00:00
else
{
2024-05-10 19:54:21 +00:00
if ( textIsEqual ( io_stmt . remote_net_label , " _ " ) )
2024-09-17 20:33:26 +00:00
remote_net = proc - > ctx - > net ;
2024-04-22 20:02:40 +00:00
else
{
2024-09-17 20:33:26 +00:00
if ( ( remote_net = _io_stmt_find_labeled_network ( * proc - > ctx - > net , io_stmt . remote_net_label ) ) = = nullptr )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The source net '%s' was not found. " , cwStringNullGuard ( io_stmt . remote_net_label ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
}
}
errLabel :
2024-05-10 19:54:21 +00:00
io_stmt . remote_net = remote_net ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
if ( io_stmt . remote_net = = nullptr )
rc = cwLogError ( kSyntaxErrorRC , " No remote net was found. " ) ;
2024-04-22 20:02:40 +00:00
return rc ;
}
2024-05-10 19:54:21 +00:00
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
rc_t _io_stmt_create ( network_t & net ,
proc_t * proc ,
io_stmt_t & io_stmt ,
const char * local_proc_var_str ,
const char * remote_net_proc_var_str ,
const char * local_label ,
const char * remote_label )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc_t rc = kOkRC ;
unsigned local_char_cnt = textLength ( local_proc_var_str ) ;
unsigned remote_char_cnt = textLength ( remote_net_proc_var_str ) ;
unsigned str_char_cnt = std : : max ( local_char_cnt , remote_char_cnt ) ;
2024-05-29 18:06:54 +00:00
//const char* remote_net_label = nullptr;
2024-05-10 19:54:21 +00:00
const char * remote_proc_label = nullptr ;
const char * remote_var_label = nullptr ;
const char * local_proc_label = nullptr ;
const char * local_var_label = nullptr ;
char str [ str_char_cnt + 1 ] ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
io_stmt . remote_proc_ele - > typeId = kRemoteProcTypeId ;
io_stmt . remote_var_ele - > typeId = kRemoteVarTypeId ;
io_stmt . local_proc_ele - > typeId = kLocalProcTypeId ;
io_stmt . local_var_ele - > typeId = kLocalVarTypeId ;
//
// Parse the remote net/proc/var
//
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// put the remote net/proc/var string into a non-const scratch buffer
textCopy ( str , remote_char_cnt + 1 , remote_net_proc_var_str ) ;
// parse the src part into it's 3 parts
if ( ( rc = _io_stmt_parse_net_proc_var_string ( str , io_stmt . remote_net_label , remote_proc_label , remote_var_label ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
cwLogError ( rc , " Unable to parse the '%s' part of an 'io-stmt'. " , remote_label ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
// parse the rem-proc
if ( ( rc = _io_stmt_parse_ele ( remote_proc_label , * io_stmt . remote_proc_ele ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( rc , " Unable to parse the %s-proc from '%s'. " , remote_label , cwStringNullGuard ( str ) ) ;
goto errLabel ;
2024-06-09 20:18:21 +00:00
}
2024-05-10 19:54:21 +00:00
// parse the remote-var
if ( ( rc = _io_stmt_parse_ele ( remote_var_label , * io_stmt . remote_var_ele ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to parse the %s-var from '%s'. " , remote_label , cwStringNullGuard ( str ) ) ;
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
2024-04-22 20:02:40 +00:00
2024-06-09 20:18:21 +00:00
//
// Parse the local proc/var
//
2024-05-08 14:18:43 +00:00
2024-06-09 20:18:21 +00:00
textCopy ( str , local_char_cnt + 1 , local_proc_var_str ) ;
2024-04-22 20:02:40 +00:00
2024-06-09 20:18:21 +00:00
// parse the 'local' part into it's 2 parts
if ( ( rc = _io_stmt_parse_proc_var_string ( str , local_proc_label , local_var_label ) ) ! = kOkRC )
{
cwLogError ( rc , " Unable to parse the '%s' part of an 'io-stmt'. " , local_label ) ;
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
2024-06-09 20:18:21 +00:00
// parse the local-proc
if ( ( rc = _io_stmt_parse_ele ( local_proc_label , * io_stmt . local_proc_ele , true ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to parse the %s-proc from '%s'. " , local_label , cwStringNullGuard ( str ) ) ;
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
2024-06-09 20:18:21 +00:00
// parse the local-var
if ( ( rc = _io_stmt_parse_ele ( local_var_label , * io_stmt . local_var_ele ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to parse the %s-var from '%s'. " , local_label , cwStringNullGuard ( str ) ) ;
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
2024-05-10 19:54:21 +00:00
2024-06-09 20:18:21 +00:00
// get the var class desc. for the local-var (only used by in-stmt)
if ( ( io_stmt . local_var_desc = var_desc_find ( proc - > class_desc , io_stmt . local_var_ele - > label ) ) = = nullptr )
{
rc = cwLogError ( kEleNotFoundRC , " Unable to locate the var class desc for the %s-var from '%s'. " , local_label , cwStringNullGuard ( io_stmt . local_var_ele - > label ) ) ;
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
2024-06-09 20:18:21 +00:00
// get the remote net
if ( ( rc = _io_stmt_locate_remote_net ( net , proc , io_stmt ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to locate the %s-net '%s'. " , remote_label , cwStringNullGuard ( io_stmt . remote_net_label ) ) ;
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
2024-06-09 20:18:21 +00:00
// verify that both the local-proc and local-var are not iterating
if ( io_stmt . local_proc_ele - > is_iter_fl & & io_stmt . local_var_ele - > is_iter_fl )
{
rc = cwLogError ( kSyntaxErrorRC , " Both the '%s' proc and '%s' var cannot be iterating. See:'%s' " , local_label , local_label , cwStringNullGuard ( local_proc_var_str ) ) ;
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
2024-06-09 20:18:21 +00:00
// if the in-var has an sfx_id, or is iterating, then the var needs to be created (the dflt creation process assumes an sfx-id of 0)
if ( io_stmt . local_var_ele - > base_sfx_id ! = kInvalidId | | io_stmt . local_var_ele - > is_iter_fl )
{
io_stmt . in_create_fl = true ;
if ( io_stmt . local_var_ele - > base_sfx_id = = kInvalidId )
io_stmt . local_var_ele - > base_sfx_id = kBaseSfxId ;
}
2024-04-22 20:02:40 +00:00
2024-06-09 20:18:21 +00:00
// if the remote-proc is not iterating and the remote-proc was not given a literal sfx-id and the remote is on the same net as the proc ...
if ( io_stmt . remote_proc_ele - > is_iter_fl = = false & & io_stmt . remote_proc_ele - > base_sfx_id = = kInvalidId & & io_stmt . remote_net = = & net )
io_stmt . remote_proc_ele - > base_sfx_id = proc - > label_sfx_id ; // ... then the remote proc takes this proc's sfx id
// (This results in poly proc's connecting to other poly procs with the same sfx-id by default).
2024-05-10 19:54:21 +00:00
2024-06-09 20:18:21 +00:00
// if this is not an iterating in-stmt ...
if ( ! io_stmt . local_var_ele - > is_iter_fl )
{
io_stmt . iter_cnt = 1 ; // ... then it must be a simple 1:1 connection (Note if in-proc is iterating then it this must also be true)
}
else
{
// if the in-stmt is iterating then determine the in-stmt element which controls the iteration count
if ( ( rc = _io_stmt_determine_iter_count_ctl_ele ( net , proc ,
* io_stmt . local_var_ele ,
* io_stmt . remote_proc_ele ,
* io_stmt . remote_var_ele ,
local_label , remote_label ,
io_stmt . iter_cnt_ctl_ele ) ) ! = kOkRC )
2024-05-08 14:18:43 +00:00
{
2024-06-09 20:18:21 +00:00
rc = cwLogError ( rc , " Unable to determine the iter count control ele. " ) ;
goto errLabel ;
2024-05-10 19:54:21 +00:00
}
2024-06-09 20:18:21 +00:00
// if the local-stmt is iterating then determine the iteration count
if ( ( rc = _io_stmt_determine_iter_count ( net , proc , local_label , remote_label , io_stmt ) ) ! = kOkRC )
{
cwLogError ( rc , " Unable to determine the %s-stmt iteration count. " , local_label ) ;
goto errLabel ;
2024-05-08 14:18:43 +00:00
}
2024-06-09 20:18:21 +00:00
}
2024-05-10 19:54:21 +00:00
errLabel :
2024-06-09 20:18:21 +00:00
if ( rc ! = kOkRC )
_io_stmt_destroy ( io_stmt ) ;
2024-05-10 19:54:21 +00:00
return rc ;
}
rc_t _io_stmt_connect_vars ( network_t & net ,
proc_t * proc ,
const char * local_label ,
const char * remote_label ,
const io_stmt_t * ioStmtA ,
unsigned ioStmtN )
{
rc_t rc = kOkRC ;
// for each io-stmt
for ( unsigned i = 0 ; i < ioStmtN ; + + i )
{
const io_stmt_t & io_stmt = ioStmtA [ i ] ;
// all local-stmts are iterating (but most only iterate once)
for ( unsigned j = 0 ; j < io_stmt . iter_cnt ; + + j )
{
variable_t * local_var = nullptr ;
network_t * remote_net = io_stmt . remote_net ;
proc_t * remote_proc = nullptr ;
variable_t * remote_var = nullptr ;
2024-05-29 18:06:54 +00:00
//const char* local_proc_label = io_stmt.local_proc_ele->label;
2024-05-10 19:54:21 +00:00
const char * local_var_label = io_stmt . local_var_ele - > label ;
const char * remote_proc_label = io_stmt . remote_proc_ele - > label ;
const char * remote_var_label = io_stmt . remote_var_ele - > label ;
unsigned local_var_sfx_id = kInvalidId ;
unsigned remote_proc_sfx_id = kInvalidId ;
unsigned remote_var_sfx_id = kInvalidId ;
// if a literal in-var sfx id was not given ...
if ( io_stmt . local_var_ele - > base_sfx_id = = kInvalidId )
local_var_sfx_id = kBaseSfxId ; // ... then use the default sfx-id
else
local_var_sfx_id = io_stmt . local_var_ele - > base_sfx_id ;
// if a literal src-proc sfx id was not given ...
if ( io_stmt . remote_proc_ele - > base_sfx_id = = kInvalidId )
remote_proc_sfx_id = kBaseSfxId ; // ... then use the sfx_id of the in-var proc
else
remote_proc_sfx_id = io_stmt . remote_proc_ele - > base_sfx_id ; // ... otherwise use the given literal
// if a literal src-var sfx id was not given ...
if ( io_stmt . remote_var_ele - > base_sfx_id = = kInvalidId )
remote_var_sfx_id = kBaseSfxId ; // ... then use the base-sfx-id
else
remote_var_sfx_id = io_stmt . remote_var_ele - > base_sfx_id ; // ... otherwise use the given literal
// When the in-proc is iterating then we incr by the in-proc sfx-id (in this case j will never exceed 0)
// otherwise increment by j - the current iteration count
unsigned iter_incr = io_stmt . local_proc_ele - > is_iter_fl ? proc - > label_sfx_id : j ;
// both in-var and in-proc cannot be iterating
assert ( ! ( io_stmt . local_var_ele - > is_iter_fl & & io_stmt . local_proc_ele - > is_iter_fl ) ) ;
2024-05-08 14:18:43 +00:00
2024-05-10 19:54:21 +00:00
// if the in-var is iterating then incr. the in-var sfx-id
if ( io_stmt . local_var_ele - > is_iter_fl )
local_var_sfx_id + = iter_incr ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// if this is an iterating src-proc then iter the src-proc-sfx-id
if ( io_stmt . remote_proc_ele - > is_iter_fl )
remote_proc_sfx_id + = iter_incr ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// if this is an iterating src-var then iter the src-var-sfx-id
if ( io_stmt . remote_var_ele - > is_iter_fl )
remote_var_sfx_id + = iter_incr ;
// locate local var
if ( ( rc = var_find ( proc , local_var_label , local_var_sfx_id , kAnyChIdx , local_var ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( rc , " The %s-var '%s:%i' was not found. " , local_label , io_stmt . local_var_ele - > label , io_stmt . local_var_ele - > base_sfx_id + j ) ;
goto errLabel ;
}
// locate remote proc instance
if ( ( remote_proc = proc_find ( * remote_net , remote_proc_label , remote_proc_sfx_id ) ) = = nullptr )
{
rc = cwLogError ( kSyntaxErrorRC , " The %s-proc '%s:%i' was not found. " , remote_label , io_stmt . remote_proc_ele - > label , remote_proc_sfx_id ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
// locate remote variable
if ( ( rc = var_find ( remote_proc , remote_var_label , remote_var_sfx_id , kAnyChIdx , remote_var ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( rc , " The %s-var '%s:i' was not found. " , remote_label , io_stmt . remote_var_ele - > label , remote_var_sfx_id ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
// verify that the remote_value type is included in the local_value type flags
if ( cwIsNotFlag ( local_var - > varDesc - > type , remote_var - > varDesc - > type ) )
{
2024-07-01 14:29:34 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The type flags don't match on %s:%s:%i (type:0x%x) %s:%s:%i.%s:%i (type:0x%x). " , local_label , local_var_label , local_var_sfx_id , local_var - > varDesc - > type , remote_label , remote_proc_label , remote_proc_sfx_id , remote_var_label , remote_var_sfx_id , remote_var - > varDesc - > type ) ;
2024-05-10 19:54:21 +00:00
goto errLabel ;
}
// verify that the source exists
if ( remote_var - > value = = nullptr )
{
rc = cwLogError ( kSyntaxErrorRC , " The %s value is null on the connection %s::%s:%i %s:%s:%i.%s:%i . " , remote_label , local_label , local_var_label , local_var_sfx_id , remote_label , remote_proc_label , remote_proc_sfx_id , remote_var_label , remote_var_sfx_id ) ;
goto errLabel ;
}
// if this is an 'in-stmt' ...
if ( io_stmt . local_proc_ele = = & io_stmt . in_proc_ele )
var_connect ( remote_var , local_var ) ;
else
{
// Disconnect any source that was previously connected to the 'in' var
// (we do this for feedback connections (out-stmts), but not for in-stmts)
var_disconnect ( remote_var ) ;
var_connect ( local_var , remote_var ) ; // ... otherwise it is an out-stmt
}
}
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
2024-04-22 20:02:40 +00:00
errLabel :
if ( rc ! = kOkRC )
2024-05-10 19:54:21 +00:00
rc = cwLogError ( rc , " Connection failed on proc '%s:%i'. " , proc - > label , proc - > label_sfx_id ) ;
return rc ;
2024-04-22 20:02:40 +00:00
}
2024-05-05 21:31:42 +00:00
2024-05-10 19:54:21 +00:00
2024-05-08 14:18:43 +00:00
// Find the proxy var associated with the proxied var 'procLabel:varLabel'
2024-05-10 19:54:21 +00:00
const variable_t * _in_stmt_find_proxy_var ( const char * procLabel , const char * varLabel , const variable_t * proxyVarL )
2024-05-05 21:31:42 +00:00
{
for ( const variable_t * proxyVar = proxyVarL ; proxyVar ! = nullptr ; proxyVar = proxyVar - > var_link )
2024-05-08 14:18:43 +00:00
if ( textIsEqual ( proxyVar - > varDesc - > proxyProcLabel , procLabel ) & & textIsEqual ( proxyVar - > varDesc - > proxyVarLabel , varLabel ) )
2024-05-05 21:31:42 +00:00
return proxyVar ;
return nullptr ;
}
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
rc_t _in_stmt_parse_in_list ( network_t & net , proc_t * proc , variable_t * proxyVarL , proc_inst_parse_state_t & pstate )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc_t rc = kOkRC ;
const char * local_label = " in " ;
const char * remote_label = " src " ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
if ( ( rc = _io_stmt_array_parse ( net , proc , " in " , pstate . in_dict_cfg , pstate . iStmtA , pstate . iStmtN ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
goto errLabel ;
2024-05-10 19:54:21 +00:00
for ( unsigned i = 0 ; i < pstate . iStmtN ; + + i )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
io_stmt_t * in_stmt = pstate . iStmtA + i ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
const char * src_net_proc_var_str = nullptr ;
const char * in_proc_var_str = pstate . in_dict_cfg - > child_ele ( i ) - > pair_label ( ) ;
in_stmt - > local_proc_ele = & in_stmt - > in_proc_ele ;
in_stmt - > local_var_ele = & in_stmt - > in_var_ele ;
in_stmt - > remote_proc_ele = & in_stmt - > src_proc_ele ;
in_stmt - > remote_var_ele = & in_stmt - > src_var_ele ;
// The validity of all the data elements in this statement was confirmed previously in _io_stmt_array_parse()
pstate . in_dict_cfg - > child_ele ( i ) - > pair_value ( ) - > value ( src_net_proc_var_str ) ;
2024-04-30 23:58:10 +00:00
2024-05-10 19:54:21 +00:00
assert ( src_net_proc_var_str ! = nullptr ) ;
// create the io_stmt record
if ( ( rc = _io_stmt_create ( net , proc , * in_stmt , in_proc_var_str , src_net_proc_var_str , local_label , remote_label ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( rc , " in-stmt create failed on '%s':%s on proc %s:%i " , in_proc_var_str , src_net_proc_var_str , proc - > label , proc - > label_sfx_id ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
// if the in-var has an sfx_id, or is iterating, then the var needs to be created (the dflt creation process assumes an sfx-id of 0)
if ( in_stmt - > in_var_ele . base_sfx_id ! = kInvalidId | | in_stmt - > in_var_ele . is_iter_fl )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
in_stmt - > in_create_fl = true ;
if ( in_stmt - > in_var_ele . base_sfx_id = = kInvalidId )
in_stmt - > in_var_ele . base_sfx_id = kBaseSfxId ;
2024-04-22 20:02:40 +00:00
}
// create the var
2024-05-10 19:54:21 +00:00
if ( in_stmt - > in_create_fl )
2024-04-22 20:02:40 +00:00
{
2024-05-05 21:31:42 +00:00
const variable_t * proxy_var ;
2024-05-08 14:18:43 +00:00
// a variable cannot be in the 'in' list if it is a proxied variable - because it will
// be connected to a proxy var.
2024-05-10 19:54:21 +00:00
if ( ( proxy_var = _in_stmt_find_proxy_var ( proc - > label , in_stmt - > in_var_ele . label , proxyVarL ) ) ! = nullptr )
2024-05-05 21:31:42 +00:00
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The variable:'%s' cannot be used as the in-var of an 'in' statement if it is a subnet variable: '%s'. " , cwStringNullGuard ( in_stmt - > in_var_ele . label ) , cwStringNullGuard ( proxy_var - > label ) ) ;
2024-05-05 21:31:42 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
for ( unsigned i = 0 ; i < in_stmt - > iter_cnt ; + + i )
2024-04-22 20:02:40 +00:00
{
variable_t * dum = nullptr ;
2024-05-08 14:18:43 +00:00
if ( ( rc = var_create ( proc ,
2024-05-10 19:54:21 +00:00
in_stmt - > local_var_desc - > label ,
in_stmt - > in_var_ele . base_sfx_id + i ,
2024-04-22 20:02:40 +00:00
kInvalidId ,
kAnyChIdx ,
2024-05-10 19:54:21 +00:00
in_stmt - > local_var_desc - > val_cfg ,
2024-04-30 23:58:10 +00:00
kInvalidTFl ,
2024-04-22 20:02:40 +00:00
dum ) ) ! = kOkRC )
{
2024-05-10 19:54:21 +00:00
rc = cwLogError ( rc , " in-stmt var create failed on '%s:%s'. " , cwStringNullGuard ( in_proc_var_str ) , cwStringNullGuard ( src_net_proc_var_str ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
}
2024-04-26 21:12:18 +00:00
}
2024-04-22 20:02:40 +00:00
}
errLabel :
2024-05-10 19:54:21 +00:00
return rc ;
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
rc_t _out_stmt_processing ( network_t & net , proc_t * proc , proc_inst_parse_state_t & pstate )
{
rc_t rc = kOkRC ;
const char * local_label = " src " ;
const char * remote_label = " in " ;
// parse the out-stmt list
if ( ( rc = _io_stmt_array_parse ( net , proc , " out " , pstate . out_dict_cfg , pstate . oStmtA , pstate . oStmtN ) ) ! = kOkRC )
goto errLabel ;
// for each out-stmt
for ( unsigned i = 0 ; i < pstate . oStmtN ; + + i )
{
io_stmt_t * out_stmt = pstate . oStmtA + i ;
const char * in_net_proc_var_str = nullptr ;
const char * src_proc_var_str = pstate . out_dict_cfg - > child_ele ( i ) - > pair_label ( ) ;
out_stmt - > local_proc_ele = & out_stmt - > src_proc_ele ;
out_stmt - > local_var_ele = & out_stmt - > src_var_ele ;
out_stmt - > remote_proc_ele = & out_stmt - > in_proc_ele ;
out_stmt - > remote_var_ele = & out_stmt - > in_var_ele ;
// The validity of all the data elements in this statement was confirmed previously in _io_stmt_array_parse()
pstate . out_dict_cfg - > child_ele ( i ) - > pair_value ( ) - > value ( in_net_proc_var_str ) ;
assert ( in_net_proc_var_str ! = nullptr ) ;
// create the io_stmt record
if ( ( rc = _io_stmt_create ( net , proc , * out_stmt , src_proc_var_str , in_net_proc_var_str , local_label , remote_label ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " out-stmt create failed on '%s':%s on proc %s:%i " , src_proc_var_str , in_net_proc_var_str , proc - > label , proc - > label_sfx_id ) ;
goto errLabel ;
}
}
// create the connections
if ( ( rc = _io_stmt_connect_vars ( net , proc , local_label , remote_label , pstate . oStmtA , pstate . oStmtN ) ) ! = kOkRC )
goto errLabel ;
errLabel :
return rc ;
}
2024-05-06 19:46:12 +00:00
// This function is used to create the variables on subnet procs
// which are represented by interface variables on the subnet proxy (wrapper) proc.
// 'proc' is a proc on the subnet's internal proc list
2024-05-05 21:31:42 +00:00
// 'wrap_varL' is a list of all the variables on the wrapper proc.
2024-05-06 19:46:12 +00:00
// These wrapper variables mirror variables on the internal subnet proc's.
// This function finds the variables in wrap_varL that mirror
// variables in 'proc' and instantiates them.
2024-05-10 19:54:21 +00:00
rc_t _subnet_create_proxied_vars ( proc_t * proc , variable_t * wrap_varL )
2024-05-05 21:31:42 +00:00
{
rc_t rc = kOkRC ;
2024-05-06 19:46:12 +00:00
// for each proxy var
2024-05-05 21:31:42 +00:00
for ( variable_t * wrap_var = wrap_varL ; wrap_var ! = nullptr ; wrap_var = wrap_var - > var_link )
{
2024-05-06 19:46:12 +00:00
// if this proxy var is on this internal proc (proc->label)
if ( textIsEqual ( wrap_var - > varDesc - > proxyProcLabel , proc - > label ) )
2024-05-05 21:31:42 +00:00
{
variable_t * var ;
2024-05-06 19:46:12 +00:00
// create the proxied var
2024-06-05 14:09:13 +00:00
if ( ( rc = var_create ( proc ,
wrap_var - > varDesc - > proxyVarLabel ,
wrap_var - > label_sfx_id ,
kInvalidId ,
wrap_var - > chIdx ,
nullptr ,
kInvalidTFl ,
var ) ) ! = kOkRC )
2024-05-05 21:31:42 +00:00
{
2024-05-06 19:46:12 +00:00
rc = cwLogError ( rc , " Subnet variable creation failed for %s:%s on wrapper variable:%s:%s. " , cwStringNullGuard ( wrap_var - > varDesc - > proxyProcLabel ) , cwStringNullGuard ( wrap_var - > varDesc - > proxyVarLabel ) , cwStringNullGuard ( wrap_var - > proc - > label ) , cwStringNullGuard ( wrap_var - > label ) ) ;
2024-05-05 21:31:42 +00:00
goto errLabel ;
}
2024-05-06 19:46:12 +00:00
//printf("Proxy matched: %s %s %s : flags:%i.\n",proc->label, wrap_var->varDesc->proxyVarLabel, wrap_var->label,wrap_var->varDesc->flags );
2024-05-05 21:31:42 +00:00
var - > flags | = kProxiedVarFl ;
2024-09-16 17:43:52 +00:00
if ( cwIsFlag ( wrap_var - > varDesc - > flags , kUdpOutVarDescFl ) )
2024-05-05 21:31:42 +00:00
var - > flags | = kProxiedOutVarFl ;
}
}
errLabel :
return rc ;
}
2024-05-10 19:54:21 +00:00
variable_t * _subnet_find_proxy_var ( variable_t * wrap_varL , variable_t * var )
2024-05-05 21:31:42 +00:00
{
for ( variable_t * wrap_var = wrap_varL ; wrap_var ! = nullptr ; wrap_var = wrap_var - > var_link )
2024-05-06 19:46:12 +00:00
if ( textIsEqual ( wrap_var - > varDesc - > proxyProcLabel , var - > proc - > label ) & & textIsEqual ( wrap_var - > varDesc - > proxyVarLabel , var - > label ) & & ( wrap_var - > label_sfx_id = = var - > label_sfx_id ) )
2024-05-05 21:31:42 +00:00
return wrap_var ;
return nullptr ;
}
2024-05-10 19:54:21 +00:00
rc_t _subnet_connect_proxy_vars ( proc_t * proc , variable_t * wrap_varL )
2024-05-05 21:31:42 +00:00
{
rc_t rc = kOkRC ;
2024-05-06 19:46:12 +00:00
for ( variable_t * var = proc - > varL ; var ! = nullptr ; var = var - > var_link )
2024-05-05 21:31:42 +00:00
{
if ( cwIsFlag ( var - > flags , kProxiedVarFl ) )
{
variable_t * wrap_var ;
2024-05-10 19:54:21 +00:00
if ( ( wrap_var = _subnet_find_proxy_var ( wrap_varL , var ) ) = = nullptr )
2024-05-05 21:31:42 +00:00
{
2024-05-06 19:46:12 +00:00
rc = cwLogError ( kEleNotFoundRC , " The wrapped variable '%s:%i' not found on '%s:%i'. " , var - > label , var - > label_sfx_id , proc - > label , proc - > label_sfx_id ) ;
2024-05-05 21:31:42 +00:00
goto errLabel ;
}
if ( cwIsFlag ( var - > flags , kProxiedOutVarFl ) )
{
//printf("Proxy connection: %i %s:%i-%s:%i -> %s:%i-%s:%i\n",var->flags,
2024-05-06 19:46:12 +00:00
// var->proc->label,var->proc->label_sfx_id,var->label,var->label_sfx_id,
// wrap_var->proc->label,wrap_var->proc->label_sfx_id,wrap_var->label,wrap_var->label_sfx_id );
2024-05-05 21:31:42 +00:00
var_connect ( var , wrap_var ) ;
}
else
{
//printf("Proxy connection: %i %s:%i-%s:%i -> %s:%i-%s:%i\n",var->flags,
2024-05-06 19:46:12 +00:00
// wrap_var->proc->label,wrap_var->proc->label_sfx_id,wrap_var->label,wrap_var->label_sfx_id,
// var->proc->label,var->proc->label_sfx_id,var->label,var->label_sfx_id );
2024-05-05 21:31:42 +00:00
var_connect ( wrap_var , var ) ;
}
}
}
errLabel :
return rc ;
}
2024-05-06 19:46:12 +00:00
// Check if the var named 'label' already exists in 'proc->varL'.
bool _is_var_proc_already_created ( proc_t * proc , const char * var_label , const proc_inst_parse_state_t & pstate )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
for ( unsigned i = 0 ; i < pstate . iStmtN ; + + i )
if ( textIsEqual ( pstate . iStmtA [ i ] . in_var_ele . label , var_label ) & & pstate . iStmtA [ i ] . in_create_fl )
2024-04-22 20:02:40 +00:00
return true ;
2024-05-06 19:46:12 +00:00
for ( variable_t * var = proc - > varL ; var ! = nullptr ; var = var - > var_link )
2024-05-05 21:31:42 +00:00
if ( textIsEqual ( var - > label , var_label ) )
return true ;
2024-04-22 20:02:40 +00:00
return false ;
}
2024-05-10 19:54:21 +00:00
rc_t _var_map_id_to_index ( proc_t * proc , unsigned vid , unsigned chIdx , unsigned & idxRef ) ;
rc_t _proc_create_var_map ( proc_t * proc )
{
rc_t rc = kOkRC ;
unsigned max_vid = kInvalidId ;
unsigned max_chIdx = 0 ;
2024-06-09 20:18:21 +00:00
variable_t * var = nullptr ;
2024-05-10 19:54:21 +00:00
// determine the max variable vid and max channel index value among all variables
2024-06-09 20:18:21 +00:00
for ( var = proc - > varL ; var ! = nullptr ; var = var - > var_link )
2024-05-10 19:54:21 +00:00
{
2024-06-09 20:18:21 +00:00
2024-05-10 19:54:21 +00:00
if ( var - > vid ! = kInvalidId )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
if ( max_vid = = kInvalidId | | var - > vid > max_vid )
max_vid = var - > vid ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
if ( var - > chIdx ! = kAnyChIdx & & ( var - > chIdx + 1 ) > max_chIdx )
max_chIdx = ( var - > chIdx + 1 ) ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
}
}
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// If there are any variables
if ( max_vid ! = kInvalidId )
{
// create the variable map array
proc - > varMapChN = max_chIdx + 1 ;
proc - > varMapIdN = max_vid + 1 ;
proc - > varMapN = proc - > varMapIdN * proc - > varMapChN ;
proc - > varMapA = mem : : allocZ < variable_t * > ( proc - > varMapN ) ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// assign each variable to a location in the map
for ( variable_t * var = proc - > varL ; var ! = nullptr ; var = var - > var_link )
if ( var - > vid ! = kInvalidId )
{
unsigned idx = kInvalidIdx ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
if ( ( rc = _var_map_id_to_index ( proc , var - > vid , var - > chIdx , idx ) ) ! = kOkRC )
goto errLabel ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// verify that there are not multiple variables per map position
if ( proc - > varMapA [ idx ] ! = nullptr )
{
variable_t * v0 = proc - > varMapA [ idx ] ;
rc = cwLogError ( kInvalidStateRC , " The variable '%s' id:%i ch:%i and '%s' id:%i ch:%i share the same variable map position on proc instance: %s. This is usually cased by duplicate variable id's. " ,
v0 - > label , v0 - > vid , v0 - > chIdx , var - > label , var - > vid , var - > chIdx , proc - > label ) ;
2024-05-08 14:18:43 +00:00
2024-05-10 19:54:21 +00:00
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
2024-05-10 19:54:21 +00:00
// assign this variable to a map position
proc - > varMapA [ idx ] = var ;
2024-05-08 14:18:43 +00:00
2024-05-10 19:54:21 +00:00
if ( var - > chIdx ! = kAnyChIdx & & var - > value = = nullptr )
{
rc = cwLogError ( kInvalidStateRC , " The value of the variable '%s' ch:%i on proc instance:'%s' has not been set. " , var - > label , var - > chIdx , proc - > label ) ;
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
}
errLabel :
return rc ;
}
/*
void _complete_input_connections ( proc_t * proc )
{
for ( variable_t * var = proc - > varL ; var ! = nullptr ; var = var - > var_link )
if ( var - > chIdx = = kAnyChIdx & & is_connected_to_source_proc ( var ) )
{
variable_t * base_src_var = var - > src_var ;
// since 'var' is on the 'any' channel the 'src' var must also be on the 'any' channel
assert ( base_src_var - > chIdx = = kAnyChIdx ) ;
//printf("%s %s\n",proc->label,var->label);
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// for each var channel in the input var
for ( variable_t * in_var = var - > ch_link ; in_var ! = nullptr ; in_var = in_var - > ch_link )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
// locate the matching channel on the 'src' var
variable_t * svar = base_src_var ;
for ( ; svar ! = nullptr ; svar = svar - > ch_link )
if ( svar - > chIdx = = in_var - > chIdx )
break ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// connect the src->input var
_connect_vars ( svar = = nullptr ? base_src_var : svar , in_var ) ;
2024-04-22 20:02:40 +00:00
}
2024-05-10 19:54:21 +00:00
}
}
*/
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
rc_t _proc_set_log_flags ( proc_t * proc , const object_t * log_labels )
{
rc_t rc = kOkRC ;
if ( log_labels = = nullptr )
return rc ;
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
if ( ! log_labels - > is_dict ( ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The log spec on '%s:%i' is not a dictionary. " , cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
for ( unsigned i = 0 ; i < log_labels - > child_count ( ) ; + + i )
{
const object_t * pair ;
unsigned sfx_id ;
if ( ( pair = log_labels - > child_ele ( i ) ) = = nullptr | | pair - > pair_label ( ) = = nullptr | | pair - > pair_value ( ) = = nullptr | | ( rc = pair - > pair_value ( ) - > value ( sfx_id ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " Syntax error on log var identifier. " ) ;
goto errLabel ;
}
if ( ( rc = var_set_flags ( proc , kAnyChIdx , pair - > pair_label ( ) , sfx_id , kLogVarFl ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Unable to set var flags on '%s:%i' var:'%s:%i'. " , cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id , pair - > pair_label ( ) , sfx_id ) ;
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
}
errLabel :
return rc ;
}
2024-05-10 19:54:21 +00:00
rc_t _proc_call_value_func_on_all_variables ( proc_t * proc )
{
rc_t rc = kOkRC ;
rc_t rc1 = kOkRC ;
for ( unsigned i = 0 ; i < proc - > varMapN ; + + i )
if ( proc - > varMapA [ i ] ! = nullptr & & proc - > varMapA [ i ] - > vid ! = kInvalidId )
{
variable_t * var = proc - > varMapA [ i ] ;
if ( ( rc = var_call_custom_value_func ( var ) ) ! = kOkRC )
rc1 = cwLogError ( rc , " The proc inst instance '%s:%i' reported an invalid valid on variable:%s chIdx:%i. " , var - > proc - > label , var - > proc - > label_sfx_id , var - > label , var - > chIdx ) ;
}
return rc1 ;
}
2024-05-08 14:18:43 +00:00
// Set pstate.proc_label and pstate.label_sfx_id
2024-05-10 19:54:21 +00:00
rc_t _proc_parse_inst_label ( const char * proc_label_str , unsigned system_sfx_id , proc_inst_parse_state_t & pstate )
2024-05-08 14:18:43 +00:00
{
rc_t rc = kOkRC ;
unsigned digitCharN = 0 ;
unsigned sfx_id = kInvalidId ;
unsigned sN = textLength ( proc_label_str ) ;
char s [ sN + 1 ] ;
if ( sN = = 0 )
{
rc = cwLogError ( kSyntaxErrorRC , " A blank proc-instance label was encountered. " ) ;
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
2024-05-08 14:18:43 +00:00
textCopy ( s , sN + 1 , proc_label_str , sN ) ;
// if this label has no digit suffix
if ( ( digitCharN = _digit_suffix_char_count ( s ) ) > 0 )
{
if ( digitCharN = = sN )
{
rc = cwLogError ( kSyntaxErrorRC , " A proc-instance label ('%s') was encountered that appears to be a number rather than identifier. " , s ) ;
goto errLabel ;
}
else
{
if ( string_to_number ( s + sN - digitCharN , sfx_id ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " A proc-instance numeric suffix (%s) could not be converted into an integer. " , s ) ;
goto errLabel ;
}
s [ sN - digitCharN ] = ' \0 ' ;
}
}
// if the parsed sfx-id did not exist
if ( sfx_id = = kInvalidId )
{
sfx_id = system_sfx_id = = kInvalidId ? kBaseSfxId : system_sfx_id ;
}
// be sure the parsed sfx-id does not conflict with the system provided sfx-id
if ( system_sfx_id ! = kInvalidId & & sfx_id ! = system_sfx_id )
{
rc = cwLogError ( kInvalidStateRC , " The proc instance '%s' numeric suffix id (%i) conflicts with the system provided sfx id (%i). " , cwStringNullGuard ( proc_label_str ) , pstate . proc_label_sfx_id , system_sfx_id ) ;
goto errLabel ;
}
2024-06-04 12:24:46 +00:00
pstate . proc_label = mem : : duplStr ( s ) ;
pstate . proc_label_sfx_id = sfx_id ;
errLabel :
return rc ;
}
rc_t _proc_parse_cfg ( network_t & net , const object_t * proc_inst_cfg , unsigned system_sfx_id , proc_inst_parse_state_t & pstate )
{
rc_t rc = kOkRC ;
const object_t * arg_dict = nullptr ;
//unsigned sfx_id;
// validate the syntax of the proc_inst_cfg pair
if ( ! _is_non_null_pair ( proc_inst_cfg ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The proc instance cfg. is not a valid pair. " ) ;
goto errLabel ;
}
pstate . proc_label_sfx_id = kInvalidId ;
// extract the proc instance label and (sfx-id suffix)
if ( ( rc = _proc_parse_inst_label ( proc_inst_cfg - > pair_label ( ) , system_sfx_id , pstate ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " Parsing failed on the label and sfx-id for '%s'. " , cwStringNullGuard ( proc_inst_cfg - > pair_label ( ) ) ) ;
goto errLabel ;
}
// verify that the proc instance label is unique
if ( proc_find ( net , pstate . proc_label , pstate . proc_label_sfx_id ) ! = nullptr )
{
rc = cwLogError ( kSyntaxErrorRC , " The proc instance label '%s:%i' has already been used. " , pstate . proc_label , pstate . proc_label_sfx_id ) ;
goto errLabel ;
}
// get the proc instance class label
if ( ( rc = proc_inst_cfg - > pair_value ( ) - > getv ( " class " , pstate . proc_clas_label ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " The proc instance cfg. %s:%i is missing: 'type'. " , pstate . proc_label , pstate . proc_label_sfx_id ) ;
goto errLabel ;
}
// parse the optional args
if ( ( rc = proc_inst_cfg - > pair_value ( ) - > getv_opt ( " args " , arg_dict ,
" in " , pstate . in_dict_cfg ,
" out " , pstate . out_dict_cfg ,
" preset " , pstate . preset_labels ,
" log " , pstate . log_labels ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " The proc instance cfg. '%s:%i' missing: 'type'. " , pstate . proc_label , pstate . proc_label_sfx_id ) ;
goto errLabel ;
}
// if an argument dict was given in the proc instance cfg
if ( arg_dict ! = nullptr )
{
//bool rptErrFl = true;
// verify the arg. dict is actually a dict.
if ( ! arg_dict - > is_dict ( ) )
{
cwLogError ( kSyntaxErrorRC , " The proc instance argument dictionary on proc instance '%s:%i' is not a dictionary. " , pstate . proc_label , pstate . proc_label_sfx_id ) ;
goto errLabel ;
}
pstate . arg_cfg = arg_dict ;
}
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( kSyntaxErrorRC , " Configuration parsing failed on proc instance: '%s:%i'. " , cwStringNullGuard ( pstate . proc_label ) , pstate . proc_label_sfx_id ) ;
return rc ;
}
//============================================================================================================================================
//
// Class Preset and Arg Value application
//
2024-06-11 00:43:55 +00:00
rc_t _var_channelize ( proc_t * proc , const char * preset_label , const char * var_label , unsigned label_sfx_id , const object_t * value )
2024-06-04 12:24:46 +00:00
{
rc_t rc = kOkRC ;
variable_t * dummy = nullptr ;
var_desc_t * vd = nullptr ;
// verify that a valid value exists
if ( value = = nullptr )
{
2024-06-11 00:43:55 +00:00
rc = cwLogError ( kSyntaxErrorRC , " Unexpected missig value on preset '%s' proc instance '%s:%i-%s:%i'. " , preset_label , proc - > label , proc - > label_sfx_id , cwStringNullGuard ( var_label ) , label_sfx_id ) ;
2024-06-04 12:24:46 +00:00
goto errLabel ;
}
else
{
bool is_var_cfg_type_fl = ( vd = var_desc_find ( proc - > class_desc , var_label ) ) ! = nullptr & & cwIsFlag ( vd - > type , kCfgTFl ) ;
bool is_list_fl = value - > is_list ( ) ;
bool is_list_of_list_fl = is_list_fl & & value - > child_count ( ) > 0 & & value - > child_ele ( 0 ) - > is_container ( ) ;
bool parse_list_fl = ( is_list_fl & & ! is_var_cfg_type_fl ) | | ( is_list_of_list_fl & & is_var_cfg_type_fl ) ;
// if a list of values was given and the var type is not a 'cfg' type or if a list of lists was given
if ( parse_list_fl )
{
// then each value in the list is assigned to the associated channel
for ( unsigned chIdx = 0 ; chIdx < value - > child_count ( ) ; + + chIdx )
2024-06-05 14:09:13 +00:00
if ( ( rc = var_channelize ( proc , var_label , label_sfx_id , chIdx , value - > child_ele ( chIdx ) , kInvalidId , dummy ) ) ! = kOkRC )
2024-06-04 12:24:46 +00:00
goto errLabel ;
}
else // otherwise a single value was given
{
2024-06-05 14:09:13 +00:00
if ( ( rc = var_channelize ( proc , var_label , label_sfx_id , kAnyChIdx , value , kInvalidId , dummy ) ) ! = kOkRC )
2024-06-04 12:24:46 +00:00
goto errLabel ;
}
}
errLabel :
return rc ;
}
2024-06-11 00:43:55 +00:00
rc_t _preset_channelize_vars ( proc_t * proc , const char * preset_label , const object_t * preset_cfg )
2024-06-04 12:24:46 +00:00
{
rc_t rc = kOkRC ;
//cwLogInfo("Channelizing '%s' preset %i vars for '%s'.",type_src_label, preset_cfg==nullptr ? 0 : preset_cfg->child_count(), proc->label );
// validate the syntax of the preset record
if ( ! preset_cfg - > is_dict ( ) )
{
2024-06-11 00:43:55 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The preset record '%s' on'%s' is not a dictionary. " , preset_label , proc - > class_desc - > label ) ;
2024-06-04 12:24:46 +00:00
goto errLabel ;
}
// for each preset variable
for ( unsigned i = 0 ; i < preset_cfg - > child_count ( ) ; + + i )
{
const object_t * value = preset_cfg - > child_ele ( i ) - > pair_value ( ) ;
const char * var_label = preset_cfg - > child_ele ( i ) - > pair_label ( ) ;
//cwLogInfo("variable:%s",var_label);
2024-06-11 00:43:55 +00:00
if ( ( rc = _var_channelize ( proc , preset_label , var_label , kBaseSfxId , value ) ) ! = kOkRC )
2024-06-04 12:24:46 +00:00
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
errLabel :
2024-06-04 12:24:46 +00:00
if ( rc ! = kOkRC )
2024-06-11 00:43:55 +00:00
rc = cwLogError ( rc , " Apply preset failed on proc instance:%s:%i class:%s preset:%s. " , proc - > label , proc - > label_sfx_id , proc - > class_desc - > label , preset_label ) ;
2024-06-04 12:24:46 +00:00
2024-05-08 14:18:43 +00:00
return rc ;
}
2024-06-04 12:24:46 +00:00
2024-04-22 20:02:40 +00:00
2024-06-04 12:24:46 +00:00
rc_t _class_preset_channelize_vars ( proc_t * proc , const char * preset_label )
2024-04-22 20:02:40 +00:00
{
2024-06-04 12:24:46 +00:00
rc_t rc = kOkRC ;
const class_preset_t * pr ;
2024-04-22 20:02:40 +00:00
2024-06-04 12:24:46 +00:00
if ( preset_label = = nullptr )
return kOkRC ;
2024-05-08 14:18:43 +00:00
2024-06-04 12:24:46 +00:00
// locate the requestd preset record
if ( ( pr = class_preset_find ( proc - > class_desc , preset_label ) ) = = nullptr )
2024-05-08 14:18:43 +00:00
{
2024-06-11 00:43:55 +00:00
rc = cwLogError ( kInvalidIdRC , " The preset '%s' could not be found for the proc instance '%s:%i'. " , preset_label , proc - > label , proc - > label_sfx_id ) ;
2024-05-08 14:18:43 +00:00
goto errLabel ;
}
2024-06-11 00:43:55 +00:00
rc = _preset_channelize_vars ( proc , preset_label , pr - > cfg ) ;
2024-04-22 20:02:40 +00:00
2024-06-04 12:24:46 +00:00
errLabel :
return rc ;
}
rc_t _class_apply_presets ( proc_t * proc , const object_t * preset_labels )
{
rc_t rc = kOkRC ;
const char * s = nullptr ;
2024-04-22 20:02:40 +00:00
2024-06-04 12:24:46 +00:00
// if preset_labels is a string
if ( preset_labels - > is_string ( ) & & preset_labels - > value ( s ) = = kOkRC )
return _class_preset_channelize_vars ( proc , s ) ;
2024-04-22 20:02:40 +00:00
2024-06-04 12:24:46 +00:00
// if the preset_labels is not a list
if ( ! preset_labels - > is_list ( ) )
rc = cwLogError ( kSyntaxErrorRC , " The preset list on proc instance '%s' is neither a list nor a string. " , proc - > label ) ;
else
2024-04-22 20:02:40 +00:00
{
2024-06-04 12:24:46 +00:00
// preset_labels is a list.
// for each label listed in the preset label list
for ( unsigned i = 0 ; i < preset_labels - > child_count ( ) ; + + i )
2024-04-22 20:02:40 +00:00
{
2024-06-04 12:24:46 +00:00
const object_t * label_obj = preset_labels - > child_ele ( i ) ;
2024-04-22 20:02:40 +00:00
2024-06-04 12:24:46 +00:00
// verify that the label is a strng
if ( ! label_obj - > is_string ( ) | | label_obj - > value ( s ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " The preset list does not contain string on proc instance '%s'. " , proc - > label ) ;
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
2024-06-04 12:24:46 +00:00
// apply a preset label
if ( ( rc = _class_preset_channelize_vars ( proc , s ) ) ! = kOkRC )
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
}
2024-06-04 12:24:46 +00:00
errLabel :
2024-04-22 20:02:40 +00:00
return rc ;
}
2024-06-05 14:09:13 +00:00
rc_t _process_args_stmt ( proc_t * proc , const object_t * arg_cfg )
{
rc_t rc = kOkRC ;
if ( arg_cfg = = nullptr )
return rc ;
unsigned argN = arg_cfg - > child_count ( ) ;
for ( unsigned i = 0 ; i < argN ; + + i )
{
const object_t * arg_pair = arg_cfg - > child_ele ( i ) ;
io_ele_t r ;
// validate the arg pair
if ( arg_pair = = nullptr | | ! arg_pair - > is_pair ( ) | | arg_pair - > pair_label ( ) = = nullptr | | arg_pair - > pair_value ( ) = = nullptr )
{
rc = cwLogError ( kSyntaxErrorRC , " Invalid 'arg' pair. " ) ;
goto errLabel ;
}
// parse the var label string
if ( ( rc = _io_stmt_parse_ele ( arg_pair - > pair_label ( ) , r ) ) ! = kOkRC )
{
goto errLabel ;
}
// if the arg expr is not iterating then set the iter count to 1
if ( r . sfx_id_count = = kInvalidCnt )
r . sfx_id_count = 1 ;
// if no base sfx id was given then set the base sfx id to kBaseSfxId
if ( r . base_sfx_id = = kInvalidId )
r . base_sfx_id = kBaseSfxId ;
//
for ( unsigned sfx_id = r . base_sfx_id ; sfx_id < r . base_sfx_id + r . sfx_id_count ; + + sfx_id )
{
// if this var has not been created yet - then create it
if ( ! var_exists ( proc , r . label , sfx_id , kAnyChIdx ) )
{
variable_t * dum = nullptr ;
if ( ( rc = var_create ( proc ,
r . label ,
sfx_id ,
kInvalidId ,
kAnyChIdx ,
nullptr ,
kInvalidTFl ,
dum ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Variable create failed on '%s %s:%i'. " , cwStringNullGuard ( proc - > label ) , cwStringNullGuard ( r . label ) , sfx_id ) ;
goto errLabel ;
}
}
2024-06-11 00:43:55 +00:00
if ( ( rc = _var_channelize ( proc , " args " , r . label , sfx_id , arg_pair - > pair_value ( ) ) ) ! = kOkRC )
2024-06-05 14:09:13 +00:00
{
rc = cwLogError ( rc , " Channeliize failed on '%s %s:%i'. " , cwStringNullGuard ( proc - > label ) , cwStringNullGuard ( r . label ) , sfx_id ) ;
goto errLabel ;
}
}
2024-06-10 20:37:27 +00:00
mem : : release ( r . label ) ;
2024-06-05 14:09:13 +00:00
}
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " 'args' processing failed on proc '%s'. " , cwStringNullGuard ( proc - > label ) ) ;
return rc ;
}
2024-09-20 22:11:30 +00:00
rc_t _process_net_preset ( proc_t * proc , const object_t * net_preset_cfgD )
{
rc_t rc = kOkRC ;
const object_t * proc_preset_cfg ;
// if no network preset dict exists or if this proc. is not mentioned in it then there is nothing to do
if ( net_preset_cfgD = = nullptr | | ( proc_preset_cfg = net_preset_cfgD - > find_child ( proc - > label ) ) = = nullptr )
return rc ;
switch ( proc_preset_cfg - > type_id ( ) )
{
case kDictTId :
if ( ( rc = _process_args_stmt ( proc , proc_preset_cfg ) ) ! = kOkRC )
goto errLabel ;
break ;
case kListTId :
case kStringTId :
if ( ( rc = _class_apply_presets ( proc , proc_preset_cfg ) ) ! = kOkRC )
goto errLabel ;
break ;
default :
rc = cwLogError ( kInvalidStateRC , " A network preset must be either a dictionary, list or string. " ) ;
goto errLabel ;
break ;
}
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Network preset application failed for proc instance:%s. " , cwStringNullGuard ( proc - > label ) ) ;
return rc ;
}
2024-05-10 19:54:21 +00:00
void _pstate_destroy ( proc_inst_parse_state_t pstate )
2024-04-22 20:02:40 +00:00
{
2024-05-10 19:54:21 +00:00
_io_stmt_array_destroy ( pstate . iStmtA , pstate . iStmtN ) ;
_io_stmt_array_destroy ( pstate . oStmtA , pstate . oStmtN ) ;
2024-05-08 14:18:43 +00:00
mem : : release ( pstate . proc_label ) ;
2024-04-22 20:02:40 +00:00
}
2024-05-19 19:24:33 +00:00
// Count of proc instances which exist in the network with a given class.
2024-04-22 20:02:40 +00:00
unsigned _poly_copy_count ( const network_t & net , const char * proc_clas_label )
{
unsigned n = 0 ;
2024-10-12 19:27:33 +00:00
for ( unsigned i = 0 ; i < net . procN ; + + i )
if ( textIsEqual ( net . procA [ i ] - > class_desc - > label , proc_clas_label ) )
2024-04-22 20:02:40 +00:00
+ + n ;
return n ;
}
2024-05-10 19:54:21 +00:00
rc_t _proc_create ( flow_t * p ,
const object_t * proc_inst_cfg ,
unsigned sfx_id ,
network_t & net ,
variable_t * proxyVarL ,
2024-09-20 22:11:30 +00:00
const object_t * net_preset_cfgD ,
2024-05-19 19:24:33 +00:00
proc_t * & proc_ref )
2024-04-22 20:02:40 +00:00
{
2024-09-20 22:11:30 +00:00
rc_t rc = kOkRC ;
proc_inst_parse_state_t pstate = { } ;
proc_t * proc = nullptr ;
class_desc_t * class_desc = nullptr ;
const object_t * proc_preset_cfg = nullptr ;
2024-04-22 20:02:40 +00:00
2024-05-06 19:46:12 +00:00
proc_ref = nullptr ;
2024-04-22 20:02:40 +00:00
2024-05-06 19:46:12 +00:00
// parse the proc instance configuration
2024-05-10 19:54:21 +00:00
if ( ( rc = _proc_parse_cfg ( net , proc_inst_cfg , sfx_id , pstate ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
goto errLabel ;
2024-05-05 21:31:42 +00:00
// locate the proc class desc
2024-05-06 19:46:12 +00:00
if ( ( class_desc = class_desc_find ( p , pstate . proc_clas_label ) ) = = nullptr )
2024-04-22 20:02:40 +00:00
{
2024-05-06 19:46:12 +00:00
rc = cwLogError ( kSyntaxErrorRC , " The flow class '%s' was not found. " , cwStringNullGuard ( pstate . proc_clas_label ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
// if the poly proc instance count has been exceeded for this proc inst class ...
2024-05-06 19:46:12 +00:00
if ( class_desc - > polyLimitN > 0 & & _poly_copy_count ( net , pstate . proc_clas_label ) > = class_desc - > polyLimitN )
2024-04-22 20:02:40 +00:00
{
// ... then silently skip this instantiation
2024-05-08 14:18:43 +00:00
cwLogDebug ( " The poly class copy count has been exceeded for '%s' - skipping instantiation of sfx_id:%i. " , pstate . proc_label , pstate . proc_label_sfx_id ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-06 19:46:12 +00:00
// instantiate the proc instance
proc = mem : : allocZ < proc_t > ( ) ;
2024-04-22 20:02:40 +00:00
2024-05-06 19:46:12 +00:00
proc - > ctx = p ;
proc - > label = mem : : duplStr ( pstate . proc_label ) ;
2024-05-08 14:18:43 +00:00
proc - > label_sfx_id = pstate . proc_label_sfx_id ;
2024-05-06 19:46:12 +00:00
proc - > proc_cfg = proc_inst_cfg - > pair_value ( ) ;
proc - > class_desc = class_desc ;
proc - > net = & net ;
2024-04-22 20:02:40 +00:00
2024-05-24 20:36:43 +00:00
// parse the in-list ,fill in pstate.in_array, and create var instances for var's referenced by in-list
2024-05-10 19:54:21 +00:00
if ( ( rc = _in_stmt_parse_in_list ( net , proc , proxyVarL , pstate ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-05-08 14:18:43 +00:00
rc = cwLogError ( rc , " in-list parse failed on proc inst instance '%s:%i'. " , cwStringNullGuard ( proc - > label ) , pstate . proc_label_sfx_id ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
// if this is a subnet wrapper proc then create the vars that are connected to the proxy vars
2024-05-10 19:54:21 +00:00
if ( ( rc = _subnet_create_proxied_vars ( proc , proxyVarL ) ) ! = kOkRC )
2024-05-05 21:31:42 +00:00
{
2024-05-08 14:18:43 +00:00
rc = cwLogError ( rc , " Proxy vars create failed on proc inst instance '%s:%i'. " , cwStringNullGuard ( proc - > label ) , pstate . proc_label_sfx_id ) ;
2024-05-05 21:31:42 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
// Instantiate all the variables in the class description - that were not already created in _in_stmt_parse_in_list()
2024-05-19 19:24:33 +00:00
// or _subnet_create_proxied_vars().
2024-04-22 20:02:40 +00:00
for ( var_desc_t * vd = class_desc - > varDescL ; vd ! = nullptr ; vd = vd - > link )
2024-05-06 19:46:12 +00:00
if ( ! _is_var_proc_already_created ( proc , vd - > label , pstate ) & & cwIsNotFlag ( vd - > type , kRuntimeTFl ) )
2024-04-22 20:02:40 +00:00
{
variable_t * var = nullptr ;
2024-05-06 19:46:12 +00:00
if ( ( rc = var_create ( proc , vd - > label , kBaseSfxId , kInvalidId , kAnyChIdx , vd - > val_cfg , kInvalidTFl , var ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-06 19:46:12 +00:00
// All the variables that can be used by this proc instance have now been created
2024-04-22 20:02:40 +00:00
// and the chIdx of each variable is set to 'any'.
2024-04-30 23:58:10 +00:00
2024-04-22 20:02:40 +00:00
// If a 'preset' field was included in the class cfg then apply the specified class preset
2024-05-19 19:24:33 +00:00
// Note that the 'preset' field can be a string or list of strings.
2024-04-22 20:02:40 +00:00
if ( pstate . preset_labels ! = nullptr )
2024-05-06 19:46:12 +00:00
if ( ( rc = _class_apply_presets ( proc , pstate . preset_labels ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
goto errLabel ;
2024-05-19 19:24:33 +00:00
// The requested class presets values have now been set and those variables
2024-04-22 20:02:40 +00:00
// that were expressed with a list have numeric channel indexes assigned.
2024-05-08 14:18:43 +00:00
// Apply the proc inst instance 'args:{}' values.
2024-04-22 20:02:40 +00:00
if ( pstate . arg_cfg ! = nullptr )
2024-04-26 21:12:18 +00:00
{
2024-06-05 14:09:13 +00:00
if ( ( rc = _process_args_stmt ( proc , pstate . arg_cfg ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
goto errLabel ;
2024-09-20 22:11:30 +00:00
}
// If the the network preset holds a preset for this proc
if ( net_preset_cfgD ! = nullptr & & ( proc_preset_cfg = net_preset_cfgD - > find_child ( proc - > label ) ) ! = nullptr )
{
if ( ( rc = _process_net_preset ( proc , net_preset_cfgD ) ) ! = kOkRC )
goto errLabel ;
2024-04-26 21:12:18 +00:00
}
2024-05-06 19:46:12 +00:00
// All the proc instance arg values have now been set and those variables
2024-04-22 20:02:40 +00:00
// that were expressed with a list have numeric channel indexes assigned.
2024-05-19 19:24:33 +00:00
// Connect the var's that are referenced in the in-stmt to their respective sources
2024-05-10 19:54:21 +00:00
if ( ( rc = _io_stmt_connect_vars ( net , proc , " in " , " src " , pstate . iStmtA , pstate . iStmtN ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-04-30 23:58:10 +00:00
rc = cwLogError ( rc , " Input connection processing failed. " ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-10 19:54:21 +00:00
2024-05-19 19:24:33 +00:00
// Connect the proxied vars in this subnet proc to their respective proxy vars.
2024-05-10 19:54:21 +00:00
if ( ( rc = _subnet_connect_proxy_vars ( proc , proxyVarL ) ) ! = kOkRC )
2024-05-05 21:31:42 +00:00
{
2024-05-06 19:46:12 +00:00
rc = cwLogError ( rc , " Proxy connection processing failed. " ) ;
2024-05-05 21:31:42 +00:00
goto errLabel ;
}
2024-05-08 14:18:43 +00:00
// Complete the instantiation of the proc inst instance by calling the custom proc instance creation function.
2024-04-22 20:02:40 +00:00
2024-05-06 19:46:12 +00:00
// Call the custom proc instance create() function.
if ( ( rc = class_desc - > members - > create ( proc ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-04-30 23:58:10 +00:00
rc = cwLogError ( kInvalidArgRC , " Custom instantiation failed. " ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-06 19:46:12 +00:00
// Create the proc instance->varMap[] lookup array
2024-05-10 19:54:21 +00:00
if ( ( rc = _proc_create_var_map ( proc ) ) ! = kOkRC )
2024-04-30 23:58:10 +00:00
{
rc = cwLogError ( rc , " Variable map creation failed. " ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
2024-04-30 23:58:10 +00:00
}
2024-04-22 20:02:40 +00:00
2024-05-10 19:54:21 +00:00
// create the feedback connections
_out_stmt_processing ( net , proc , pstate ) ;
2024-04-22 20:02:40 +00:00
// the custom creation function may have added channels to in-list vars fix up those connections here.
2024-05-06 19:46:12 +00:00
//_complete_input_connections(proc);
2024-04-22 20:02:40 +00:00
2024-05-06 19:46:12 +00:00
// set the log flags again so that vars created by the proc instance can be included in the log output
2024-05-10 19:54:21 +00:00
if ( ( rc = _proc_set_log_flags ( proc , pstate . log_labels ) ) ! = kOkRC )
2024-04-30 23:58:10 +00:00
goto errLabel ;
2024-05-06 19:46:12 +00:00
// call the 'value()' function to inform the proc instance of the current value of all of it's variables.
2024-05-10 19:54:21 +00:00
if ( ( rc = _proc_call_value_func_on_all_variables ( proc ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
goto errLabel ;
2024-05-19 19:24:33 +00:00
// validate the proc's state.
2024-05-06 19:46:12 +00:00
if ( ( rc = proc_validate ( proc ) ) ! = kOkRC )
2024-04-30 23:58:10 +00:00
{
2024-05-08 14:18:43 +00:00
rc = cwLogError ( rc , " proc inst instance validation failed. " ) ;
2024-04-30 23:58:10 +00:00
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
2024-05-06 19:46:12 +00:00
proc_ref = proc ;
2024-04-22 20:02:40 +00:00
errLabel :
if ( rc ! = kOkRC )
2024-04-30 23:58:10 +00:00
{
2024-05-08 14:18:43 +00:00
rc = cwLogError ( rc , " Proc instantiation failed on '%s:%i'. " , cwStringNullGuard ( pstate . proc_label ) , pstate . proc_label_sfx_id ) ;
2024-05-06 19:46:12 +00:00
proc_destroy ( proc ) ;
2024-04-30 23:58:10 +00:00
}
2024-05-10 19:54:21 +00:00
_pstate_destroy ( pstate ) ;
2024-04-22 20:02:40 +00:00
return rc ;
}
2024-05-19 19:24:33 +00:00
//
// Network preset pair table
//
rc_t _network_preset_pair_count ( const network_t & net , unsigned & count_ref )
{
rc_t rc = kOkRC ;
count_ref = 0 ;
unsigned n = 0 ;
2024-10-12 19:27:33 +00:00
for ( unsigned i = 0 ; i < net . procN ; + + i )
2024-05-19 19:24:33 +00:00
{
2024-10-12 19:27:33 +00:00
const proc_t * proc = net . procA [ i ] ;
2024-05-19 19:24:33 +00:00
for ( const variable_t * var = proc - > varL ; var ! = nullptr ; var = var - > var_link )
if ( var - > chIdx = = kAnyChIdx )
{
unsigned varChCnt = 0 ;
if ( ( rc = var_channel_count ( var , varChCnt ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The network preset pair count operation failed. " ) ;
goto errLabel ;
}
n + = varChCnt + 1 ; // Add 1 for the kAnyCh
}
}
count_ref = n ;
errLabel :
return rc ;
}
rc_t _network_preset_pair_fill_table ( const network_t & net , network_preset_pair_t * nppA , unsigned nppN )
{
rc_t rc = kOkRC ;
unsigned j = 0 ;
2024-10-12 19:27:33 +00:00
for ( unsigned i = 0 ; i < net . procN ; + + i )
2024-05-19 19:24:33 +00:00
{
2024-10-12 19:27:33 +00:00
const proc_t * proc = net . procA [ i ] ;
2024-05-19 19:24:33 +00:00
for ( const variable_t * var = proc - > varL ; var ! = nullptr ; var = var - > var_link )
if ( var - > chIdx = = kAnyChIdx )
{
unsigned varChCnt = 0 ;
if ( ( rc = var_channel_count ( var , varChCnt ) ) ! = kOkRC )
goto errLabel ;
unsigned k = 0 ;
for ( const variable_t * ch_var = var ; ch_var ! = nullptr ; ch_var = ch_var - > ch_link , + + j , + + k )
{
if ( j > = nppN )
{
rc = cwLogError ( kInvalidStateRC , " Unexpected end of preset-pair table was encountered. " ) ;
goto errLabel ;
}
nppA [ j ] . proc = proc ;
nppA [ j ] . var = ch_var ;
nppA [ j ] . chIdx = var - > chIdx ; ;
nppA [ j ] . chN = varChCnt ; ;
}
if ( k ! = varChCnt + 1 )
{
rc = cwLogError ( kInvalidStateRC , " An inconsistent var channel count was encountered on '%s:%i'-'%s:%i'. " ,
cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ,
cwStringNullGuard ( var - > label ) , var - > label_sfx_id ) ;
goto errLabel ;
}
}
}
if ( j ! = nppN )
rc = cwLogError ( kInvalidStateRC , " The expected count of entries in the preset_pair table (%i) does not match the actual count (%i). " , nppN , j ) ;
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Preset pair table fill failed. " ) ;
return rc ;
}
rc_t _network_preset_pair_create_table ( network_t & net )
{
rc_t rc = kOkRC ;
unsigned pair_count = 0 ;
// get the total count of variables in this network
if ( ( rc = _network_preset_pair_count ( net , pair_count ) ) ! = kOkRC )
goto errLabel ;
2024-05-21 22:53:11 +00:00
// allocate the preset pair table
2024-05-19 19:24:33 +00:00
net . preset_pairA = mem : : allocZ < network_preset_pair_t > ( pair_count ) ;
net . preset_pairN = pair_count ;
// fill the preset pair table
if ( ( rc = _network_preset_pair_fill_table ( net , net . preset_pairA , net . preset_pairN ) ) ! = kOkRC )
goto errLabel ;
errLabel :
if ( rc ! = kOkRC )
{
rc = cwLogError ( rc , " Network preset pair table create failed. " ) ;
mem : : release ( net . preset_pairA ) ;
net . preset_pairN = 0 ;
}
return rc ;
}
unsigned _network_preset_pair_find_index ( const network_t & net , const variable_t * var )
{
for ( unsigned i = 0 ; i < net . preset_pairN ; + + i )
{
const network_preset_pair_t * npp = net . preset_pairA + i ;
if ( var - > proc = = npp - > proc & & var = = npp - > var )
{
assert ( var - > chIdx = = npp - > var - > chIdx ) ;
return i ;
}
}
return kInvalidIdx ;
}
2024-06-04 12:24:46 +00:00
//==================================================================================================================
2024-05-19 19:24:33 +00:00
//
// Preset processing
//
rc_t _parse_network_proc_label ( const network_t & net , const network_preset_t & network_preset , const char * proc_label , io_ele_t & proc_id )
{
rc_t rc = kOkRC ;
// parse the proc label
if ( ( rc = _io_stmt_parse_ele ( proc_label , proc_id ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " Parse failed on the proc label '%s' of preset '%s'. " , cwStringNullGuard ( proc_label ) , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
}
// set the proc_id base sfx id
if ( proc_id . base_sfx_id = = kInvalidId )
proc_id . base_sfx_id = kBaseSfxId ;
// if not iterating
if ( ! proc_id . is_iter_fl )
{
proc_id . sfx_id_count = 1 ;
}
else
{
if ( proc_id . sfx_id_count = = kInvalidCnt )
2024-05-21 22:53:11 +00:00
proc_id . sfx_id_count = proc_mult_count ( net , proc_id . label ) ;
2024-05-19 19:24:33 +00:00
}
errLabel :
return rc ;
}
rc_t _parse_network_proc_var_label ( network_t & net , const char * network_preset_label , const object_t * var_pair , const char * proc_label , unsigned proc_label_sfx_id , io_ele_t & var_id )
{
rc_t rc = kOkRC ;
const char * var_label = nullptr ;
if ( var_pair = = nullptr | | ! var_pair - > is_pair ( ) | | ( var_label = var_pair - > pair_label ( ) ) = = nullptr | | var_pair - > pair_value ( ) = = nullptr )
{
rc = cwLogError ( kSyntaxErrorRC , " A syntax error was encountered on a preset pair value on preset '%s:%s'. " , cwStringNullGuard ( network_preset_label ) , cwStringNullGuard ( proc_label ) ) ;
goto errLabel ;
}
//
if ( ( rc = _io_stmt_parse_ele ( var_label , var_id ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Parse failed on the var label of preset '%s:%s:%s'. " , cwStringNullGuard ( network_preset_label ) , cwStringNullGuard ( proc_label ) , cwStringNullGuard ( var_label ) ) ;
goto errLabel ;
}
// set the var_id base sfx id
if ( var_id . base_sfx_id = = kInvalidId )
var_id . base_sfx_id = kBaseSfxId ;
// if not iterating
if ( ! var_id . is_iter_fl )
{
var_id . sfx_id_count = 1 ;
}
else
{
proc_t * proc ;
// find the var proc
if ( ( proc = proc_find ( net , proc_label , proc_label_sfx_id ) ) = = nullptr )
{
rc = cwLogError ( kEleNotFoundRC , " The proc '%s' could not be found for network preset '%s'. " , cwStringNullGuard ( proc_label ) , cwStringNullGuard ( network_preset_label ) ) ;
goto errLabel ;
}
if ( var_id . sfx_id_count = = kInvalidCnt )
2024-05-21 22:53:11 +00:00
var_id . sfx_id_count = var_mult_count ( proc , var_id . label ) ;
2024-05-19 19:24:33 +00:00
}
errLabel :
return rc ;
}
rc_t _network_preset_get_class_preset ( network_t & net , const char * network_preset_label , const char * proc_label , const object_t * class_preset_label_cfg , const object_t * & class_preset_cfg_ref )
{
rc_t rc = kOkRC ;
const char * class_preset_label = nullptr ; ;
const class_preset_t * class_preset = nullptr ;
2024-05-29 18:06:54 +00:00
//class_desc_t* class_desc = nullptr;
2024-05-19 19:24:33 +00:00
proc_t * proc = nullptr ;
class_preset_cfg_ref = nullptr ;
// get the label of the proc class preset
if ( ( rc = class_preset_label_cfg - > value ( class_preset_label ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The preset label could not be parsed on the preset:'%s:%s' " , cwStringNullGuard ( network_preset_label ) , cwStringNullGuard ( proc_label ) ) ;
goto errLabel ;
}
// locate the proc this preset will be applied to
if ( ( proc = proc_find ( net , proc_label , kBaseSfxId ) ) = = nullptr )
{
rc = cwLogError ( rc , " The proc '%s' could not be found for the preset:'%s' " , cwStringNullGuard ( proc_label ) , cwStringNullGuard ( network_preset_label ) ) ;
goto errLabel ;
}
// get the preset record for this proc/preset_label
if ( ( class_preset = class_preset_find ( proc - > class_desc , class_preset_label ) ) = = nullptr )
{
rc = cwLogError ( rc , " The class description for proc '%s' could not be found for the preset:'%s' " , cwStringNullGuard ( proc_label ) , cwStringNullGuard ( network_preset_label ) ) ;
goto errLabel ;
}
class_preset_cfg_ref = class_preset - > cfg ;
errLabel :
return rc ;
}
rc_t _network_preset_create_channel_value ( network_t & net , network_preset_t & network_preset , proc_t * proc , variable_t * var , unsigned chN , const object_t * value_cfg )
{
rc_t rc = kOkRC ;
unsigned pairTblIdx = kInvalidIdx ;
preset_value_t * preset_value = mem : : allocZ < preset_value_t > ( ) ;
// cfg to value
if ( ( rc = cfg_to_value ( value_cfg , preset_value - > value ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The preset cfg to value conversion failed on '%s:%i'-'%s:%i'. " , cwStringNullGuard ( var - > label ) , var - > label_sfx_id , cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
}
// locate the the
if ( ( pairTblIdx = _network_preset_pair_find_index ( net , var ) ) = = kInvalidIdx )
{
rc = cwLogError ( rc , " The preset pair record could not be found for '%s:%i'-'%s:%i'. " , cwStringNullGuard ( var - > label ) , var - > label_sfx_id , cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
}
preset_value - > proc = proc ;
preset_value - > var = var ;
preset_value - > pairTblIdx = pairTblIdx ;
2024-05-21 22:53:11 +00:00
if ( network_preset . u . vlist . value_head = = nullptr )
network_preset . u . vlist . value_head = preset_value ;
2024-05-19 19:24:33 +00:00
else
2024-05-21 22:53:11 +00:00
network_preset . u . vlist . value_tail - > link = preset_value ;
2024-05-19 19:24:33 +00:00
2024-05-21 22:53:11 +00:00
network_preset . u . vlist . value_tail = preset_value ;
2024-05-19 19:24:33 +00:00
errLabel :
if ( rc ! = kOkRC )
_preset_value_destroy ( preset_value ) ;
return rc ;
}
rc_t _network_preset_find_or_create_variable ( proc_t * proc , const char * var_label , unsigned var_sfx_id , unsigned chIdx , const object_t * value_cfg , bool allow_create_fl , variable_t * & var_ref )
{
rc_t rc = kOkRC ;
variable_t * var = nullptr ;
var_ref = nullptr ;
// if the var was not found on 'chIdx'
if ( ( rc = var_find ( proc , var_label , var_sfx_id , chIdx , var ) ) ! = kOkRC )
{
if ( ! allow_create_fl )
{
rc = cwLogError ( kEleNotFoundRC , " The preset variable '%s:%i' ch:%i could not be found on proc: '%s:%i'. " ,
cwStringNullGuard ( var_label ) , var_sfx_id , chIdx , cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
}
else
{
2024-05-29 18:06:54 +00:00
//variable_t* base_var = nullptr;
2024-05-19 19:24:33 +00:00
// get the base var
if ( ( rc = var_find ( proc , var_label , kBaseSfxId , kAnyChIdx , var ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The base variable '%s:%i' ch:%i could not be found to pre-emptively create the variable '%s:%i' ch:%i on proc: '%s:%i'. " ,
cwStringNullGuard ( var_label ) , kBaseSfxId , kAnyChIdx ,
cwStringNullGuard ( var_label ) , var_sfx_id , chIdx ,
cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
}
// create the variable
if ( ( rc = var_create ( proc , var_label , var_sfx_id , kInvalidId , chIdx , value_cfg , kInvalidTFl , var ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Pre-emptive variable creation failed for '%s:%i' ch:%i on proc:'%s:%i'. " ,
cwStringNullGuard ( var_label ) , var_sfx_id , chIdx ,
cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
}
}
}
var_ref = var ;
errLabel :
return rc ;
}
rc_t _network_preset_create_value ( network_t & net ,
network_preset_t & network_preset ,
const char * proc_label ,
unsigned proc_sfx_id ,
const char * var_label ,
unsigned var_sfx_id ,
const object_t * value_cfg )
{
rc_t rc = kOkRC ;
var_desc_t * var_desc = nullptr ;
proc_t * proc = nullptr ;
// locate the proc this preset will be applied to
if ( ( proc = proc_find ( net , proc_label , proc_sfx_id ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The proc '%s:%i' does not exist. " , cwStringNullGuard ( proc_label ) , proc_sfx_id ) ;
goto errLabel ;
}
else
{
bool is_var_cfg_type_fl = ( var_desc = var_desc_find ( proc - > class_desc , var_label ) ) ! = nullptr & & cwIsFlag ( var_desc - > type , kCfgTFl ) ;
bool is_list_fl = value_cfg - > is_list ( ) ;
bool is_list_of_list_fl = is_list_fl & & value_cfg - > child_count ( ) > 0 & & value_cfg - > child_ele ( 0 ) - > is_list ( ) ;
bool parse_list_fl = ( is_list_fl & & ! is_var_cfg_type_fl ) | | ( is_list_of_list_fl & & is_var_cfg_type_fl ) ;
// Case 1: By default we assume a single variable instance on channel 'kAnyChIdx' ....
unsigned valueN = 1 ;
unsigned chIdx = kAnyChIdx ;
const object_t * vobj = value_cfg ;
// Case 2: ... however if a list of preset values was given and the var type is not a 'cfg' type or if a list of lists was given
// then we are going to iterate through a list of preset values each on a successive channel index
if ( parse_list_fl )
{
chIdx = 0 ;
valueN = value_cfg - > child_count ( ) ;
vobj = value_cfg - > child_ele ( 0 ) ;
}
// Iterate over each channel
for ( unsigned i = 0 ; i < valueN ; + + i )
{
variable_t * var = nullptr ;
// find the var referenced in the preset
if ( ( rc = _network_preset_find_or_create_variable ( proc , var_label , var_sfx_id , chIdx , vobj , false , var ) ) ! = kOkRC )
goto errLabel ;
// create a 'preset_value_t' record and prepend it to 'network_preset.valueL'
if ( ( rc = _network_preset_create_channel_value ( net , network_preset , proc , var , valueN , vobj ) ) ! = kOkRC )
goto errLabel ;
// Case 2:
if ( parse_list_fl )
{
chIdx + = 1 ;
vobj = value_cfg - > child_ele ( i ) ;
}
}
//printf("%s %s:%i-%s:%i\n",network_preset.label,proc_label,proc_sfx_id,var_label,var_sfx_id);
}
errLabel :
return rc ;
}
2024-05-21 22:53:11 +00:00
rc_t _network_preset_parse_dual_label ( network_t & net , const object_t * list_cfg , unsigned idx , const char * pri_sec_label , const char * network_preset_label , const network_preset_t * & vlist_ref )
{
rc_t rc = kOkRC ;
const char * preset_label = nullptr ;
2024-05-29 18:06:54 +00:00
//const preset_value_list_t* vlist = nullptr;
2024-05-21 22:53:11 +00:00
vlist_ref = nullptr ;
if ( ! list_cfg - > child_ele ( idx ) - > is_string ( ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The dual preset list %s preset is not a string on network preset:'%s'. " , pri_sec_label , cwStringNullGuard ( network_preset_label ) ) ;
goto errLabel ;
}
if ( ( rc = list_cfg - > child_ele ( idx ) - > value ( preset_label ) ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " The dual preset %s preset could not be parsed on network preset:'%s'. " , pri_sec_label , cwStringNullGuard ( network_preset_label ) ) ;
goto errLabel ;
}
if ( ( vlist_ref = network_preset_from_label ( net , preset_label ) ) = = nullptr )
{
rc = cwLogError ( kEleNotFoundRC , " The dual preset %s preset could not be found on network preset:'%s'. " , pri_sec_label , cwStringNullGuard ( network_preset_label ) ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
2024-05-19 19:24:33 +00:00
2024-05-21 22:53:11 +00:00
rc_t _network_preset_parse_dual ( flow_t * p , network_t & net , const object_t * dual_list_cfg , network_preset_t & network_preset )
{
rc_t rc = kOkRC ;
if ( dual_list_cfg = = nullptr | | ! dual_list_cfg - > is_list ( ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The dual preset specification is not a list on network preset:'%s'. " , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
}
if ( dual_list_cfg - > child_count ( ) ! = 3 )
{
rc = cwLogError ( kSyntaxErrorRC , " The dual preset list does not have 3 elements on network preset:'%s'. " , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
}
if ( ( rc = _network_preset_parse_dual_label ( net , dual_list_cfg , 0 , " primary " , network_preset . label , network_preset . u . dual . pri ) ) ! = kOkRC )
goto errLabel ;
if ( ( rc = _network_preset_parse_dual_label ( net , dual_list_cfg , 1 , " secondary " , network_preset . label , network_preset . u . dual . sec ) ) ! = kOkRC )
goto errLabel ;
if ( ( rc = dual_list_cfg - > child_ele ( 2 ) - > value ( network_preset . u . dual . coeff ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " The dual preset coeff could not be parsed on network preset:'%s'. " , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
}
network_preset . tid = kPresetDualTId ;
errLabel :
return rc ;
}
2024-05-19 19:24:33 +00:00
2024-05-21 22:53:11 +00:00
rc_t _network_preset_parse_value_list ( flow_t * p , network_t & net , const object_t * network_preset_dict_cfg , network_preset_t & network_preset )
2024-05-19 19:24:33 +00:00
{
rc_t rc = kOkRC ;
unsigned procN = 0 ;
if ( network_preset_dict_cfg = = nullptr | | ! network_preset_dict_cfg - > is_dict ( ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The proc preset dictionary is not a dictionary in network preset:'%s'. " , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
}
2024-05-21 22:53:11 +00:00
network_preset . tid = kPresetVListTId ;
2024-05-19 19:24:33 +00:00
procN = network_preset_dict_cfg - > child_count ( ) ;
// for each proc in the network preset
for ( unsigned i = 0 ; i < procN ; + + i )
{
const object_t * var_dict = nullptr ;
const object_t * proc_preset_pair = network_preset_dict_cfg - > child_ele ( i ) ;
const char * proc_label = nullptr ;
io_ele_t proc_id = { } ;
unsigned varN = 0 ;
// validate the process preset syntax
if ( proc_preset_pair = = nullptr | | ! proc_preset_pair - > is_pair ( ) | | ( proc_label = proc_preset_pair - > pair_label ( ) ) = = nullptr | | proc_preset_pair - > pair_value ( ) = = nullptr )
{
rc = cwLogError ( kSyntaxErrorRC , " A syntax error was encountered on a preset pair on preset '%s'. " , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
}
// parse the proc label
if ( ( rc = _parse_network_proc_label ( net , network_preset , proc_label , proc_id ) ) ! = kOkRC )
goto errLabel ;
// if the preset refers to a proc class preset
if ( proc_preset_pair - > pair_value ( ) - > is_string ( ) )
{
// get the referenced preset cfg from the class desc
if ( ( rc = _network_preset_get_class_preset ( net , network_preset . label , proc_id . label , proc_preset_pair - > pair_value ( ) , var_dict ) ) ! = kOkRC )
goto errLabel ;
}
else // the preset is a dictionary of var/value pairs
{
// if preset is not a dictionary
if ( ! proc_preset_pair - > pair_value ( ) - > is_dict ( ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The preset value dictionary for '%s:%s' is not valid. " , cwStringNullGuard ( network_preset . label ) , cwStringNullGuard ( proc_id . label ) ) ;
goto errLabel ;
}
var_dict = proc_preset_pair - > pair_value ( ) ;
}
// var_dict now refers to a dictionary of var/value pairs for a single proc
varN = var_dict - > child_count ( ) ;
// for each proc/sf_id (the proc label may refer to multiple proc instances)
for ( unsigned j = 0 ; j < proc_id . sfx_id_count ; + + j )
{
// for each variable label:value pair
for ( unsigned k = 0 ; k < varN ; + + k )
{
io_ele_t var_id = { } ;
const object_t * var_pair = var_dict - > child_ele ( k ) ;
2024-05-21 22:53:11 +00:00
unsigned proc_label_sfx_id = proc_id . base_sfx_id + j ;
2024-05-19 19:24:33 +00:00
// parse the preset var label
2024-05-21 22:53:11 +00:00
if ( ( rc = _parse_network_proc_var_label ( net , network_preset . label , var_pair , proc_id . label , proc_label_sfx_id , var_id ) ) ! = kOkRC )
2024-05-19 19:24:33 +00:00
goto errLabel ;
// create a preset for each var:sfx_id pair (the var label may refer to multiple var instances)
for ( unsigned m = 0 ; m < var_id . sfx_id_count ; + + m )
2024-05-21 22:53:11 +00:00
if ( ( rc = _network_preset_create_value ( net , network_preset , proc_id . label , proc_label_sfx_id , var_id . label , var_id . base_sfx_id + m , var_pair - > pair_value ( ) ) ) ! = kOkRC )
2024-05-19 19:24:33 +00:00
goto errLabel ;
mem : : release ( var_id . label ) ;
}
}
mem : : release ( proc_id . label ) ;
}
errLabel :
return rc ;
}
2024-09-20 22:11:30 +00:00
2024-05-19 19:24:33 +00:00
2024-09-20 22:11:30 +00:00
rc_t _network_preset_parse_dict ( flow_t * p , network_t & net , const object_t * preset_cfg )
2024-05-19 19:24:33 +00:00
{
rc_t rc = kOkRC ;
unsigned presetAllocN = 0 ;
if ( preset_cfg = = nullptr )
return rc ;
if ( ! preset_cfg - > is_dict ( ) )
{
rc = cwLogError ( kSyntaxErrorRC , " The network preset list is not a dictionary. " ) ;
goto errLabel ;
}
presetAllocN = preset_cfg - > child_count ( ) ;
net . presetA = mem : : allocZ < network_preset_t > ( presetAllocN ) ;
net . presetN = 0 ;
// parse each preset_label pair
for ( unsigned i = 0 ; i < presetAllocN ; + + i )
{
const object_t * preset_pair_cfg = preset_cfg - > child_ele ( i ) ;
network_preset_t & network_preset = net . presetA [ i ] ;
// validate the network preset pair
2024-05-21 22:53:11 +00:00
if ( preset_pair_cfg = = nullptr | | ! preset_pair_cfg - > is_pair ( ) | | ( network_preset . label = preset_pair_cfg - > pair_label ( ) ) = = nullptr | | preset_pair_cfg - > pair_value ( ) = = nullptr )
2024-05-19 19:24:33 +00:00
{
rc = cwLogError ( kSyntaxErrorRC , " Invalid syntax encountered on a network preset. " ) ;
goto errLabel ;
}
2024-05-21 22:53:11 +00:00
switch ( preset_pair_cfg - > pair_value ( ) - > type_id ( ) )
2024-05-19 19:24:33 +00:00
{
2024-05-21 22:53:11 +00:00
case kDictTId : // 'value-list' preset
if ( ( rc = _network_preset_parse_value_list ( p , net , preset_pair_cfg - > pair_value ( ) , network_preset ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " Network value-list preset parse failed on preset:'%s'. " , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
}
break ;
case kListTId : // dual preset
if ( ( rc = _network_preset_parse_dual ( p , net , preset_pair_cfg - > pair_value ( ) , network_preset ) ) ! = kOkRC )
{
rc = cwLogError ( kSyntaxErrorRC , " Network dual preset parse failed on preset:'%s'. " , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
}
break ;
default :
rc = cwLogError ( kAssertFailRC , " Unknown preset type on network preset: '%s'. " , cwStringNullGuard ( network_preset . label ) ) ;
goto errLabel ;
2024-05-19 19:24:33 +00:00
}
2024-05-21 22:53:11 +00:00
2024-05-19 19:24:33 +00:00
net . presetN + = 1 ;
}
errLabel :
if ( rc ! = kOkRC )
{
_network_preset_array_destroy ( net ) ;
}
return rc ;
}
2024-09-20 22:11:30 +00:00
// Given a network preset label return the dictionary of proc presets that is associated with it.
rc_t _get_network_preset_cfg ( const object_t * presetsCfg , const char * preset_label , const object_t * & preset_ref )
{
rc_t rc = kOkRC ;
preset_ref = nullptr ;
if ( preset_label = = nullptr )
return rc ;
if ( presetsCfg = = nullptr )
{
rc = cwLogError ( kInvalidArgRC , " The network preset '%s' could not be found because there is no network 'presets' dictionary. " , cwStringNullGuard ( preset_label ) ) ;
goto errLabel ;
}
if ( ( preset_ref = presetsCfg - > find_child ( preset_label ) ) = = nullptr )
{
rc = cwLogError ( kEleNotFoundRC , " The network preset '%s' was not found in the 'presets' dictionary. " ) ;
goto errLabel ;
}
switch ( preset_ref - > type_id ( ) )
{
case kDictTId : // this is a dictionary of proc presets
break ;
case kListTId : // this is a 'dual' preset - skip it
preset_ref = nullptr ;
break ;
default :
rc = cwLogError ( kSyntaxErrorRC , " Network presets must be either dictionaries or lists. Preset '%s' is neither. " , cwStringNullGuard ( preset_label ) ) ;
preset_ref = nullptr ;
}
errLabel :
return rc ;
}
2024-05-19 19:24:33 +00:00
template < typename T0 , typename T1 >
rc_t _preset_set_var_from_dual_interp_1 ( variable_t * var , T0 v0 , T1 v1 , double coeff )
{
return var_set ( var , ( T0 ) ( v0 + ( v1 - v0 ) * coeff ) ) ;
}
template < typename T >
rc_t _preset_set_var_from_dual_interp_0 ( variable_t * var , T v0 , const value_t * v1 , double coeff )
{
rc_t rc = kOkRC ;
switch ( v1 - > tflag & kTypeMask )
{
case kUIntTFl :
rc = _preset_set_var_from_dual_interp_1 ( var , v0 , v1 - > u . u , coeff ) ;
break ;
case kIntTFl :
2024-05-21 22:53:11 +00:00
rc = _preset_set_var_from_dual_interp_1 ( var , v0 , v1 - > u . i , coeff ) ;
2024-05-19 19:24:33 +00:00
break ;
case kFloatTFl :
2024-05-21 22:53:11 +00:00
rc = _preset_set_var_from_dual_interp_1 ( var , v0 , v1 - > u . f , coeff ) ;
2024-05-19 19:24:33 +00:00
break ;
2024-05-21 22:53:11 +00:00
case kDoubleTFl :
rc = _preset_set_var_from_dual_interp_1 ( var , v0 , v1 - > u . d , coeff ) ;
2024-05-19 19:24:33 +00:00
break ;
default :
rc = cwLogError ( kInvalidDataTypeRC , " The second operand of a set by interpolation had a non-numeric data type. " ) ;
}
return rc ;
}
rc_t _preset_set_var_from_dual ( const preset_value_t * preset_val , const value_t * value_1 , double coeff )
{
rc_t rc = kOkRC ;
unsigned legalTypeMask = kUIntTFl | kIntTFl | kFloatTFl | kDoubleTFl ;
if ( value_1 = = nullptr | | ( preset_val - > value . tflag & legalTypeMask ) = = 0 )
rc = var_set ( preset_val - > var , & preset_val - > value ) ;
else
{
if ( ( value_1 - > tflag & legalTypeMask ) = = 0 )
{
rc = cwLogError ( kInvalidDataTypeRC , " The type of value-1 (0x%x) is not a scalar number. " , value_1 - > tflag ) ;
goto errLabel ;
}
switch ( preset_val - > value . tflag & legalTypeMask )
{
case kUIntTFl :
rc = _preset_set_var_from_dual_interp_0 ( preset_val - > var , preset_val - > value . u . u , value_1 , coeff ) ;
break ;
case kIntTFl :
rc = _preset_set_var_from_dual_interp_0 ( preset_val - > var , preset_val - > value . u . i , value_1 , coeff ) ;
break ;
case kFloatTFl :
rc = _preset_set_var_from_dual_interp_0 ( preset_val - > var , preset_val - > value . u . f , value_1 , coeff ) ;
break ;
case kDoubleTFl :
rc = _preset_set_var_from_dual_interp_0 ( preset_val - > var , preset_val - > value . u . d , value_1 , coeff ) ;
break ;
default :
rc = cwLogError ( kInvalidDataTypeRC , " The first operand of a set by interpolation had a non-numeric data type. " ) ;
}
}
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Set variable from dual preset failed on '%s:%i'-'%s:%i' ch:0. " ,
cwStringNullGuard ( preset_val - > proc - > label ) , preset_val - > proc - > label_sfx_id ,
cwStringNullGuard ( preset_val - > var - > label ) , preset_val - > var - > label_sfx_id ,
preset_val - > var - > chIdx ) ;
return rc ;
}
2024-05-21 22:53:11 +00:00
rc_t _network_apply_preset ( network_t & net , const preset_value_list_t * vlist , unsigned proc_label_sfx_id )
{
rc_t rc = kOkRC ;
const preset_value_t * preset_value = nullptr ;
for ( preset_value = vlist - > value_head ; preset_value ! = nullptr ; preset_value = preset_value - > link )
{
2024-05-24 20:36:43 +00:00
if ( proc_label_sfx_id = = kInvalidId | | preset_value - > proc - > label_sfx_id = = proc_label_sfx_id )
2024-05-21 22:53:11 +00:00
if ( ( rc = var_set ( preset_value - > var , & preset_value - > value ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Preset value apply failed on '%s:%i'-'%s:%i'. " ,
cwStringNullGuard ( preset_value - > proc - > label ) , preset_value - > proc - > label_sfx_id ,
cwStringNullGuard ( preset_value - > var - > label ) , preset_value - > var - > label_sfx_id ) ;
goto errLabel ;
}
}
errLabel :
return rc ;
}
2024-05-24 20:36:43 +00:00
rc_t _network_apply_dual_preset ( network_t & net , const network_preset_t * net_ps0 , const network_preset_t * net_ps1 , double coeff , unsigned proc_label_sfx_id )
2024-05-21 22:53:11 +00:00
{
rc_t rc = kOkRC ;
// clear the value field of the preset-pair array
for ( unsigned i = 0 ; i < net . preset_pairN ; + + i )
net . preset_pairA [ i ] . value = nullptr ;
// set the value pointer in each of the preset-pair records referenced by preset-1
for ( const preset_value_t * pv1 = net_ps1 - > u . vlist . value_head ; pv1 ! = nullptr ; pv1 = pv1 - > link )
2024-05-24 20:36:43 +00:00
if ( proc_label_sfx_id = = kInvalidId | | pv1 - > proc - > label_sfx_id = = proc_label_sfx_id )
2024-05-21 22:53:11 +00:00
{
2024-05-24 20:36:43 +00:00
if ( pv1 - > var - > chIdx ! = kAnyChIdx )
net . preset_pairA [ pv1 - > pairTblIdx ] . value = & pv1 - > value ;
else
2024-05-21 22:53:11 +00:00
{
2024-05-24 20:36:43 +00:00
for ( unsigned i = 0 ; i < net . preset_pairA [ pv1 - > pairTblIdx ] . chN ; + + i )
{
net . preset_pairA [ pv1 - > pairTblIdx + i ] . value = & pv1 - > value ;
assert ( textIsEqual ( net . preset_pairA [ pv1 - > pairTblIdx + i ] . var - > label , pv1 - > var - > label ) & & net . preset_pairA [ pv1 - > pairTblIdx + i ] . var - > label_sfx_id = = pv1 - > var - > label_sfx_id ) ;
}
}
}
2024-05-21 22:53:11 +00:00
//
for ( const preset_value_t * pv0 = net_ps0 - > u . vlist . value_head ; pv0 ! = nullptr ; pv0 = pv0 - > link )
2024-05-24 20:36:43 +00:00
if ( proc_label_sfx_id = = kInvalidId | | pv0 - > proc - > label_sfx_id = = proc_label_sfx_id )
2024-05-21 22:53:11 +00:00
{
2024-05-24 20:36:43 +00:00
if ( pv0 - > var - > chIdx ! = kAnyChIdx )
2024-05-21 22:53:11 +00:00
{
2024-05-24 20:36:43 +00:00
rc = _preset_set_var_from_dual ( pv0 , net . preset_pairA [ pv0 - > pairTblIdx ] . value , coeff ) ;
2024-05-21 22:53:11 +00:00
}
2024-05-24 20:36:43 +00:00
else
{
for ( unsigned i = 0 ; i < net . preset_pairA [ pv0 - > pairTblIdx ] . chN ; + + i )
{
if ( ( rc = _preset_set_var_from_dual ( pv0 , net . preset_pairA [ pv0 - > pairTblIdx + i ] . value , coeff ) ) ! = kOkRC )
goto errLabel ;
assert ( textIsEqual ( net . preset_pairA [ pv0 - > pairTblIdx + i ] . var - > label , pv0 - > var - > label ) & & net . preset_pairA [ pv0 - > pairTblIdx + i ] . var - > label_sfx_id = = pv0 - > var - > label_sfx_id ) ;
}
}
2024-05-21 22:53:11 +00:00
}
errLabel :
return rc ;
}
2024-06-04 12:24:46 +00:00
//==================================================================================================================
//
// Presets - Probabilistic Selection
//
unsigned _select_ranked_ele_by_rank_prob ( const preset_order_t * presetA , const bool * selV , unsigned presetN )
{
// get a count of the candidate presets
unsigned rankN = selV = = nullptr ? presetN : std : : count_if ( selV , selV + presetN , [ ] ( const bool & x ) { return x ; } ) ;
if ( rankN = = 0 )
{
cwLogWarning ( " All preset candidates have been eliminated. " ) ;
return kInvalidIdx ;
}
unsigned rankV [ rankN ] ;
unsigned idxMapA [ rankN ] ;
// fill rankV[] with candidates 'order' value
for ( unsigned i = 0 , j = 0 ; i < presetN ; + + i )
if ( selV = = nullptr | | selV [ i ] )
{
assert ( j < rankN ) ;
rankV [ j ] = presetA [ i ] . order ;
idxMapA [ j ] = i ;
+ + j ;
}
// if only one element remains to be selected
if ( rankN = = 1 )
return idxMapA [ 0 ] ;
assert ( rankN > 1 ) ;
unsigned threshV [ rankN ] ;
unsigned uniqueRankV [ rankN ] ;
unsigned uniqueRankN = 0 ;
unsigned sel_idx = rankN - 1 ; //
// for each possible rank value
for ( unsigned i = 0 ; i < rankN ; + + i )
{
// locate the rank in the uniqueRankV[]
unsigned j = 0 ;
for ( ; j < uniqueRankN ; + + j )
if ( uniqueRankV [ j ] = = rankV [ i ] )
break ;
// if the rank was not found then include it here
if ( j = = uniqueRankN )
uniqueRankV [ uniqueRankN + + ] = rankV [ i ] ;
}
// uniqueRankV[] now includes the set of possible rank values
// Take the product of all possible values.
// (this will be evenly divisible by all values)
unsigned prod = vop : : prod ( uniqueRankV , uniqueRankN ) ;
unsigned thresh = 0 ;
for ( unsigned i = 0 ; i < rankN ; + + i )
threshV [ i ] = ( thresh + = rankV [ i ] * prod ) ;
// Thresh is now set to the max possible random value.
// Generate a random number between 0 and thresh
double fval = ( double ) std : : rand ( ) * thresh / RAND_MAX ;
unsigned thresh0 = 0 ;
for ( unsigned i = 0 ; i < rankN ; + + i )
{
if ( thresh0 < = fval & & fval < threshV [ i ] )
{
sel_idx = i ;
break ;
}
}
assert ( sel_idx < rankN ) ;
return idxMapA [ sel_idx ] ;
}
const char * _select_ranked_ele_label_by_rank_prob ( const preset_order_t * rankV , const bool * selA , unsigned rankN )
{
unsigned sel_idx ;
if ( ( sel_idx = _select_ranked_ele_by_rank_prob ( rankV , selA , rankN ) ) = = kInvalidIdx )
{
cwLogWarning ( " The multi-preset select function failed. Selecting preset 0. " ) ;
sel_idx = 0 ;
}
return rankV [ sel_idx ] . preset_label ;
}
double _calc_multi_preset_dual_coeff ( const multi_preset_selector_t & mps )
{
double result = 0 ;
unsigned resultN = 0 ;
if ( mps . coeffN = = 0 )
{
result = 0.5 ;
}
else
{
for ( unsigned i = 0 ; i < mps . coeffN ; + + i )
{
/*
Temporarily commented out because coeffV [ ] values
have already been normalized .
double norm_factor = ( mps . coeffMaxV [ i ] - mps . coeffMinV [ i ] ) ;
if ( norm_factor < = 0 )
cwLogWarning ( " Invalid normalization factor in aggregated distance measurement. " ) ;
else
norm_factor = 1 ;
result + = std : : max ( mps . coeffMinV [ i ] , std : : min ( mps . coeffMaxV [ i ] , mps . coeffV [ i ] ) ) / norm_factor ;
*/
// WOULD DISTANCE BE BETTER THAN AVERAGE????
if ( mps . coeffV [ i ] ! = 0 )
{
result + = mps . coeffV [ i ] ;
resultN + = 1 ;
}
}
if ( resultN < = 0 )
cwLogWarning ( " Invalid normalization factor in aggregated distance measurement. " ) ;
else
result = std : : min ( 1.0 , std : : max ( 0.0 , result / mps . coeffN ) ) ;
}
return result ;
}
2024-09-17 20:33:26 +00:00
//==================================================================================================================
//
// Network - Create
//
2024-05-21 22:53:11 +00:00
2024-09-17 20:33:26 +00:00
rc_t _network_create ( flow_t * p ,
const object_t * networkCfg ,
unsigned sfx_id ,
variable_t * proxyVarL ,
2024-09-20 22:11:30 +00:00
const char * preset_label ,
2024-09-17 20:33:26 +00:00
network_t * & net_ref )
{
2024-09-20 22:11:30 +00:00
rc_t rc = kOkRC ;
unsigned procN = 0 ;
const object_t * netPresetCfg = nullptr ;
network_t * net = mem : : allocZ < network_t > ( ) ;
2024-09-17 20:33:26 +00:00
// if the top level network has not been set then set it here.
// (this is necessary so that proc's later in the exec order
// can locate proc's earlier in the exec order)
if ( p - > net = = nullptr )
p - > net = net ;
if ( ( rc = networkCfg - > getv ( " procs " , net - > procsCfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Failed on parsing required network cfg. elements. " ) ;
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
2024-09-17 20:33:26 +00:00
if ( ( rc = networkCfg - > getv_opt ( " presets " , net - > presetsCfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Failed on parsing optional network cfg. elements. " ) ;
goto errLabel ;
}
2024-04-22 20:02:40 +00:00
2024-09-20 22:11:30 +00:00
// locate the requested network preset cfg
if ( ( rc = _get_network_preset_cfg ( net - > presetsCfg , preset_label , netPresetCfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Network create failed because the network preset resolution failed. " ) ;
goto errLabel ;
}
procN = net - > procsCfg - > child_count ( ) ;
2024-10-12 19:27:33 +00:00
net - > procA = mem : : allocZ < proc_t * > ( procN ) ;
2024-04-22 20:02:40 +00:00
2024-09-17 20:33:26 +00:00
// for each proc in the network
for ( unsigned j = 0 ; j < procN ; + + j )
{
const object_t * proc_cfg = net - > procsCfg - > child_ele ( j ) ;
2024-04-22 20:02:40 +00:00
2024-09-17 20:33:26 +00:00
// create the proc inst instance
2024-10-12 19:27:33 +00:00
if ( ( rc = _proc_create ( p , proc_cfg , sfx_id , * net , proxyVarL , netPresetCfg , net - > procA [ j ] ) ) ! = kOkRC )
2024-09-17 20:33:26 +00:00
{
rc = cwLogError ( rc , " The processor instantiation at proc index %i failed. " , j ) ;
goto errLabel ;
}
2024-09-16 14:43:02 +00:00
2024-10-12 19:27:33 +00:00
net - > procN + = 1 ;
2024-09-17 20:33:26 +00:00
}
2024-04-22 20:02:40 +00:00
2024-09-17 20:33:26 +00:00
if ( ( rc = _network_preset_pair_create_table ( * net ) ) ! = kOkRC )
2024-09-16 12:18:05 +00:00
goto errLabel ;
2024-09-20 22:11:30 +00:00
// parse the network presets but do not apply thme
_network_preset_parse_dict ( p , * net , net - > presetsCfg ) ;
2024-09-17 20:33:26 +00:00
net_ref = net ;
errLabel :
if ( rc ! = kOkRC )
{
if ( p - > net = = net )
p - > net = nullptr ;
net_ref = nullptr ;
_network_destroy ( net ) ;
2024-04-22 20:02:40 +00:00
}
2024-09-16 12:18:05 +00:00
2024-09-17 20:33:26 +00:00
return rc ;
2024-04-22 20:02:40 +00:00
}
2024-10-12 19:27:33 +00:00
rc_t _form_net_ui_desc ( const flow_t * p , network_t & net , ui_net_t * & ui_net_ref ) ;
rc_t _fill_net_ui_proc_and_preset_arrays ( const flow_t * p , network_t & net , ui_net_t * & ui_net_ref )
{
rc_t rc = kOkRC ;
ui_net_ref - > procA = mem : : allocZ < ui_proc_t > ( net . procN ) ;
ui_net_ref - > procN = net . procN ;
for ( unsigned i = 0 ; i < ui_net_ref - > procN ; + + i )
{
ui_proc_t * ui_proc = ui_net_ref - > procA + i ;
ui_proc - > ui_net = ui_net_ref ;
ui_proc - > label = net . procA [ i ] - > label ;
ui_proc - > label_sfx_id = net . procA [ i ] - > label_sfx_id ;
ui_proc - > desc = net . procA [ i ] - > class_desc - > ui ;
ui_proc - > cfg = net . procA [ i ] - > proc_cfg ;
ui_proc - > varN = 0 ;
ui_proc - > varA = mem : : allocZ < ui_var_t > ( net . procA [ i ] - > varMapN ) ;
proc_t * proc_ptr = proc_find ( net , ui_proc - > label , ui_proc - > label_sfx_id ) ;
assert ( proc_ptr ! = nullptr ) ;
ui_proc - > proc = proc_ptr ;
for ( unsigned j = 0 ; j < net . procA [ i ] - > varMapN ; + + j )
{
variable_t * var = net . procA [ i ] - > varMapA [ j ] ;
// all slots in the varMapA[] are not used
if ( var ! = nullptr )
{
ui_var_t * ui_var = ui_proc - > varA + ui_proc - > varN + + ;
ui_var - > ui_proc = ui_proc ;
ui_var - > label = var - > label ;
ui_var - > label_sfx_id = var - > label_sfx_id ;
2024-10-19 16:37:13 +00:00
ui_var - > has_source_fl = is_connected_to_source ( var ) ;
2024-10-12 19:27:33 +00:00
ui_var - > vid = var - > vid ;
ui_var - > ch_cnt = var_channel_count ( net . procA [ i ] , var - > label , var - > label_sfx_id ) ;
ui_var - > ch_idx = var - > chIdx ;
ui_var - > value_tid = var - > type ;
ui_var - > desc_flags = var - > varDesc - > flags ;
ui_var - > desc_cfg = var - > varDesc - > cfg ;
2024-10-14 18:16:14 +00:00
ui_var - > user_id = kInvalidId ;
var - > ui_var = ui_var ;
2024-10-12 19:27:33 +00:00
}
}
if ( net . procA [ i ] - > internal_net ! = nullptr )
{
if ( ( rc = _form_net_ui_desc ( p , * net . procA [ i ] - > internal_net , ui_proc - > internal_net ) ) ! = kOkRC )
goto errLabel ;
}
}
ui_net_ref - > presetA = mem : : allocZ < ui_preset_t > ( net . presetN ) ;
ui_net_ref - > presetN = net . presetN ;
2024-10-19 16:37:13 +00:00
2024-10-12 19:27:33 +00:00
for ( unsigned i = 0 ; i < ui_net_ref - > presetN ; + + i )
{
ui_net_ref - > presetA [ i ] . label = net . presetA [ i ] . label ;
ui_net_ref - > presetA [ i ] . preset_idx = i ;
}
errLabel :
return rc ;
}
rc_t _form_net_ui_desc ( const flow_t * p , network_t & net , ui_net_t * & ui_net_ref )
{
rc_t rc = kOkRC ;
ui_net_ref = mem : : allocZ < ui_net_t > ( ) ;
if ( ( rc = _fill_net_ui_proc_and_preset_arrays ( p , net , ui_net_ref ) ) ! = kOkRC )
goto errLabel ;
ui_net_ref - > poly_idx = net . poly_idx ;
if ( net . poly_link ! = nullptr )
_form_net_ui_desc ( p , * net . poly_link , ui_net_ref - > poly_link ) ;
errLabel :
return rc ;
}
2024-09-17 20:33:26 +00:00
2024-04-22 20:02:40 +00:00
}
2024-09-17 20:33:26 +00:00
}
2024-04-22 20:02:40 +00:00
2024-09-16 12:18:05 +00:00
2024-05-19 19:24:33 +00:00
2024-09-17 20:33:26 +00:00
cw : : rc_t cw : : flow : : network_create ( flow_t * p ,
const object_t * const * netCfgA ,
unsigned netCfgN ,
variable_t * proxyVarL ,
unsigned polyCnt ,
2024-09-20 22:11:30 +00:00
const char * preset_label ,
2024-09-17 20:33:26 +00:00
network_t * & net_ref )
{
rc_t rc = kOkRC ;
network_t * n0 = nullptr ;
net_ref = nullptr ;
2024-05-19 19:24:33 +00:00
2024-09-17 20:33:26 +00:00
if ( ! ( netCfgN = = 1 | | netCfgN = = polyCnt ) )
{
cwLogError ( kInvalidArgRC , " The count of network cfg's must be one, or must match the 'poly count'. " ) ;
2024-05-19 19:24:33 +00:00
goto errLabel ;
2024-09-17 20:33:26 +00:00
}
2024-05-19 19:24:33 +00:00
2024-09-17 20:33:26 +00:00
for ( unsigned i = 0 ; i < polyCnt ; + + i )
{
network_t * net = nullptr ;
// All procs in a poly should share the same sfx_id
// otherwise the sfx_id can be automatically generated.
unsigned sfx_id = polyCnt > 1 ? i : kInvalidId ;
2024-09-20 22:11:30 +00:00
const object_t * netCfg = i < netCfgN ? netCfgA [ i ] : netCfgA [ 0 ] ;
// create the network
if ( ( rc = _network_create ( p , netCfg , sfx_id , proxyVarL , preset_label , net ) ) ! = kOkRC )
2024-09-17 20:33:26 +00:00
{
rc = cwLogError ( rc , " Network create failed on poly index %i. " , i ) ;
goto errLabel ;
}
// The returned net is always the first in a poly chain
if ( net_ref = = nullptr )
net_ref = net ;
net - > poly_idx = i ;
if ( n0 ! = nullptr )
n0 - > poly_link = net ;
n0 = net ;
}
2024-04-22 20:02:40 +00:00
errLabel :
2024-09-17 20:33:26 +00:00
if ( rc ! = kOkRC & & net_ref ! = nullptr )
_network_destroy ( net_ref ) ;
2024-04-22 20:02:40 +00:00
return rc ;
}
2024-09-17 20:33:26 +00:00
cw : : rc_t cw : : flow : : network_destroy ( network_t * & net )
2024-04-22 20:02:40 +00:00
{
return _network_destroy ( net ) ;
}
const cw : : object_t * cw : : flow : : find_network_preset ( const network_t & net , const char * presetLabel )
{
const object_t * preset_value = nullptr ;
if ( net . presetsCfg ! = nullptr )
{
rc_t rc ;
if ( ( rc = net . presetsCfg - > getv_opt ( presetLabel , preset_value ) ) ! = kOkRC )
cwLogError ( rc , " Search for network preset named '%s' failed. " , cwStringNullGuard ( presetLabel ) ) ;
}
2024-05-23 13:32:24 +00:00
return preset_value ;
2024-04-22 20:02:40 +00:00
}
2024-10-12 19:27:33 +00:00
cw : : rc_t cw : : flow : : create_net_ui_desc ( flow_t * p )
{
rc_t rc = kOkRC ;
if ( p - > net = = nullptr )
{
rc = cwLogError ( kInvalidStateRC , " The UI description could not be formed because the network is not valid. " ) ;
goto errLabel ;
}
if ( ( rc = _form_net_ui_desc ( p , * p - > net , p - > net - > ui_net ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The UI description creation failed. " ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
2024-09-17 20:33:26 +00:00
cw : : rc_t cw : : flow : : exec_cycle ( network_t & net )
2024-04-22 20:02:40 +00:00
{
rc_t rc = kOkRC ;
2024-07-01 14:29:34 +00:00
bool halt_fl = false ;
2024-04-22 20:02:40 +00:00
2024-10-12 19:27:33 +00:00
for ( unsigned i = 0 ; i < net . procN ; + + i )
2024-04-22 20:02:40 +00:00
{
2024-10-12 19:27:33 +00:00
if ( ( rc = net . procA [ i ] - > class_desc - > members - > exec ( net . procA [ i ] ) ) ! = kOkRC )
2024-05-02 17:59:19 +00:00
{
2024-07-01 14:29:34 +00:00
if ( rc = = kEofRC )
halt_fl = true ;
else
{
2024-10-12 19:27:33 +00:00
rc = cwLogError ( rc , " Execution failed on the proc:%s:%i. " , cwStringNullGuard ( net . procA [ i ] - > label ) , net . procA [ i ] - > label_sfx_id ) ;
2024-07-01 14:29:34 +00:00
break ;
}
2024-04-22 20:02:40 +00:00
}
}
2024-09-16 12:18:05 +00:00
2024-07-01 14:29:34 +00:00
return halt_fl ? kEofRC : rc ;
2024-04-22 20:02:40 +00:00
}
2024-05-06 19:46:12 +00:00
cw : : rc_t cw : : flow : : get_variable ( network_t & net , const char * proc_label , const char * var_label , unsigned chIdx , proc_t * & procPtrRef , variable_t * & varPtrRef )
2024-04-22 20:02:40 +00:00
{
rc_t rc = kOkRC ;
2024-05-06 19:46:12 +00:00
proc_t * proc = nullptr ;
2024-04-22 20:02:40 +00:00
variable_t * var = nullptr ;
varPtrRef = nullptr ;
2024-05-06 19:46:12 +00:00
procPtrRef = nullptr ;
2024-04-22 20:02:40 +00:00
2024-05-08 14:18:43 +00:00
// locate the proc inst instance
2024-05-06 19:46:12 +00:00
if ( ( proc = proc_find ( net , proc_label , kBaseSfxId ) ) = = nullptr )
2024-04-22 20:02:40 +00:00
{
2024-05-08 14:18:43 +00:00
rc = cwLogError ( kInvalidIdRC , " Unknown proc inst instance label '%s'. " , cwStringNullGuard ( proc_label ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
// locate the variable
2024-05-06 19:46:12 +00:00
if ( ( rc = var_find ( proc , var_label , kBaseSfxId , chIdx , var ) ) ! = kOkRC )
2024-04-22 20:02:40 +00:00
{
2024-05-08 14:18:43 +00:00
rc = cwLogError ( kInvalidArgRC , " The variable '%s' could not be found on the proc inst instance '%s'. " , cwStringNullGuard ( var_label ) , cwStringNullGuard ( proc_label ) ) ;
2024-04-22 20:02:40 +00:00
goto errLabel ;
}
2024-05-06 19:46:12 +00:00
procPtrRef = proc ;
2024-04-22 20:02:40 +00:00
varPtrRef = var ;
errLabel :
return rc ;
}
2024-10-14 18:16:14 +00:00
cw : : rc_t cw : : flow : : set_variable_user_id ( network_t & net , const ui_var_t * ui_var , unsigned user_id )
{
rc_t rc = kOkRC ;
variable_t * var = nullptr ;
if ( ( rc = var_find ( ui_var - > ui_proc - > proc , ui_var - > vid , ui_var - > ch_idx , var ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " User-Id assigned failed on '%s:%i' because the variable was not found. " , cwStringNullGuard ( ui_var - > label ) , ui_var - > label_sfx_id ) ;
goto errLabel ;
}
var - > ui_var - > user_id = user_id ;
errLabel :
return rc ;
}
2024-05-19 19:24:33 +00:00
cw : : rc_t cw : : flow : : network_apply_preset ( network_t & net , const char * preset_label , unsigned proc_label_sfx_id )
{
rc_t rc = kOkRC ;
const network_preset_t * network_preset = nullptr ;
if ( ( network_preset = network_preset_from_label ( net , preset_label ) ) = = nullptr )
{
2024-05-21 22:53:11 +00:00
rc = cwLogError ( kInvalidIdRC , " The network preset '%s' could not be found. " , cwStringNullGuard ( preset_label ) ) ;
2024-05-19 19:24:33 +00:00
goto errLabel ;
}
2024-05-21 22:53:11 +00:00
switch ( network_preset - > tid )
{
case kPresetVListTId :
if ( ( rc = _network_apply_preset ( net , & network_preset - > u . vlist , proc_label_sfx_id ) ) ! = kOkRC )
2024-05-19 19:24:33 +00:00
goto errLabel ;
2024-05-21 22:53:11 +00:00
break ;
case kPresetDualTId :
2024-05-24 20:36:43 +00:00
if ( ( rc = _network_apply_dual_preset ( net , network_preset - > u . dual . pri , network_preset - > u . dual . sec , network_preset - > u . dual . coeff , proc_label_sfx_id ) ) ! = kOkRC )
2024-05-21 22:53:11 +00:00
goto errLabel ;
break ;
default :
rc = cwLogError ( kAssertFailRC , " Unknown preset type. " ) ;
break ;
}
2024-05-19 19:24:33 +00:00
cwLogInfo ( " Activated preset:%s " , preset_label ) ;
errLabel :
2024-05-21 22:53:11 +00:00
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " The network application '%s' failed. " , cwStringNullGuard ( preset_label ) ) ;
2024-05-19 19:24:33 +00:00
return rc ;
}
2024-05-21 22:53:11 +00:00
2024-05-24 20:36:43 +00:00
cw : : rc_t cw : : flow : : network_apply_dual_preset ( network_t & net , const char * preset_label_0 , const char * preset_label_1 , double coeff , unsigned proc_label_sfx_id )
2024-05-19 19:24:33 +00:00
{
rc_t rc = kOkRC ;
const network_preset_t * net_ps0 = nullptr ;
const network_preset_t * net_ps1 = nullptr ;
if ( ( net_ps0 = network_preset_from_label ( net , preset_label_0 ) ) = = nullptr )
{
rc = cwLogError ( kInvalidIdRC , " The network preset '%s' could not be found. " , preset_label_0 ) ;
goto errLabel ;
}
if ( ( net_ps1 = network_preset_from_label ( net , preset_label_1 ) ) = = nullptr )
{
rc = cwLogError ( kInvalidIdRC , " The network preset '%s' could not be found. " , preset_label_1 ) ;
goto errLabel ;
}
2024-05-24 20:36:43 +00:00
if ( ( rc = _network_apply_dual_preset ( net , net_ps0 , net_ps1 , coeff , proc_label_sfx_id ) ) ! = kOkRC )
2024-05-21 22:53:11 +00:00
goto errLabel ;
2024-05-19 19:24:33 +00:00
errLabel :
if ( rc ! = kOkRC )
2024-05-21 22:53:11 +00:00
rc = cwLogError ( rc , " Apply dual-preset failed. " ) ;
2024-05-19 19:24:33 +00:00
return rc ;
}
2024-04-22 20:02:40 +00:00
2024-05-24 20:36:43 +00:00
cw : : rc_t cw : : flow : : network_apply_preset ( network_t & net , const multi_preset_selector_t & mps , unsigned proc_label_sfx_id )
2024-04-22 20:02:40 +00:00
{
rc_t rc = kOkRC ;
const char * label0 = nullptr ;
const char * label1 = nullptr ;
bool priProbFl = cwIsFlag ( mps . flags , kPriPresetProbFl ) ;
bool secProbFl = cwIsFlag ( mps . flags , kSecPresetProbFl ) ;
bool interpFl = cwIsFlag ( mps . flags , kInterpPresetFl ) ;
//printf("preset flags: pri:%i sec:%i interp:%i\n",priProbFl,secProbFl,interpFl);
// verify that the set of candidate presets is not empty
if ( mps . presetN = = 0 )
{
cwLogError ( kInvalidArgRC , " A multi-preset application was requested but no presets were provided. " ) ;
goto errLabel ;
}
// if only a single candidate preset exists or needs to be selected
if ( interpFl = = false | | mps . presetN = = 1 )
{
// if only a single candidate preset is available or pri. probablity is not enabled
if ( mps . presetN = = 1 | | priProbFl = = false )
label0 = mps . presetA [ 0 ] . preset_label ;
else
{
if ( priProbFl )
label0 = _select_ranked_ele_label_by_rank_prob ( mps . presetA , nullptr , mps . presetN ) ;
else
label0 = mps . presetA [ 0 ] . preset_label ;
}
}
else // interpolation has been selected and at least 2 presets exist
{
unsigned pri_sel_idx = 0 ;
// select the primary preset
if ( priProbFl )
pri_sel_idx = _select_ranked_ele_by_rank_prob ( mps . presetA , nullptr , mps . presetN ) ;
else
{
// select all presets assigned to order == 1
bool selA [ mps . presetN ] ;
for ( unsigned i = 0 ; i < mps . presetN ; + + i )
selA [ i ] = mps . presetA [ i ] . order = = 1 ;
// select the preset among all presets marked as 1
pri_sel_idx = _select_ranked_ele_by_rank_prob ( mps . presetA , selA , mps . presetN ) ;
}
if ( pri_sel_idx = = kInvalidIdx )
pri_sel_idx = 0 ;
// the primary preset has now been selected
// if there is only one candidate secondary preset
if ( mps . presetN = = 2 )
{
assert ( pri_sel_idx < = 1 ) ;
label1 = mps . presetA [ pri_sel_idx = = 0 ? 1 : 0 ] . preset_label ;
}
2024-05-24 20:36:43 +00:00
else // at least two remaining presets exist to select between
2024-04-22 20:02:40 +00:00
{
// mark the selected primary preset as not-available
bool selA [ mps . presetN ] ;
vop : : fill ( selA , mps . presetN , true ) ;
selA [ pri_sel_idx ] = false ;
// if the second preset should be selected probabilistically
if ( secProbFl )
label1 = _select_ranked_ele_label_by_rank_prob ( mps . presetA , selA , mps . presetN ) ;
else
{
// select the best preset that is not the primary preset
for ( unsigned i = 0 ; i < mps . presetN ; + + i )
if ( i ! = pri_sel_idx )
{
label1 = mps . presetA [ i ] . preset_label ;
break ;
}
}
}
assert ( pri_sel_idx ! = kInvalidIdx ) ;
label0 = mps . presetA [ pri_sel_idx ] . preset_label ;
}
assert ( label0 ! = nullptr ) ;
if ( label1 = = nullptr )
{
2024-05-24 20:36:43 +00:00
rc = network_apply_preset ( net , label0 , proc_label_sfx_id ) ;
2024-04-22 20:02:40 +00:00
}
else
{
double coeff = _calc_multi_preset_dual_coeff ( mps ) ;
2024-05-24 20:36:43 +00:00
rc = network_apply_dual_preset ( net , label0 , label1 , coeff , proc_label_sfx_id ) ;
2024-04-22 20:02:40 +00:00
}
errLabel :
return rc ;
}