#include "niml_private.h"
/*---------------------------------------------------------------------------*/
/*! Return a pointer to the idcode of a NIML element (group or data),
if it has one. Otherwise, return NULL. Do not modify or free()
this string, since it points into the NIML element struct.
-----------------------------------------------------------------------------*/
char * NI_self_idcode( void *nini )
{
char *rhs ;
int ii ;
static char *iname[] = { "self_idcode" ,
"AFNI_idcode" ,
"ni_idcode" ,
"idcode" ,
NULL } ;
for( ii=0 ; iname[ii] != NULL ; ii++ ){
rhs = NI_get_attribute( nini , iname[ii] ) ;
if( rhs != NULL ) return rhs ;
}
return NULL ;
}
/*---------------------------------------------------------------------------*/
/*! Open a stream, read all NIML stuff possible from it, close it.
- Returns an array of (*ndc) object containers in (*dc).
- Max time delay allowed at any I/O step is msec.
- If (*ndc)==0 on return, then nothing good happened.
-----------------------------------------------------------------------------*/
void NI_suck_stream( char *sname, int msec, int *ndc, NI_objcontainer ***dc )
{
NI_stream ns ;
int nn , start_msec=NI_clock_time() ;
NI_objcontainer *mdc ;
void *nini ;
char *rhs ;
/*-- startup and sanity checks --*/
if( ndc == NULL ) return ; /* clueless caller */
*ndc = 0 ; /* number of objects found thus far */
if( dc == NULL ) return ; /* stupid caller */
*dc = NULL ; /* array of objects found thus far */
ns = NI_stream_open( sname , "r" ) ;
if( ns == NULL ) return ; /* not so good */
NI_add_trusted_host(NULL) ;
if( msec == 0 ) msec = 1 ; /* short waits */
else if( msec < 0 ) msec = 999999999 ; /* long waits */
/*-- wait for connection to be good --*/
nn = NI_stream_goodcheck( ns , msec ) ;
if( nn <= 0 ){ NI_stream_closenow(ns); return; }
/*-- loopback point to get a new NI element (group or data) --*/
GetElement:
nini = NI_read_element( ns , msec ) ;
if( nini == NULL ){ NI_stream_closenow(ns); return; } /*** the way out ***/
nn = NI_element_type(nini) ;
rhs = NI_self_idcode (nini) ;
mdc = (NI_objcontainer *)calloc(1,sizeof(NI_objcontainer)) ;
mdc->self_data = nini ;
NI_strncpy( mdc->self_idcode , rhs , IDCODE_LEN ) ;
if( nn == NI_ELEMENT_TYPE ){
NI_element *nel = (NI_element *)nini ;
NI_strncpy( mdc->type_name , "NI_ELEMENT" , IDCODE_LEN ) ;
NI_strncpy( mdc->self_name , nel->name , IDCODE_LEN ) ;
} else if( nn == NI_GROUP_TYPE ){
NI_group *ngr = (NI_group *)nini ;
NI_strncpy( mdc->type_name , "NI_GROUP" , IDCODE_LEN ) ;
NI_strncpy( mdc->self_name , ngr->name , IDCODE_LEN ) ;
} else { /** should never happen */
fprintf(stderr,"\n** ERROR: non-NIML data on stream '%s' !!\n",sname) ;
free((void *)mdc) ;
goto GetElement ;
}
/*-- add new element to output list --*/
NI_convert_elm_to_obj( mdc ) ; /* convert to struct in-place, if possible */
(*ndc)++ ;
(*dc) = (NI_objcontainer **)realloc( (void *)(*dc) ,
sizeof(NI_objcontainer *) * (*ndc) ) ;
(*dc)[(*ndc)-1] = mdc ;
goto GetElement ;
}
/*---------------------------------------------------------------------------*/
typedef struct {
char self_name[IDCODE_LEN] ;
NI_objconverter_func to_obj , to_elm ;
} NI_converterstruct ;
static int num_converters = 0 ;
static NI_converterstruct *converters = NULL ;
/*---------------------------------------------------------------------------*/
void NI_register_objconverters( char *self_name ,
NI_objconverter_func elm_to_obj ,
NI_objconverter_func obj_to_elm )
{
int cc ;
if( self_name == NULL || *self_name == '\0' ) return ;
if( elm_to_obj == (NI_objconverter_func)NULL ) return ;
for( cc=0 ; cc < num_converters ; cc++ )
if( strcmp(converters[cc].self_name,self_name) == 0 ) break ;
if( cc == num_converters ){
num_converters++ ;
converters = (NI_converterstruct *)
realloc( (void *)converters ,
sizeof(NI_converterstruct)*num_converters ) ;
}
NI_strncpy( converters[cc].self_name , self_name , IDCODE_LEN ) ;
converters[cc].to_obj = elm_to_obj ;
converters[cc].to_elm = obj_to_elm ;
return ;
}
/*---------------------------------------------------------------------------*/
/*! See if we can convert an element to an object.
On input:
- dc->type_name should be "NI_ELEMENT" or "NI_GROUP"
- conversion is based on dc->self_name
On output
- dc->type_name will be set to dc->self_name
- data in dc->self_data will be altered, and the NIML element
will have been destroyed
-----------------------------------------------------------------------------*/
void NI_convert_elm_to_obj( NI_objcontainer *dc )
{
int cc , nn ;
if( dc == NULL ) return ;
if( strcmp(dc->type_name,"NI_ELEMENT") != 0 &&
strcmp(dc->type_name,"NI_GROUP" ) != 0 ) return ;
for( cc=0 ; cc < num_converters ; cc++ )
if( strcmp(converters[cc].self_name,dc->self_name) == 0 ) break ;
if( cc == num_converters ) return ;
nn = converters[cc].to_obj( dc ) ;
if( nn > 0 )
NI_strncpy( dc->type_name , dc->self_name , IDCODE_LEN ) ;
return ;
}
syntax highlighted by Code2HTML, v. 0.9.1