Doxygen Source Code Documentation
niml_header.c File Reference
#include "niml_private.h"Go to the source code of this file.
Defines | |
| #define | SKIPABL(c) ((c)=='#' || isspace(c)) |
Functions | |
| char * | get_header_attribute (header_stuff *hs, char *attname) |
| void | destroy_header_stuff (header_stuff *hs) |
| intpair | find_string (int nst, int nch, char *ch) |
| header_stuff * | parse_header_stuff (int ndat, char *dat, int *nused) |
| intpair | decode_type_field (char *tf) |
| NI_str_array * | NI_decode_string_list (char *ss, char *sep) |
| int_array * | decode_dimen_string (char *ds) |
| int_array * | decode_type_string (char *ts) |
Define Documentation
|
|
Macro to define skippable characters. Definition at line 9 of file niml_header.c. Referenced by parse_header_stuff(). |
Function Documentation
|
|
Decode a ni_dimen string into an array of integers. Returns NULL if the input is bad bad bad. ---------------------------------------------------------------------- Definition at line 391 of file niml_header.c. References int_array::ar, NI_free, NI_malloc, NI_realloc, NI_strlen(), and int_array::num. Referenced by make_empty_data_element().
00392 {
00393 int num , dd,nn,id,jd , lds ;
00394 int_array *iar ;
00395
00396 if( ds == NULL || ds[0] == '\0' ) return NULL ;
00397
00398 iar = NI_malloc(int_array, sizeof(int_array)) ; /* create output */
00399 iar->num = 0 ; iar->ar = NULL ;
00400
00401 /* scan string for integers */
00402
00403 num = id = 0 ;
00404 lds = NI_strlen(ds) ;
00405 do{
00406 /* skip ahead until ds[id] is a digit */
00407
00408 while( id < lds && !isdigit(ds[id]) ) id++ ;
00409 if( id == lds ) break ; /* end of input */
00410
00411 /* decode integer starting here */
00412
00413 nn = jd = 0 ;
00414 sscanf( ds+id , "%d%n" , &jd , &nn ) ; /* get the count */
00415 if( jd < 0 || nn <= 0 ) break ; /* something bad */
00416 id += nn ; /* skip these chars */
00417
00418 /* extend output array, store new dimension in it */
00419
00420 iar->ar = NI_realloc( iar->ar , int, sizeof(int)*(num+1) ) ;
00421 iar->ar[num++] = jd ;
00422 } while(1) ;
00423
00424 if( num == 0 ){ NI_free(iar); return NULL; } /* bad */
00425
00426 iar->num = num ; return iar ;
00427 }
|
|
|
Decode a single type field. Return value is an intpair with the .i component being the type code and the .j component being the number of characters consumed. If the .i component is -1, then no legal type was found (.j is still the number of chars used in the scan). ---------------------------------------------------------------------- Definition at line 249 of file niml_header.c. References intpair::i, IS_NAME_CHAR, intpair::j, NI_BYTE, NI_COMPLEX, NI_DOUBLE, NI_FLOAT, NI_INT, NI_RGB, NI_RGBA, NI_rowtype_name_to_code(), NI_SHORT, and NI_STRING. Referenced by decode_type_string().
00250 {
00251 intpair ans = {-1,1} ; /* default answer */
00252 char tname[256] ;
00253 int jj ;
00254
00255 /* check input for goodness */
00256
00257 if( tf == NULL || !isalpha(*tf) ) return ans ; /* prima facie bad */
00258
00259 #if 1 /*** The new way! Look for full names, not initials - RWCcox ***/
00260
00261 /* copy input into local string,
00262 as long as 'name' characters are found,
00263 then get the integer code for this type name */
00264
00265 for( jj=0 ; jj < 255 && IS_NAME_CHAR(tf[jj]) ; jj++ ) tname[jj] = tf[jj];
00266 tname[jj] = '\0' ;
00267 ans.i = NI_rowtype_name_to_code( tname ) ; /* where the names are stored */
00268 ans.j = jj ;
00269
00270 #else /*** This is the old way! Replaced on 12 Feb 2003 - RWCox ***/
00271
00272 /* check if tf[0] starts a full datum name,
00273 or if it is just an initial */
00274
00275 switch( tf[0] ){
00276
00277 default: break ; /* not a legal datum character */
00278
00279 case 'b':
00280 ans.i = NI_BYTE ;
00281 if( strncmp(tf,"byte" ,4) == 0 ) ans.j = 4 ;
00282 break ;
00283
00284 case 's':
00285 ans.i = NI_SHORT ;
00286 if( strncmp(tf,"short" ,5) == 0 ) ans.j = 5 ;
00287 break ;
00288
00289 case 'i':
00290 ans.i = NI_INT ;
00291 if( strncmp(tf,"int" ,3) == 0 ) ans.j = 3 ;
00292 break ;
00293
00294 case 'f':
00295 ans.i = NI_FLOAT ;
00296 if( strncmp(tf,"float" ,5) == 0 ) ans.j = 5 ;
00297 break ;
00298
00299 case 'c':
00300 ans.i = NI_COMPLEX ;
00301 if( strncmp(tf,"complex",7) == 0 ) ans.j = 7 ;
00302 break ;
00303
00304 case 'd':
00305 ans.i = NI_DOUBLE ;
00306 if( strncmp(tf,"double" ,6) == 0 ) ans.j = 6 ;
00307 break ;
00308
00309 case 'r':
00310 ans.i = NI_RGB ;
00311 if( strncmp(tf,"rgb" ,3) == 0 ) ans.j = 3 ;
00312 break ;
00313
00314 case 'R':
00315 ans.i = NI_RGBA ;
00316 if( strncmp(tf,"RGBA" ,4) == 0 ) ans.j = 4 ;
00317 break ;
00318
00319 case 'S':
00320 ans.i = NI_STRING ;
00321 if( strncmp(tf,"STRING" ,6) == 0 ) ans.j = 6 ;
00322 break ;
00323 }
00324 #endif
00325
00326 return ans ;
00327 }
|
|
|
Decode a data type string into an array of integer codes. Returns NULL if the input is bad bad bad. ---------------------------------------------------------------------- Definition at line 434 of file niml_header.c. References int_array::ar, decode_type_field(), intpair::i, intpair::j, NI_free, NI_malloc, NI_realloc, NI_strlen(), int_array::num, and typ. Referenced by make_empty_data_element(), SUMA_TypeOfColNumb(), and SUMA_TypeOfDsetColNumb().
00435 {
00436 int num, typ, lts, id,jd, nn,kk ;
00437 int_array *iar ;
00438 intpair dc ;
00439
00440 if( ts == NULL || ts[0] == '\0' ) return NULL ;
00441
00442 iar = NI_malloc(int_array, sizeof(int_array)) ; /* create output */
00443 iar->num = 0 ; iar->ar = NULL ;
00444
00445 /* scan type string to find counts/fields and add to output */
00446
00447 lts = NI_strlen(ts) ;
00448 num = 0 ; /* will be count of fields */
00449
00450 for( id=kk=0 ; id < lts ; ){ /* loop over input string */
00451
00452 if( isdigit(ts[id]) ){ /* a count prefix */
00453 jd = nn = 0 ;
00454 sscanf( ts+id , "%d%n" , &jd , &nn ) ; /* get the count */
00455 if( jd <= 0 || nn <= 0 ){ /* shouldn't happen */
00456 NI_free(iar->ar) ; NI_free(iar) ; return NULL ;
00457 }
00458 id += nn ; /* skip count prefix characters */
00459 if( ts[id] == '*' ) id++ ; /* allow for "3*float" */
00460
00461 } else if( isalpha(ts[id]) ){ /* start of a type name */
00462 jd = 1 ; /* default count of 1 */
00463
00464 } else {
00465 id++ ; continue ; /* skip this character */
00466 }
00467
00468 dc = decode_type_field( ts+id ) ;
00469
00470 /* dc.i = type code; dc.j = character count used to get type code */
00471
00472 id += dc.j ; /* skip these characters */
00473 if( dc.i < 0 ) continue ; /* bad type code */
00474
00475 num += jd ; /* this many fields so far */
00476
00477 /* extend output array length */
00478
00479 iar->ar = NI_realloc( iar->ar , int, sizeof(int)*num ) ;
00480
00481 /* put values into output array */
00482
00483 for( nn=0 ; nn < jd ; nn++ ) iar->ar[kk++] = dc.i ;
00484
00485 } /* end of loop over input string */
00486
00487 /* nothing found? */
00488
00489 if( num <= 0 ){
00490 NI_free(iar->ar) ; NI_free(iar) ; return NULL ; /* bad */
00491 }
00492
00493 iar->num = num ; return iar ;
00494 }
|
|
|
Deallocate a header_stuff struct. ---------------------------------------------------------------------------- Definition at line 36 of file niml_header.c. References header_stuff::lhs, header_stuff::name, header_stuff::nattr, NI_free, and header_stuff::rhs. Referenced by NI_read_element(), and parse_header_stuff().
|
|
||||||||||||||||
|
Find an isolated string in the input array of char.
Definition at line 61 of file niml_header.c. References intpair::i, IS_QUOTE_CHAR, IS_STRING_CHAR, intpair::j, and NI_dpr(). Referenced by NI_decode_one_string(), and parse_header_stuff().
00062 {
00063 intpair ans = {-1,-1} ; /* default answer ==> nothing found */
00064 int ii,jj ;
00065 char quot ;
00066
00067 #ifdef NIML_DEBUG
00068 NI_dpr(" ENTER find_string: nst=%d nch=%d\n",nst,nch) ;
00069 #endif
00070
00071 if( nst >= nch || nch < 2 || ch == NULL ) return ans; /* bad input */
00072
00073 for( ii=nst; ii<nch && !IS_STRING_CHAR(ch[ii]); ii++ ) ; /* skip to start */
00074
00075 if( ii >= nch ) return ans ; /* bad input */
00076
00077 if( IS_QUOTE_CHAR(ch[ii]) ){ /* quoted string */
00078 if( ii == nch-1 ) return ans ; /* bad input */
00079 quot = ch[ii] ; ii++ ;
00080 for( jj=ii ; jj<nch && ch[jj] != quot ; jj++ ) ; /* skip to close */
00081 } else {
00082 for( jj=ii+1 ; jj<nch && IS_STRING_CHAR(ch[jj]) ; jj++ ) ; /* to blank */
00083 }
00084
00085 ans.i = ii ; ans.j = jj ; /* answer starts at ch[ii] and goes to ch[jj-1] */
00086 return ans ;
00087 }
|
|
||||||||||||
|
Find an attribute in a header_stuff struct. Returns the RHS or NULL. ---------------------------------------------------------------------------- Definition at line 15 of file niml_header.c. References header_stuff::lhs, header_stuff::nattr, and header_stuff::rhs. Referenced by header_stuff_is_group().
00016 {
00017 int nn ;
00018 static char *zorkon = "\0" ;
00019
00020 if( hs == NULL ) return NULL ;
00021
00022 for( nn=0 ; nn < hs->nattr ; nn++ )
00023 if( strcmp(hs->lhs[nn],attname) == 0 ) break ;
00024
00025 if( nn == hs->nattr ) return NULL ;
00026
00027 if( hs->rhs[nn] == NULL ) return zorkon ;
00028
00029 return hs->rhs[nn] ;
00030 }
|
|
||||||||||||
|
Decode a single string into a bunch of strings, separated by characters from the list in sep.
Definition at line 338 of file niml_header.c. References NI_malloc, NI_realloc, NI_strlen(), NI_str_array::num, and NI_str_array::str. Referenced by basis_parser(), make_empty_data_element(), mri_1D_fromstring(), NI_rowtype_define(), SYM_expand_ranges(), THD_datablock_from_atr(), THD_load_tcat(), THD_open_3D(), and THD_open_tcat().
00339 {
00340 NI_str_array *sar ;
00341 int num , nn,id,jd , lss ;
00342
00343 if( ss == NULL || ss[0] == '\0' ) return NULL ; /* bad input */
00344
00345 if( sep == NULL || sep[0] == '\0' ) sep = "," ; /* default sep */
00346
00347 sar = NI_malloc(NI_str_array, sizeof(NI_str_array)) ; /* create output */
00348 sar->num = 0 ; sar->str = NULL ;
00349
00350 /* scan for sub-strings */
00351
00352 lss = NI_strlen(ss) ;
00353 num = id = 0 ;
00354 while( id < lss ){
00355
00356 /* skip current position ahead over whitespace */
00357
00358 while( id < lss && isspace(ss[id]) ) id++ ;
00359 if( id == lss ) break ; /* ran out of string */
00360
00361 jd = id ; /* save current position (start of new string) */
00362
00363 /* skip ahead until ss[id] is a separator [or a space - 10 Dec 2002] */
00364
00365 while( id < lss && strchr(sep,ss[id]) == NULL && !isspace(ss[id]) ) id++;
00366 if( id == jd ){ id++; continue; } /* is only a separator? */
00367
00368 /* new sub-string runs from ss[jd] to ss[id-1] */
00369
00370 sar->str = NI_realloc( sar->str , char*, sizeof(char *)*(num+1) ) ;
00371
00372 nn = id-jd ; /* length of sub-string */
00373 #if 0
00374 while( nn > 0 && isspace(ss[jd+nn-1]) ) nn-- ; /* clip trailing blanks */
00375 #endif
00376 sar->str[num] = NI_malloc(char, nn+1) ; /* make output string */
00377 if( nn > 0 ) memcpy(sar->str[num],ss+jd,nn) ; /* copy sub-string */
00378 sar->str[num++][nn] = '\0' ; /* terminate output */
00379
00380 id++ ; /* skip separator */
00381 }
00382
00383 sar->num = num ; return sar ;
00384 }
|
|
||||||||||||||||
|
Parse into strings a <header and=its attributes="stuff">.
Definition at line 101 of file niml_header.c. References destroy_header_stuff(), header_stuff::empty, find_string(), intpair::i, IS_QUOTE_CHAR, intpair::j, header_stuff::lhs, header_stuff::name, header_stuff::nattr, NI_dpr(), NI_malloc, NI_realloc, NI_strncpy(), header_stuff::rhs, SKIPABL, and unescape_inplace(). Referenced by NI_read_element().
00102 {
00103 header_stuff *hs ; /* return value */
00104 int id,jd , nn ;
00105 intpair ss ;
00106
00107 if( ndat < 2 || dat == NULL ) return NULL ; /* bad input */
00108
00109 #ifdef NIML_DEBUG
00110 NI_dpr("ENTER parse_header_stuff: %.*s\n",ndat,dat) ;
00111 #endif
00112
00113 for( id=0 ; id < ndat && dat[id] != '<' ; id++ ) ; /* skip to opening '<' */
00114
00115 if( id >= ndat-1 ) return NULL ; /* bad input */
00116
00117 hs = NI_malloc(header_stuff,sizeof(header_stuff)); /* make output struct */
00118 hs->nattr = hs->empty = 0 ;
00119 hs->name = NULL ;
00120 hs->lhs = hs->rhs = NULL ;
00121
00122 /* find and assign name string (immediately after '<') */
00123
00124 ss = find_string( id+1 , ndat , dat ) ;
00125
00126 if( ss.i < 0 || ss.j <= ss.i ){
00127 destroy_header_stuff( hs ) ; return NULL ; /* no name string */
00128 }
00129
00130 nn = ss.j - ss.i ; /* string length */
00131 hs->name = NI_malloc(char, nn+1) ;
00132 NI_strncpy( hs->name , dat+ss.i , nn+1 ) ;
00133
00134 #ifdef NIML_DEBUG
00135 NI_dpr(" parse_header_stuff: name = %s\n",hs->name) ;
00136 #endif
00137
00138 /* start scanning for next string at location id */
00139
00140 id = ss.j ; if( IS_QUOTE_CHAR(dat[id]) ) id++ ;
00141
00142 /* find and assign attribute strings */
00143
00144 while(1){
00145
00146 #ifdef NIML_DEBUG
00147 NI_dpr(" parse_header_stuff: scan start at id=%d\n",id) ;
00148 #endif
00149
00150 for( ; id < ndat && SKIPABL(dat[id]) ; id++ ) ; /* skip blanks */
00151
00152 if( id >= ndat ) break ; /* end of input found */
00153
00154 if( dat[id] == '>' ) break ; /* ">" end found */
00155
00156 if( dat[id] == '/' ){ /* "/>" end found */
00157 if( id < ndat-1 ) id++ ; /* skip the '>' */
00158 hs->empty = 1 ; /* mark header as 'empty' */
00159 break ; /* done with scanning for attributes */
00160 }
00161
00162 if( dat[id] == '?' ){ /* "?>" found */
00163 if( id < ndat-1 ) id++ ; /* ==> this is a procins! */
00164 hs->empty = 1 ;
00165 break ;
00166 }
00167
00168 /* find next string */
00169
00170 ss = find_string( id , ndat , dat ) ;
00171
00172 if( ss.i < 0 || ss.j <= ss.i ) break ; /* didn't find a string */
00173
00174 #ifdef NIML_DEBUG
00175 NI_dpr(" parse_header_stuff: next string = %.*s\n",ss.j-ss.i,dat+ss.i) ;
00176 #endif
00177
00178 /* extend size of attribute arrays */
00179
00180 hs->lhs = NI_realloc( hs->lhs , char*, sizeof(char *)*(hs->nattr+1) ) ;
00181 hs->rhs = NI_realloc( hs->rhs , char*, sizeof(char *)*(hs->nattr+1) ) ;
00182
00183 /* this is the LHS string */
00184
00185 nn = ss.j - ss.i ; /* length of string */
00186 hs->lhs[hs->nattr] = NI_malloc(char, nn+1) ;
00187 NI_strncpy( hs->lhs[hs->nattr] , dat+ss.i , nn+1 ) ;
00188 unescape_inplace( hs->lhs[hs->nattr] ) ;
00189
00190 hs->rhs[hs->nattr] = NULL ; /* in case there is no RHS */
00191
00192 id = ss.j ;
00193 if( id >= ndat ) break ; /* end of input ? */
00194 if( IS_QUOTE_CHAR(dat[id]) ) id++ ; /* skip close quote */
00195 while( id < ndat && SKIPABL(dat[id]) ) id++ ; /* skip blanks */
00196 if( id >= ndat ) break ; /* end of input ? */
00197
00198 if( dat[id] != '=' ){ /* no '=' means no RHS */
00199 (hs->nattr)++ ; /* count the LHS and */
00200 continue ; /* go get next attribute */
00201 }
00202
00203 id++ ; /* skip the '=' */
00204 while( id < ndat && SKIPABL(dat[id]) ) id++ ; /* skip blanks */
00205 if( id >= ndat ) break ; /* end of input ? */
00206
00207 /* find next string (the RHS) */
00208
00209 ss = find_string( id , ndat , dat ) ;
00210
00211 if( ss.i < 0 || ss.j <= ss.i ) break ; /* didn't find a string */
00212
00213 #ifdef NIML_DEBUG
00214 NI_dpr(" parse_header_stuff: next string = %.*s\n",ss.j-ss.i,dat+ss.i) ;
00215 #endif
00216
00217 /* this is the RHS string */
00218
00219 nn = ss.j - ss.i ; /* length of string */
00220 hs->rhs[hs->nattr] = NI_malloc(char, nn+1) ;
00221 NI_strncpy( hs->rhs[hs->nattr] , dat+ss.i , nn+1 ) ;
00222 unescape_inplace( hs->rhs[hs->nattr] ) ;
00223
00224 (hs->nattr)++ ; /* increment attribute count */
00225
00226 /* start scanning for next string at location id */
00227
00228 id = ss.j ;
00229 if( IS_QUOTE_CHAR(dat[id]) ) id++ ; /* skip closing quote */
00230
00231 } /* end of loop over input */
00232
00233 if( nused != NULL ){
00234 if( id >= ndat ) id = ndat-1 ;
00235 *nused = id+1 ; /* number of bytes used from dat */
00236 }
00237
00238 return hs ; /* the goal of all that work */
00239 }
|