00001 #include "niml_private.h"
00002
00003
00004
00005
00006
00007
00008
00009 #define SKIPABL(c) ((c)=='#' || isspace(c))
00010
00011
00012
00013
00014
00015 char * get_header_attribute( header_stuff *hs , char *attname )
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 }
00031
00032
00033
00034
00035
00036 void destroy_header_stuff( header_stuff *hs )
00037 {
00038 int ii ;
00039 if( hs == NULL ) return ;
00040 NI_free(hs->name) ;
00041 for( ii=0 ; ii < hs->nattr ; ii++ ){
00042 if( hs->lhs != NULL ) NI_free( hs->lhs[ii] ) ;
00043 if( hs->rhs != NULL ) NI_free( hs->rhs[ii] ) ;
00044 }
00045 NI_free( hs ) ;
00046 }
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 intpair find_string( int nst, int nch, char *ch )
00062 {
00063 intpair ans = {-1,-1} ;
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;
00072
00073 for( ii=nst; ii<nch && !IS_STRING_CHAR(ch[ii]); ii++ ) ;
00074
00075 if( ii >= nch ) return ans ;
00076
00077 if( IS_QUOTE_CHAR(ch[ii]) ){
00078 if( ii == nch-1 ) return ans ;
00079 quot = ch[ii] ; ii++ ;
00080 for( jj=ii ; jj<nch && ch[jj] != quot ; jj++ ) ;
00081 } else {
00082 for( jj=ii+1 ; jj<nch && IS_STRING_CHAR(ch[jj]) ; jj++ ) ;
00083 }
00084
00085 ans.i = ii ; ans.j = jj ;
00086 return ans ;
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 header_stuff * parse_header_stuff( int ndat, char *dat, int *nused )
00102 {
00103 header_stuff *hs ;
00104 int id,jd , nn ;
00105 intpair ss ;
00106
00107 if( ndat < 2 || dat == NULL ) return NULL ;
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++ ) ;
00114
00115 if( id >= ndat-1 ) return NULL ;
00116
00117 hs = NI_malloc(header_stuff,sizeof(header_stuff));
00118 hs->nattr = hs->empty = 0 ;
00119 hs->name = NULL ;
00120 hs->lhs = hs->rhs = NULL ;
00121
00122
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 ;
00128 }
00129
00130 nn = ss.j - ss.i ;
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
00139
00140 id = ss.j ; if( IS_QUOTE_CHAR(dat[id]) ) id++ ;
00141
00142
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++ ) ;
00151
00152 if( id >= ndat ) break ;
00153
00154 if( dat[id] == '>' ) break ;
00155
00156 if( dat[id] == '/' ){
00157 if( id < ndat-1 ) id++ ;
00158 hs->empty = 1 ;
00159 break ;
00160 }
00161
00162 if( dat[id] == '?' ){
00163 if( id < ndat-1 ) id++ ;
00164 hs->empty = 1 ;
00165 break ;
00166 }
00167
00168
00169
00170 ss = find_string( id , ndat , dat ) ;
00171
00172 if( ss.i < 0 || ss.j <= ss.i ) break ;
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
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
00184
00185 nn = ss.j - ss.i ;
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 ;
00191
00192 id = ss.j ;
00193 if( id >= ndat ) break ;
00194 if( IS_QUOTE_CHAR(dat[id]) ) id++ ;
00195 while( id < ndat && SKIPABL(dat[id]) ) id++ ;
00196 if( id >= ndat ) break ;
00197
00198 if( dat[id] != '=' ){
00199 (hs->nattr)++ ;
00200 continue ;
00201 }
00202
00203 id++ ;
00204 while( id < ndat && SKIPABL(dat[id]) ) id++ ;
00205 if( id >= ndat ) break ;
00206
00207
00208
00209 ss = find_string( id , ndat , dat ) ;
00210
00211 if( ss.i < 0 || ss.j <= ss.i ) break ;
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
00218
00219 nn = ss.j - ss.i ;
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)++ ;
00225
00226
00227
00228 id = ss.j ;
00229 if( IS_QUOTE_CHAR(dat[id]) ) id++ ;
00230
00231 }
00232
00233 if( nused != NULL ){
00234 if( id >= ndat ) id = ndat-1 ;
00235 *nused = id+1 ;
00236 }
00237
00238 return hs ;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 intpair decode_type_field( char *tf )
00250 {
00251 intpair ans = {-1,1} ;
00252 char tname[256] ;
00253 int jj ;
00254
00255
00256
00257 if( tf == NULL || !isalpha(*tf) ) return ans ;
00258
00259 #if 1
00260
00261
00262
00263
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 ) ;
00268 ans.j = jj ;
00269
00270 #else
00271
00272
00273
00274
00275 switch( tf[0] ){
00276
00277 default: break ;
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 }
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 NI_str_array * NI_decode_string_list( char *ss , char *sep )
00339 {
00340 NI_str_array *sar ;
00341 int num , nn,id,jd , lss ;
00342
00343 if( ss == NULL || ss[0] == '\0' ) return NULL ;
00344
00345 if( sep == NULL || sep[0] == '\0' ) sep = "," ;
00346
00347 sar = NI_malloc(NI_str_array, sizeof(NI_str_array)) ;
00348 sar->num = 0 ; sar->str = NULL ;
00349
00350
00351
00352 lss = NI_strlen(ss) ;
00353 num = id = 0 ;
00354 while( id < lss ){
00355
00356
00357
00358 while( id < lss && isspace(ss[id]) ) id++ ;
00359 if( id == lss ) break ;
00360
00361 jd = id ;
00362
00363
00364
00365 while( id < lss && strchr(sep,ss[id]) == NULL && !isspace(ss[id]) ) id++;
00366 if( id == jd ){ id++; continue; }
00367
00368
00369
00370 sar->str = NI_realloc( sar->str , char*, sizeof(char *)*(num+1) ) ;
00371
00372 nn = id-jd ;
00373 #if 0
00374 while( nn > 0 && isspace(ss[jd+nn-1]) ) nn-- ;
00375 #endif
00376 sar->str[num] = NI_malloc(char, nn+1) ;
00377 if( nn > 0 ) memcpy(sar->str[num],ss+jd,nn) ;
00378 sar->str[num++][nn] = '\0' ;
00379
00380 id++ ;
00381 }
00382
00383 sar->num = num ; return sar ;
00384 }
00385
00386
00387
00388
00389
00390
00391 int_array * decode_dimen_string( char *ds )
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)) ;
00399 iar->num = 0 ; iar->ar = NULL ;
00400
00401
00402
00403 num = id = 0 ;
00404 lds = NI_strlen(ds) ;
00405 do{
00406
00407
00408 while( id < lds && !isdigit(ds[id]) ) id++ ;
00409 if( id == lds ) break ;
00410
00411
00412
00413 nn = jd = 0 ;
00414 sscanf( ds+id , "%d%n" , &jd , &nn ) ;
00415 if( jd < 0 || nn <= 0 ) break ;
00416 id += nn ;
00417
00418
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; }
00425
00426 iar->num = num ; return iar ;
00427 }
00428
00429
00430
00431
00432
00433
00434 int_array * decode_type_string( char *ts )
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)) ;
00443 iar->num = 0 ; iar->ar = NULL ;
00444
00445
00446
00447 lts = NI_strlen(ts) ;
00448 num = 0 ;
00449
00450 for( id=kk=0 ; id < lts ; ){
00451
00452 if( isdigit(ts[id]) ){
00453 jd = nn = 0 ;
00454 sscanf( ts+id , "%d%n" , &jd , &nn ) ;
00455 if( jd <= 0 || nn <= 0 ){
00456 NI_free(iar->ar) ; NI_free(iar) ; return NULL ;
00457 }
00458 id += nn ;
00459 if( ts[id] == '*' ) id++ ;
00460
00461 } else if( isalpha(ts[id]) ){
00462 jd = 1 ;
00463
00464 } else {
00465 id++ ; continue ;
00466 }
00467
00468 dc = decode_type_field( ts+id ) ;
00469
00470
00471
00472 id += dc.j ;
00473 if( dc.i < 0 ) continue ;
00474
00475 num += jd ;
00476
00477
00478
00479 iar->ar = NI_realloc( iar->ar , int, sizeof(int)*num ) ;
00480
00481
00482
00483 for( nn=0 ; nn < jd ; nn++ ) iar->ar[kk++] = dc.i ;
00484
00485 }
00486
00487
00488
00489 if( num <= 0 ){
00490 NI_free(iar->ar) ; NI_free(iar) ; return NULL ;
00491 }
00492
00493 iar->num = num ; return iar ;
00494 }