Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

niml_element.c

Go to the documentation of this file.
00001 #include "niml_private.h"
00002 
00003 /*-----------------------------------------------------------------------*/
00004 /*! Construct an empty data element from a header.
00005     - The data vectors will have space allocated, but they will be
00006       filled with all zero bytes.
00007     - If the header was "empty" (ended in "/>"), then no vectors will
00008       be allocated, and nel->vec_num=0.
00009     - This function is used by NI_read_element() to create the
00010       data element after the header has been parsed.
00011     - 27 Mar 2003: modified to allow vec_len=0, indicating vector
00012       length to be inferred from amount of data
00013 -------------------------------------------------------------------------*/
00014 
00015 NI_element * make_empty_data_element( header_stuff *hs )
00016 {
00017    NI_element *nel ;
00018    int ii , qq ;
00019 
00020    if( hs == NULL || hs->name == NULL ) return NULL ;
00021 
00022 #ifdef NIML_DEBUG
00023 NI_dpr("ENTER make_empty_data_element\n") ;
00024 #endif
00025 
00026    nel = NI_malloc(NI_element, sizeof(NI_element) ) ;
00027 
00028    nel->type = NI_ELEMENT_TYPE ;
00029 
00030    nel->outmode = -1 ;   /* 29 Mar 2005 */
00031 
00032    /* move name and attributes from hs to new element */
00033 
00034    nel->name = hs->name ; hs->name = NULL ;
00035 
00036    nel->attr_num = hs->nattr ;
00037 
00038    if( nel->attr_num > 0 ){
00039       nel->attr_lhs = hs->lhs ; hs->lhs = NULL ;
00040       nel->attr_rhs = hs->rhs ; hs->rhs = NULL ;
00041    } else {
00042       nel->attr_lhs = nel->attr_rhs = NULL ;
00043    }
00044 
00045    /* set default vector parameters [indicating no data] */
00046 
00047    nel->vec_num = 0 ;
00048    nel->vec_len = 0 ;
00049    nel->vec_typ = NULL ;
00050    nel->vec     = NULL ;
00051 
00052    nel->vec_filled = 0 ;  /* no data has been filled into vectors */
00053 
00054    nel->vec_rank        = 0 ;
00055    nel->vec_axis_len    = NULL ;
00056    nel->vec_axis_delta  = NULL ;
00057    nel->vec_axis_origin = NULL ;
00058    nel->vec_axis_unit   = NULL ;
00059    nel->vec_axis_label  = NULL ;
00060 
00061    if( !hs->empty ){  /* find and process ni_* attributes about vectors */
00062 
00063      /* ni_type attribute: set types of vectors */
00064 
00065      ii = string_index( "ni_type" , nel->attr_num , nel->attr_lhs ) ;
00066 
00067      if( ii >= 0 && nel->attr_rhs[ii] != NULL ){
00068        int_array *iar = decode_type_string( nel->attr_rhs[ii] ) ;
00069        if( iar != NULL ){
00070          nel->vec_num = iar->num ;  /* number of vectors */
00071          nel->vec_typ = iar->ar ;   /* vector types */
00072          NI_free(iar) ;             /* just the shell of the struct */
00073        }
00074      }
00075 
00076      /* ni_dimen attribute: set vector length and rank */
00077 
00078      ii = string_index( "ni_dimen" , nel->attr_num , nel->attr_lhs ) ;
00079 
00080      if( ii >= 0 && nel->attr_rhs[ii] != NULL ){
00081         int_array *dar = decode_dimen_string( nel->attr_rhs[ii] ) ;
00082         if( dar != NULL && dar->num > 0 ){
00083            int nd=dar->num , qq,pp ;
00084            /* compute product of all dimensions */
00085            for( qq=1,pp=0 ; pp < nd ; pp++ ) qq *= dar->ar[pp] ;
00086            nel->vec_len      = qq ;      /* length of vectors */
00087            nel->vec_rank     = nd ;      /* number of dimensions */
00088            nel->vec_axis_len = dar->ar ; /* array of dimension lengths */
00089            NI_free(dar) ;                /* just the struct shell */
00090            if( nel->vec_len == 0 )       /* 27 Mar 2003 */
00091              nel->vec_rank = 1 ;
00092         }
00093      }
00094 
00095      /* if we had ni_dimen, also try ni_delta */
00096 
00097      ii = string_index( "ni_delta" , nel->attr_num , nel->attr_lhs ) ;
00098      if( ii >= 0 && nel->vec_rank > 0 ){
00099         NI_str_array *sar = NI_decode_string_list( nel->attr_rhs[ii] , NULL ) ;
00100         if( sar != NULL && sar->num > 0 ){
00101            int ns=sar->num , nd=nel->vec_rank , pp ;
00102            nel->vec_axis_delta = NI_malloc(float,sizeof(float)*nd) ;
00103            if( nd > ns ) nd = ns ;
00104            for( pp=0 ; pp < nd ; pp++ )
00105              sscanf( sar->str[pp] , "%f" , nel->vec_axis_delta+pp ) ;
00106            NI_delete_str_array(sar) ;
00107         }
00108      }
00109 
00110      /* if we had ni_dimen, also try ni_origin */
00111 
00112      ii = string_index( "ni_origin" , nel->attr_num , nel->attr_lhs ) ;
00113      if( ii >= 0 && nel->vec_rank > 0 ){
00114         NI_str_array *sar = NI_decode_string_list( nel->attr_rhs[ii] , NULL ) ;
00115         if( sar != NULL && sar->num > 0 ){
00116            int ns=sar->num , nd=nel->vec_rank , pp ;
00117            nel->vec_axis_origin = NI_malloc(float,sizeof(float)*nd) ;
00118            if( nd > ns ) nd = ns ;
00119            for( pp=0 ; pp < nd ; pp++ )
00120              sscanf( sar->str[pp] , "%f" , nel->vec_axis_origin+pp ) ;
00121            NI_delete_str_array(sar) ;
00122         }
00123      }
00124 
00125      /* if we had ni_dimen, also try ni_units */
00126 
00127      ii = string_index( "ni_units" , nel->attr_num , nel->attr_lhs ) ;
00128      if( ii >= 0 && nel->vec_rank > 0 ){
00129         NI_str_array *sar = NI_decode_string_list( nel->attr_rhs[ii] , NULL ) ;
00130         if( sar != NULL && sar->num > 0 ){
00131            int ns=sar->num , nd=nel->vec_rank , pp ;
00132            nel->vec_axis_unit = NI_malloc(char*,sizeof(char *)*nd) ;
00133            if( nd > ns ) nd = ns ;
00134            for( pp=0 ; pp < nd ; pp++ )
00135              nel->vec_axis_unit[pp] = NI_strdup(sar->str[pp]) ;
00136            NI_delete_str_array(sar) ;
00137         }
00138      }
00139 
00140      /* if we had ni_dimen, also try ni_axes */
00141 
00142      ii = string_index( "ni_axes" , nel->attr_num , nel->attr_lhs ) ;
00143      if( ii >= 0 && nel->vec_rank > 0 ){
00144         NI_str_array *sar = NI_decode_string_list( nel->attr_rhs[ii] , NULL ) ;
00145         if( sar != NULL && sar->num > 0 ){
00146            int ns=sar->num , nd=nel->vec_rank , pp ;
00147            nel->vec_axis_label = NI_malloc(char*,sizeof(char *)*nd) ;
00148            if( nd > ns ) nd = ns ;
00149            for( pp=0 ; pp < nd ; pp++ )
00150              nel->vec_axis_label[pp] = NI_strdup(sar->str[pp]) ;
00151            NI_delete_str_array(sar) ;
00152         }
00153      }
00154 
00155      /* supply vector parameters if none was given */
00156      /* (remember, we DON'T have an empty element) */
00157 
00158      if( nel->vec_num == 0 ){                    /* default type */
00159         nel->vec_num    = 1 ;
00160         nel->vec_typ    = NI_malloc(int,sizeof(int)) ;
00161         nel->vec_typ[0] = NI_BYTE ;
00162      }
00163 
00164      if( nel->vec_rank == 0 ){                  /* default dimensions */
00165         nel->vec_len         = 0 ;
00166         nel->vec_rank        = 1 ;
00167         nel->vec_axis_len    = NI_malloc(int, sizeof(int)) ;
00168         nel->vec_axis_len[0] = 1 ;
00169      }
00170 
00171      /* now allocate space for vectors defined above */
00172 
00173      nel->vec = NI_malloc(void*, sizeof(void *)*nel->vec_num ) ;
00174 
00175      /* 27 Mar 2003: only allocate space if we know how long they are */
00176 
00177      if( nel->vec_len > 0 ){
00178        for( ii=0 ; ii < nel->vec_num ; ii++ )
00179          nel->vec[ii] = NI_malloc(void,
00180                                   NI_type_size(nel->vec_typ[ii])*nel->vec_len) ;
00181      } else {
00182        for( ii=0 ; ii < nel->vec_num ; ii++ )
00183          nel->vec[ii] = NULL ;
00184      }
00185 
00186    } /* end of processing non-empty header stuff */
00187 
00188    return nel ;
00189 }
00190 
00191 /*-------------------------------------------------------------------------*/
00192 /*! Make an empty group element from parsed header info.
00193     The attributes in the header are assigned to the group, and the group
00194     parts are initialized to nothing.
00195 ---------------------------------------------------------------------------*/
00196 
00197 NI_group * make_empty_group_element( header_stuff *hs )
00198 {
00199    NI_group *ngr ;
00200    int ii , qq ;
00201 
00202    if( hs == NULL || hs->name == NULL ) return NULL ;
00203 
00204    ngr = NI_malloc(NI_group, sizeof(NI_group) ) ;
00205 
00206    ngr->type = NI_GROUP_TYPE ;
00207 
00208    ngr->name = hs->name ; hs->name = NULL ;  /* 24 Feb 2005 */
00209 
00210    ngr->outmode = -1 ;   /* 29 Mar 2005 */
00211 
00212    /* move attributes from hs to new element */
00213 
00214    ngr->attr_num = hs->nattr ;
00215 
00216    if( ngr->attr_num > 0 ){
00217      ngr->attr_lhs = hs->lhs ; hs->lhs = NULL ;
00218      ngr->attr_rhs = hs->rhs ; hs->rhs = NULL ;
00219    } else {
00220      ngr->attr_lhs = ngr->attr_rhs = NULL ;
00221    }
00222 
00223    /* have no pieces-parts yet */
00224 
00225    ngr->part_num = 0 ;
00226    ngr->part_typ = NULL ;
00227    ngr->part     = NULL ;
00228 
00229    return ngr ;
00230 }
00231 
00232 /*-------------------------------------------------------------------------*/
00233 /*! Byte size of a given integer type code.
00234     Modified 13 Feb 2003 to use the new rowtype stuff.
00235 ---------------------------------------------------------------------------*/
00236 
00237 int NI_type_size( int tval )
00238 {
00239    int ii = NI_rowtype_code_to_size( tval ) ;
00240    return (ii > 0) ? ii : 0 ;
00241 }
00242 
00243 /*************************************************************************/
00244 /********** Functions to create NIML data and group elements *************/
00245 /*************************************************************************/
00246 
00247 /*-----------------------------------------------------------------------*/
00248 /*! Return the type of something that points to a NI element.
00249     - The input should be point to a NI_element, NI_group, or NI_procins.
00250     - The return value is NI_ELEMENT_TYPE, NI_GROUP_TYPE, NI_PROCINS_TYPE,
00251       or -1 if the type is anything else or unknowable.
00252 -------------------------------------------------------------------------*/
00253 
00254 int NI_element_type( void *nini )
00255 {
00256    NI_element *nel = (NI_element *) nini ;
00257    NI_group   *ngr = (NI_group *)   nini ;
00258    NI_procins *npi = (NI_procins *) nini ;  /* 16 Mar 2005 */
00259 
00260    if( nini == NULL ) return -1 ;
00261 
00262    if( nel->type == NI_ELEMENT_TYPE ) return NI_ELEMENT_TYPE ;
00263    if( ngr->type == NI_GROUP_TYPE   ) return NI_GROUP_TYPE   ;
00264    if( npi->type == NI_PROCINS_TYPE ) return NI_PROCINS_TYPE ;
00265 
00266    return -1 ;
00267 }
00268 
00269 /*-----------------------------------------------------------------------*/
00270 /*! Return the name of a NI element.  If the input is bad, returns
00271     a NULL pointer.  Do not free this pointer!  It points to the
00272     name string inside the element struct.
00273 -------------------------------------------------------------------------*/
00274 
00275 char * NI_element_name( void *nini )
00276 {
00277    NI_element *nel = (NI_element *) nini ;
00278    NI_group   *ngr = (NI_group *)   nini ;
00279    NI_procins *npi = (NI_procins *) nini ;
00280 
00281    if( nini == NULL ) return NULL ;
00282 
00283    if( nel->type == NI_ELEMENT_TYPE ) return nel->name ;
00284    if( ngr->type == NI_GROUP_TYPE   ) return ngr->name ;
00285    if( npi->type == NI_PROCINS_TYPE ) return npi->name ;
00286 
00287    return NULL ;
00288 }
00289 
00290 /*-----------------------------------------------------------------------*/
00291 /*! Expunge a data or group element and its contents from the universe.
00292 -------------------------------------------------------------------------*/
00293 
00294 void NI_free_element( void *nini )
00295 {
00296    int ii , tt=NI_element_type(nini) , jj ;
00297 
00298    if( tt < 0 ) return ; /* bad input */
00299 
00300    /*-- erase contents of data element --*/
00301 
00302    if( tt == NI_ELEMENT_TYPE ){
00303       NI_element *nel = (NI_element *)nini ;
00304 
00305       NI_free(nel->name) ;
00306       for( ii=0 ; ii < nel->attr_num ; ii++ ){
00307          NI_free( nel->attr_lhs[ii] ) ;
00308          NI_free( nel->attr_rhs[ii] ) ;
00309       }
00310       NI_free( nel->attr_lhs ) ;
00311       NI_free( nel->attr_rhs ) ;
00312 
00313       /* 14 Feb 2003: NI_free_column() will also free var dim arrays */
00314 
00315       if( nel->vec != NULL )
00316         for( ii=0 ; ii < nel->vec_num ; ii++ )
00317            NI_free_column( NI_rowtype_find_code(nel->vec_typ[ii]) ,
00318                            nel->vec_len , nel->vec[ii]             ) ;
00319 
00320       NI_free( nel->vec_typ  ) ;
00321       NI_free( nel->vec ) ;
00322 
00323       NI_free(nel->vec_axis_len) ;
00324       NI_free(nel->vec_axis_delta) ;
00325       NI_free(nel->vec_axis_origin) ;
00326       NI_free(nel->vec_axis_unit) ;
00327       NI_free(nel->vec_axis_label) ;
00328 
00329       NI_free( nel ) ;
00330 
00331    /*-- erase contents of group element --*/
00332 
00333    } else if( tt == NI_GROUP_TYPE ){
00334       NI_group *ngr = (NI_group *)nini ;
00335 
00336       for( ii=0 ; ii < ngr->attr_num ; ii++ ){
00337         NI_free( ngr->attr_lhs[ii] ) ;
00338         NI_free( ngr->attr_rhs[ii] ) ;
00339       }
00340       NI_free( ngr->attr_lhs ) ;
00341       NI_free( ngr->attr_rhs ) ;
00342 
00343       if( ngr->part != NULL ){
00344         for( ii=0 ; ii < ngr->part_num ; ii++ )
00345           NI_free_element( ngr->part[ii] ) ;     /* recursion */
00346       }
00347 
00348       NI_free( ngr->part_typ ) ;
00349       NI_free( ngr->part ) ;
00350       NI_free( ngr->name ) ;    /* 03 Jun 2002 */
00351       NI_free( ngr ) ;
00352 
00353    /*-- erase contents of processing instruction --*/
00354 
00355    } else if( tt == NI_PROCINS_TYPE ){
00356       NI_procins *npi = (NI_procins *)nini ;
00357 
00358       for( ii=0 ; ii < npi->attr_num ; ii++ ){
00359         NI_free( npi->attr_lhs[ii] ) ;
00360         NI_free( npi->attr_rhs[ii] ) ;
00361       }
00362       NI_free( npi->attr_lhs ) ;
00363       NI_free( npi->attr_rhs ) ;
00364 
00365       NI_free( npi->name ) ;    /* 03 Jun 2002 */
00366       NI_free( npi ) ;
00367    }
00368 
00369    return ;
00370 }
00371 
00372 /*-----------------------------------------------------------------------*/
00373 /*! Create a new data element.
00374 
00375     - name   = string name for header.
00376     - veclen = size (length) of vectors (ni_dimen attribute).
00377                - Vectors are added with NI_add_column().
00378                - Set this to zero for "empty" elements (those with only
00379                  headers, no data).
00380 
00381     Return is NULL if inputs are stupid or criminal or insane.
00382 -------------------------------------------------------------------------*/
00383 
00384 NI_element * NI_new_data_element( char *name , int veclen )
00385 {
00386    NI_element *nel ;
00387 
00388    if( name == NULL || name[0] == '\0' || veclen < 0 ) return NULL ;
00389 
00390    nel = NI_malloc(NI_element, sizeof(NI_element) ) ;
00391 
00392    nel->type = NI_ELEMENT_TYPE ;  /* mark as being a data element */
00393 
00394    nel->outmode = -1 ;   /* 29 Mar 2005 */
00395 
00396    nel->name = NI_strdup(name) ;
00397    nel->attr_num = 0 ;
00398    nel->attr_lhs = nel->attr_rhs = NULL ;  /* no attributes yes */
00399 
00400    nel->vec_num = 0 ;                      /* no vectors yet */
00401    nel->vec_typ = NULL ;
00402    nel->vec     = NULL ;
00403 
00404    if( veclen == 0 ){                      /* empty element */
00405      nel->vec_len      = 0 ;
00406      nel->vec_filled   = 0 ;
00407      nel->vec_rank     = 0 ;
00408      nel->vec_axis_len = NULL ;
00409    } else {                                /* element with data to */
00410      nel->vec_len         = veclen ;       /* come via NI_add_column */
00411      nel->vec_filled      = veclen ;
00412      nel->vec_rank        = 1 ;
00413      nel->vec_axis_len    = NI_malloc(int, sizeof(int)) ;
00414      nel->vec_axis_len[0] = veclen ;
00415    }
00416 
00417    nel->vec_axis_delta  = NULL ;
00418    nel->vec_axis_origin = NULL ;
00419    nel->vec_axis_unit   = NULL ;
00420    nel->vec_axis_label  = NULL ;
00421 
00422    return nel ;
00423 }
00424 
00425 /*-----------------------------------------------------------------------*/
00426 /*! Add a vector (column) of data to a data element.
00427 
00428     - nel = data element to modify
00429     - typ = integer type code of data (e.g., NI_FLOAT)
00430     - arr = pointer to data values - must be an array of length veclen
00431             (same value as used in NI_new_data_element() call)
00432     - if arr is NULL, then will add a zero-filled column of the given
00433       type to the data element
00434 
00435     The data array is copied into the element.  If the element was
00436     specified with veclen=0, then this function will do nothing.
00437     Since this function has no return value, the only way to check for
00438     such an error is to see if nel->vec_num was incremented.  Or don't
00439     be so stupid as to make this error.
00440 -------------------------------------------------------------------------*/
00441 
00442 void NI_add_column( NI_element *nel , int typ , void *arr )
00443 {
00444    int nn ;
00445    NI_rowtype *rt ;
00446 
00447    /* check for reasonable inputs */
00448 
00449    if( nel == NULL || nel->vec_len <= 0 )            return ;
00450    if( nel->type != NI_ELEMENT_TYPE )                return ;
00451    rt = NI_rowtype_find_code(typ) ; if( rt == NULL ) return ;
00452 
00453    /* get number of vectors currently in element */
00454 
00455    nn = nel->vec_num ;
00456 
00457    /* add 1 to the vec_typ array */
00458 
00459    nel->vec_typ     = NI_realloc( nel->vec_typ, int, sizeof(int)*(nn+1) ) ;
00460    nel->vec_typ[nn] = typ ;
00461 
00462    /* add 1 element to the vec array, and copy data into it */
00463 
00464    nel->vec = NI_realloc( nel->vec , void*, sizeof(void *)*(nn+1) ) ;
00465    if( arr != NULL )
00466      nel->vec[nn] = NI_copy_column( rt , nel->vec_len , arr ) ;
00467    else
00468      nel->vec[nn] = NI_malloc(void, rt->size * nel->vec_len ) ;
00469 
00470    /* add 1 to the count of vectors */
00471 
00472    nel->vec_num = nn+1 ;
00473    return ;
00474 }
00475 
00476 /*------------------------------------------------------------------------*/
00477 /*! Change the length of all the columns in a data element.
00478      - If the columns are longer, they will be zero filled.
00479      - New values can be inserted later with NI_insert_value().
00480      - If the columns are shorter, data will be lost.
00481      - You cannot use this to convert an element to/from being empty;
00482        that is, newlen > 0 is required, as is nel->vec_len on input.
00483 --------------------------------------------------------------------------*/
00484 
00485 void NI_alter_veclen( NI_element *nel , int newlen )
00486 {
00487    int oldlen , ii ;
00488    NI_rowtype *rt ;
00489    char *pt ;
00490 
00491    if( nel          == NULL || nel->type != NI_ELEMENT_TYPE ) return ;
00492    if( nel->vec_len <= 0    || newlen    <= 0               ) return ;
00493 
00494    if( nel->vec_num == 0 ){                       /* if have no data yet */
00495      nel->vec_len = nel->vec_filled = newlen; return;
00496    }
00497 
00498    oldlen = nel->vec_len ; if( oldlen == newlen ) return ;
00499 
00500    for( ii=0 ; ii < nel->vec_num ; ii++ ){
00501      rt = NI_rowtype_find_code( nel->vec_typ[ii] ) ;
00502      nel->vec[ii] = NI_realloc( nel->vec[ii] , void , rt->size * newlen ) ;
00503      if( oldlen < newlen ){
00504        pt = ((char *)nel->vec[ii]) + (rt->size * oldlen) ; /* zero fill */
00505        memset( pt , 0 , (newlen-oldlen)*rt->size ) ;       /* new data! */
00506      }
00507    }
00508 
00509    nel->vec_len = nel->vec_filled = newlen ; return ;
00510 }
00511 
00512 /*------------------------------------------------------------------------*/
00513 /*! As in NI_add_column(), but adding every stride-th element from arr.
00514     Thus, arr should be at least nel->vec_len * stride elements long.
00515 --------------------------------------------------------------------------*/
00516 
00517 void NI_add_column_stride( NI_element *nel, int typ, void *arr, int stride )
00518 {
00519    int nn , ii ;
00520    NI_rowtype *rt ;
00521    char *idat ;
00522 
00523    /* check for reasonable inputs */
00524 
00525    if( nel == NULL || nel->vec_len <= 0 )            return ;
00526    if( nel->type != NI_ELEMENT_TYPE )                return ;
00527    rt = NI_rowtype_find_code(typ) ; if( rt == NULL ) return ;
00528 
00529    /* add an empty column */
00530 
00531    NI_add_column( nel , typ , NULL ) ;
00532    if( arr == NULL ) return ;          /* no input data ==> we're done */
00533 
00534    /* loop over inputs and put them in one at a time */
00535 
00536    nn   = nel->vec_num-1 ;
00537    idat = (char *) arr ;
00538 
00539    for( ii=0 ; ii < nel->vec_len ; ii++ )
00540      NI_insert_value( nel , ii , nn , idat + (ii*stride*rt->size) ) ;
00541 
00542    return ;
00543 }
00544 
00545 /*------------------------------------------------------------------------*/
00546 /*! ZSS; Fills an already created column with values up to vec_filled
00547          the values in arr are inserted into nel->vec[nn]
00548 --------------------------------------------------------------------------*/
00549 
00550 void NI_fill_column_stride( NI_element *nel, int typ,
00551                             void *arr, int nn, int stride )
00552 {
00553    int  ii , nf;
00554    NI_rowtype *rt ;
00555    char *idat ;
00556 
00557    /* check for reasonable inputs */
00558 
00559    if( nel == NULL || nel->vec_len <= 0 )            return ;
00560    if( nel->type != NI_ELEMENT_TYPE )                return ;
00561    rt = NI_rowtype_find_code(typ) ; if( rt == NULL ) return ;
00562 
00563    /* check for NULL column or other similar errors*/
00564 
00565    if( arr == NULL )                                 return ;
00566    if( nel->vec[nn] == NULL )                        return ;
00567    if( nn < 0 || nn >= nel->vec_num )                return ;
00568    if( typ != nel->vec_typ[nn] )                     return ;
00569 
00570    /* loop over inputs and put them in */
00571 
00572    if( nel->vec_filled > 0 && nel->vec_filled <= nel->vec_len )
00573      nf = nel->vec_filled ;
00574    else
00575      nf = nel->vec_len ;
00576 
00577    idat = (char *) arr ;
00578 
00579    for( ii=0 ; ii < nf ; ii++ )
00580      NI_insert_value( nel , ii , nn , idat + (ii*stride*rt->size) ) ;
00581 
00582    return ;
00583 }
00584 
00585 /*------------------------------------------------------------------------*/
00586 /*! Replace the row-th value in the col-th column of the data element.
00587      - dat is the pointer to the data values to copy into the element.
00588      - The column must have been created with NI_add_column() before
00589        calling this function!
00590      - NOTE WELL: When the column type is NI_STRING, it is a mistake
00591        to call this function with dat being a pointer to the C string
00592        to insert.  Instead, dat should be a pointer to the pointer to
00593        the C string.  For example:
00594         - char *me = "RWCox" ;
00595         - WRONG:  NI_insert_value ( nel, 3,5,  me ) ; [Seg Fault ensues]
00596         - RIGHT:  NI_insert_value ( nel, 3,5, &me ) ;
00597         - RIGHT:  NI_insert_string( nel, 3,5,  me ) ;
00598         - The last case illustrates the NI_insert_string() function,
00599           which can be used to simplify insertion into a column
00600           of Strings; that function is just a simple wrapper to call
00601           NI_insert_value() properly.
00602         - The reason the first example is WRONG is that dat is supposed
00603           to point to the data to be stored.  In the case of a String,
00604           the data is the pointer to the C string.
00605 --------------------------------------------------------------------------*/
00606 
00607 void NI_insert_value( NI_element *nel, int row, int col, void *dat )
00608 {
00609    NI_rowtype *rt ;
00610    char *cdat , *idat=(char *)dat , *qpt ;
00611    int jj , kk ;
00612 
00613    /* check for reasonable inputs */
00614 
00615    if( nel == NULL || idat == NULL        ) return ;
00616    if( nel->type    != NI_ELEMENT_TYPE    ) return ;
00617    if( nel->vec_len <= 0                  ) return ;
00618    if( row < 0     || row >= nel->vec_len ) return ;
00619    if( col < 0     || col >= nel->vec_num ) return ;
00620 
00621    rt = NI_rowtype_find_code( nel->vec_typ[col] ) ;
00622    if( rt == NULL )                         return ;
00623 
00624    cdat = (char *) nel->vec[col] ;   /* points to column data */
00625    cdat = cdat + rt->size * row ;    /* points to data to alter */
00626 
00627    /* shallow copy of input data over data now present */
00628 
00629    memcpy( cdat , idat , rt->size ) ;
00630 
00631    /* copy any var dim arrays inside */
00632 
00633    if( ROWTYPE_is_varsize(rt) ){
00634      for( jj=0 ; jj < rt->part_num ; jj++ ){            /* loop over parts */
00635 
00636        if( rt->part_typ[jj] == NI_STRING ){               /* a string part */
00637          char **apt = (char **)(cdat+rt->part_off[jj]) ;   /* *apt => data */
00638          qpt = NI_strdup(*apt) ; *apt = qpt ;
00639 
00640        } else if( rt->part_dim[jj] >= 0 ){                /* var dim array */
00641          char **apt = (char **)(cdat+rt->part_off[jj]) ;   /* *apt => data */
00642          if( *apt != NULL ){
00643            kk  = ROWTYPE_part_dimen(rt,cdat,jj) * rt->part_rtp[jj]->size ;
00644            qpt = NI_malloc(char, kk) ; memcpy(qpt,*apt,kk) ; *apt = qpt ;
00645          }
00646        }
00647      }
00648    }
00649 
00650    return ;
00651 }
00652 
00653 /*------------------------------------------------------------------------*/
00654 
00655 void NI_insert_string( NI_element *nel, int row, int col, char *str )
00656 {
00657    if( nel == NULL || str == NULL         ) return ;
00658    if( nel->type   != NI_ELEMENT_TYPE     ) return ;
00659    if( row < 0     || row >= nel->vec_len ) return ;
00660    if( col < 0     || col >= nel->vec_num ) return ;
00661    if( nel->vec_typ[col] != NI_STRING     ) return ;
00662 
00663    NI_insert_value( nel , row,col , &str ); return ;
00664 }
00665 
00666 /*------------------------------------------------------------------------*/
00667 /*! Add an attribute to a data or group element.
00668     If an attribute with the same attname already exists, then
00669     it will be replaced with this one.
00670 --------------------------------------------------------------------------*/
00671 
00672 void NI_set_attribute( void *nini , char *attname , char *attvalue )
00673 {
00674    int nn , tt=NI_element_type(nini) ;
00675 
00676    if( tt < 0 || attname == NULL || attname[0] == '\0' ) return ;
00677 
00678    /* input is a data element */
00679 
00680    if( tt == NI_ELEMENT_TYPE ){
00681       NI_element *nel = (NI_element *) nini ;
00682 
00683       /* see if name is already in element header */
00684 
00685       for( nn=0 ; nn < nel->attr_num ; nn++ )
00686          if( strcmp(nel->attr_lhs[nn],attname) == 0 ) break ;
00687 
00688       /* if not, then add a header attribute */
00689 
00690       if( nn == nel->attr_num ){
00691         nel->attr_lhs = NI_realloc( nel->attr_lhs, char*, sizeof(char *)*(nn+1) );
00692         nel->attr_rhs = NI_realloc( nel->attr_rhs, char*, sizeof(char *)*(nn+1) );
00693         nel->attr_num = nn+1 ;
00694       } else {
00695         NI_free(nel->attr_lhs[nn]) ;  /* free old attribute */
00696         NI_free(nel->attr_rhs[nn]) ;
00697       }
00698 
00699       nel->attr_lhs[nn] = NI_strdup(attname) ;
00700       nel->attr_rhs[nn] = NI_strdup(attvalue);
00701 
00702    /* input is a group element */
00703 
00704    } else if( tt == NI_GROUP_TYPE ){
00705       NI_group *ngr = (NI_group *) nini ;
00706 
00707       for( nn=0 ; nn < ngr->attr_num ; nn++ )
00708          if( strcmp(ngr->attr_lhs[nn],attname) == 0 ) break ;
00709 
00710       if( nn == ngr->attr_num ){
00711         ngr->attr_lhs = NI_realloc( ngr->attr_lhs, char*, sizeof(char *)*(nn+1) );
00712         ngr->attr_rhs = NI_realloc( ngr->attr_rhs, char*, sizeof(char *)*(nn+1) );
00713         ngr->attr_num = nn+1 ;
00714       } else {
00715         NI_free(ngr->attr_lhs[nn]) ;
00716         NI_free(ngr->attr_rhs[nn]) ;
00717       }
00718 
00719       ngr->attr_lhs[nn] = NI_strdup(attname) ;
00720       ngr->attr_rhs[nn] = NI_strdup(attvalue);
00721 
00722    /* input is a processing instruction */
00723 
00724    } else if( tt == NI_PROCINS_TYPE ){
00725       NI_procins *npi = (NI_procins *) nini ;
00726 
00727       for( nn=0 ; nn < npi->attr_num ; nn++ )
00728         if( strcmp(npi->attr_lhs[nn],attname) == 0 ) break ;
00729 
00730       if( nn == npi->attr_num ){
00731         npi->attr_lhs = NI_realloc( npi->attr_lhs, char*, sizeof(char *)*(nn+1) );
00732         npi->attr_rhs = NI_realloc( npi->attr_rhs, char*, sizeof(char *)*(nn+1) );
00733         npi->attr_num = nn+1 ;
00734       } else {
00735         NI_free(npi->attr_lhs[nn]) ;
00736         NI_free(npi->attr_rhs[nn]) ;
00737       }
00738 
00739       npi->attr_lhs[nn] = NI_strdup(attname) ;
00740       npi->attr_rhs[nn] = NI_strdup(attvalue);
00741    }
00742 
00743    return ;
00744 }
00745 
00746 /*-----------------------------------------------------------------------*/
00747 /*! Get an attribute with the given LHS name.  Returns a pointer to the
00748     RHS field in the element if the attribute name is found; otherwise
00749     returns NULL.  If the LHS is found, but the RHS is NULL, returns
00750     a pointer to an empty C string ("\0").  Do not free() the result
00751     from this function, since it points to the internal field
00752     of the element!
00753 -------------------------------------------------------------------------*/
00754 
00755 char * NI_get_attribute( void *nini , char *attname )
00756 {
00757    int nn , tt=NI_element_type(nini) ;
00758    static char *zorkon = "\0" ;
00759 
00760    if( tt < 0 || attname == NULL || attname[0] == '\0' ) return NULL ;
00761 
00762    /* input is a data element */
00763 
00764    if( tt == NI_ELEMENT_TYPE ){
00765       NI_element *nel = (NI_element *) nini ;
00766 
00767       for( nn=0 ; nn < nel->attr_num ; nn++ )
00768          if( strcmp(nel->attr_lhs[nn],attname) == 0 ) break ;
00769 
00770       if( nn == nel->attr_num ) return NULL ;
00771 
00772       if( nel->attr_rhs[nn] == NULL ) return zorkon ;
00773 
00774       return nel->attr_rhs[nn] ;
00775 
00776    /* input is a group element */
00777 
00778    } else if( tt == NI_GROUP_TYPE ){
00779       NI_group *ngr = (NI_group *) nini ;
00780 
00781       for( nn=0 ; nn < ngr->attr_num ; nn++ )
00782          if( strcmp(ngr->attr_lhs[nn],attname) == 0 ) break ;
00783 
00784       if( nn == ngr->attr_num ) return NULL ;
00785 
00786       if( ngr->attr_rhs[nn] == NULL ) return zorkon ;
00787 
00788       return ngr->attr_rhs[nn] ;
00789 
00790    /* input is a processing instruction */
00791 
00792    } else if( tt == NI_PROCINS_TYPE ){
00793       NI_procins *npi = (NI_procins *) nini ;
00794 
00795       for( nn=0 ; nn < npi->attr_num ; nn++ )
00796         if( strcmp(npi->attr_lhs[nn],attname) == 0 ) break ;
00797 
00798       if( nn == npi->attr_num ) return NULL ;
00799 
00800       if( npi->attr_rhs[nn] == NULL ) return zorkon ;
00801 
00802       return npi->attr_rhs[nn] ;
00803    }
00804 
00805    return NULL ; /* should never be reached */
00806 }
00807 
00808 /*-----------------------------------------------------------------------*/
00809 /*! Set the dimen attribute for a data element.
00810 -------------------------------------------------------------------------*/
00811 
00812 void NI_set_dimen( NI_element *nel , int rank , int *nd )
00813 {
00814    int ii , ntot ;
00815 
00816    if( nel == NULL || nel->type != NI_ELEMENT_TYPE ||
00817        rank < 1    || nd == NULL                     ) return ; /* bad */
00818 
00819    for( ntot=1,ii=0 ; ii < rank ; ii++ ){
00820       if( nd[ii] <= 0 ) return ;                                /* bad */
00821       ntot *= nd[ii] ;
00822    }
00823    if( ntot != nel->vec_len ) return ;                          /* bad */
00824 
00825    nel->vec_rank = rank ;
00826    nel->vec_axis_len = NI_realloc( nel->vec_axis_len, int, sizeof(int)*rank ) ;
00827    memcpy( nel->vec_axis_len , nd , sizeof(int)*rank ) ;
00828    return ;
00829 }
00830 
00831 /*-----------------------------------------------------------------------*/
00832 /*! Set the delta attribute for a data element.
00833     Do not call this function until NI_set_dimen() has been called,
00834     unless there is only 1 dimension (which is the default).
00835 -------------------------------------------------------------------------*/
00836 
00837 void NI_set_delta( NI_element *nel , float *del )
00838 {
00839    if( nel == NULL       || nel->type != NI_ELEMENT_TYPE ||
00840        nel->vec_rank < 1 || del == NULL                    ) return ;
00841 
00842    nel->vec_axis_delta = NI_realloc( nel->vec_axis_delta , float,
00843                                      nel->vec_rank * sizeof(float) ) ;
00844    memcpy( nel->vec_axis_delta , del , nel->vec_rank * sizeof(float) ) ;
00845    return ;
00846 }
00847 
00848 /*-----------------------------------------------------------------------*/
00849 /*! Set the origin attribute for a data element.
00850     Do not call this function until NI_set_dimen() has been called,
00851     unless there is only 1 dimension (which is the default).
00852 -------------------------------------------------------------------------*/
00853 
00854 void NI_set_origin( NI_element *nel , float *org )
00855 {
00856    if( nel == NULL       || nel->type != NI_ELEMENT_TYPE ||
00857        nel->vec_rank < 1 || org == NULL                    ) return ;
00858 
00859    nel->vec_axis_origin = NI_realloc( nel->vec_axis_origin , float,
00860                                       nel->vec_rank * sizeof(float) ) ;
00861    memcpy( nel->vec_axis_origin , org , nel->vec_rank * sizeof(float) ) ;
00862    return ;
00863 }
00864 
00865 /*-----------------------------------------------------------------------*/
00866 /*! Set the units attribute for a data element.
00867     Do not call this function until NI_set_dimen() has been called,
00868     unless there is only 1 dimension (which is the default).
00869 -------------------------------------------------------------------------*/
00870 
00871 void NI_set_units( NI_element *nel , char **units )
00872 {
00873    int ii ;
00874 
00875    if( nel == NULL       || nel->type != NI_ELEMENT_TYPE ||
00876        nel->vec_rank < 1 || units == NULL                  ) return ;
00877 
00878    nel->vec_axis_unit = NI_realloc( nel->vec_axis_unit , char*,
00879                                     nel->vec_rank * sizeof(char *) ) ;
00880    for( ii=0 ; ii < nel->vec_rank ; ii++ )
00881       nel->vec_axis_unit[ii] = NI_strdup( units[ii] ) ;
00882    return ;
00883 }
00884 
00885 /*-----------------------------------------------------------------------*/
00886 /*! Set the axes attribute for a data element.
00887     Do not call this function until NI_set_dimen() has been called,
00888     unless there is only 1 dimension (which is the default).
00889 -------------------------------------------------------------------------*/
00890 
00891 void NI_set_axes( NI_element *nel , char **ax )
00892 {
00893    int ii ;
00894 
00895    if( nel == NULL       || nel->type != NI_ELEMENT_TYPE ||
00896        nel->vec_rank < 1 || ax == NULL                     ) return ;
00897 
00898    nel->vec_axis_label = NI_realloc( nel->vec_axis_label , char*,
00899                                      nel->vec_rank * sizeof(char *) ) ;
00900    for( ii=0 ; ii < nel->vec_rank ; ii++ )
00901       nel->vec_axis_label[ii] = NI_strdup( ax[ii] ) ;
00902    return ;
00903 }
00904 
00905 /*-----------------------------------------------------------------------*/
00906 /*! Create a new processing instruction with a given 'target' name.
00907 -------------------------------------------------------------------------*/
00908 
00909 NI_procins * NI_new_processing_instruction( char *name )
00910 {
00911    NI_procins *npi ;
00912 
00913    if( name == NULL || name[0] == '\0' ) return NULL ;
00914 
00915    npi = NI_malloc(NI_procins,sizeof(NI_procins)) ;
00916 
00917    npi->type = NI_PROCINS_TYPE ;
00918    npi->name = NI_strdup(name) ;
00919 
00920    npi->attr_num = 0 ;
00921    npi->attr_lhs = npi->attr_rhs = NULL ;
00922 
00923    return npi ;
00924 }
00925 
00926 /*-----------------------------------------------------------------------*/
00927 /*! Create a new group element.
00928 -------------------------------------------------------------------------*/
00929 
00930 NI_group * NI_new_group_element(void)
00931 {
00932    NI_group *ngr ;
00933 
00934    ngr = NI_malloc(NI_group, sizeof(NI_group) ) ;
00935 
00936    ngr->type = NI_GROUP_TYPE ;
00937 
00938    ngr->outmode = -1 ;   /* 29 Mar 2005 */
00939 
00940    ngr->attr_num = 0 ;
00941    ngr->attr_lhs = ngr->attr_rhs = NULL ;
00942 
00943    ngr->part_num = 0 ;
00944    ngr->part_typ = NULL ;
00945    ngr->part     = NULL ;
00946    ngr->name     = NULL ;  /* 03 Jun 2002 */
00947 
00948    return ngr ;
00949 }
00950 
00951 /*-----------------------------------------------------------------------*/
00952 /*! Add an element to a group element.
00953 -------------------------------------------------------------------------*/
00954 
00955 void NI_add_to_group( NI_group *ngr , void *nini )
00956 {
00957    int nn , tt=NI_element_type(nini) ;
00958 
00959    if( ngr == NULL || ngr->type != NI_GROUP_TYPE || tt < 0 ) return ;
00960 
00961    nn = ngr->part_num ;
00962 
00963    ngr->part_typ     = NI_realloc( ngr->part_typ , int, sizeof(int)*(nn+1) ) ;
00964    ngr->part_typ[nn] = tt ;
00965    ngr->part         = NI_realloc( ngr->part , void*, sizeof(void *)*(nn+1) );
00966    ngr->part[nn]     = nini ;
00967    ngr->part_num     = nn+1 ;
00968    return ;
00969 }
00970 
00971 /*-----------------------------------------------------------------------*/
00972 /*! Remove an element from a group.  Does NOT delete the element;
00973     that is the caller's responsibility, if desired.
00974 -------------------------------------------------------------------------*/
00975 
00976 void NI_remove_from_group( NI_group *ngr , void *nini )  /* 16 Apr 2005 */
00977 {
00978    int ii , nn , jj ;
00979 
00980    if( ngr == NULL || ngr->type != NI_GROUP_TYPE || nini == NULL ) return ;
00981 
00982    nn = ngr->part_num ;
00983    for( ii=0 ; ii < nn ; ii++ )       /* search for part */
00984      if( nini == ngr->part[ii] ) break ;
00985    if( ii == nn ) return ;            /* not found */
00986 
00987    for( jj=ii+1 ; jj < nn ; jj++ ){   /* move parts above down */
00988      ngr->part_typ[jj-1] = ngr->part_typ[jj] ;
00989      ngr->part    [jj-1] = ngr->part    [jj] ;
00990    }
00991    ngr->part[nn-1] = NULL ;    /* NULL-ify last part to be safe */
00992    ngr->part_num -- ;          /* reduce part count */
00993    return ;
00994 }
00995 
00996 /*-----------------------------------------------------------------------*/
00997 /*! Rename a group element from the default - 03 Jun 2002.
00998 -------------------------------------------------------------------------*/
00999 
01000 void NI_rename_group( NI_group *ngr , char *nam )
01001 {
01002    if( ngr == NULL || ngr->type != NI_GROUP_TYPE ) return ;
01003    NI_free( ngr->name ) ;
01004    ngr->name = NI_strdup(nam) ;
01005    return ;
01006 }
01007 
01008 /*-----------------------------------------------------------------------*/
01009 /*! Return a list of all elements in a group that have a given name.
01010       - This is a 'shallow' search: if the group itself contains
01011         groups, these sub-groups are not searched.
01012       - Return value of function is number of elements found (might be 0).
01013       - If something is found, then *nipt is an array of 'void *', each
01014         of which points to a matching element.
01015       - The returned elements might be group or data elements.
01016       - Sample usage:
01017           - int n,i ; void **nelar ;
01018           - n = NI_search_group_shallow( ngr , "fred" , &nelar ) ;
01019           - for( i=0 ; i < n ; i++ ) do_something( nelar[ii] ) ;
01020           - if( n > 0 ) NI_free(nelar) ;
01021 -------------------------------------------------------------------------*/
01022 
01023 int NI_search_group_shallow( NI_group *ngr , char *enam , void ***nipt )
01024 {
01025    void **nelar=NULL , *nini ;
01026    int ii , nn=0 ;
01027    char *nm ;
01028 
01029    if( ngr  == NULL || ngr->type != NI_GROUP_TYPE    ) return 0 ;
01030    if( enam == NULL || *enam == '\0' || nipt == NULL ) return 0 ;
01031    if( ngr->part_num == 0                            ) return 0 ;
01032 
01033    for( ii=0 ; ii < ngr->part_num ; ii++ ){
01034      nini = ngr->part[ii] ;
01035      nm   = NI_element_name( nini ) ;
01036      if( nm != NULL && strcmp(nm,enam) == 0 ){
01037        nelar = (void **) NI_realloc(nelar,void*,nn+1) ;
01038        nelar[nn++] = nini ;
01039      }
01040    }
01041 
01042    if( nn > 0 ) *nipt = nelar ;
01043    return nn ;
01044 }
01045 
01046 /*-----------------------------------------------------------------------*/
01047 /*! Return a list of all elements in a group that have a given name.
01048       - This is a 'deep' search: if the group itself contains
01049         groups, these sub-groups are searched, etc.
01050       - If a group element has the name 'enam' AND a data element within
01051         that group has the name 'enam' as well, they will BOTH be returned
01052         in this list.
01053       - Return value of function is number of elements found (might be 0).
01054       - If something is found, then *nipt is an array of 'void *', each
01055         of which points to a matching element.
01056       - The returned elements might be group or data elements.
01057       - Sample usage:
01058           - int n,i ; void **nelar ;
01059           - n = NI_search_group_shallow( ngr , "fred" , &nelar ) ;
01060           - for( i=0 ; i < n ; i++ ) do_something( nelar[ii] ) ;
01061           - if( n > 0 ) NI_free(nelar) ;
01062 -------------------------------------------------------------------------*/
01063 
01064 int NI_search_group_deep( NI_group *ngr , char *enam , void ***nipt )
01065 {
01066    void **nelar=NULL , *nini ;
01067    int ii , nn=0 ;
01068    char *nm ;
01069 
01070    if( ngr  == NULL || ngr->type != NI_GROUP_TYPE    ) return 0 ;
01071    if( enam == NULL || *enam == '\0' || nipt == NULL ) return 0 ;
01072    if( ngr->part_num == 0                            ) return 0 ;
01073 
01074    for( ii=0 ; ii < ngr->part_num ; ii++ ){
01075      nini = ngr->part[ii] ;
01076      nm   = NI_element_name( nini ) ;
01077      if( nm != NULL && strcmp(nm,enam) == 0 ){
01078        nelar = (void **) NI_realloc(nelar,void*,nn+1) ;
01079        nelar[nn++] = nini ;
01080      }
01081      if( NI_element_type(nini) == NI_GROUP_TYPE ){  /* recursion */
01082        int nsub , jj ; void **esub ;
01083        nsub = NI_search_group_deep( nini , enam , &esub ) ;
01084        if( nsub > 0 ){
01085          nelar = (void **) NI_realloc(nelar,void*,nn+nsub) ;
01086          for( jj=0 ; jj < nsub ; jj++ ) nelar[nn++] = esub[jj] ;
01087          NI_free(esub) ;
01088        }
01089      }
01090    }
01091 
01092    if( nn > 0 ) *nipt = nelar ;
01093    return nn ;
01094 }
 

Powered by Plone

This site conforms to the following standards: