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 } |