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 }