00001 #include "niml_private.h"
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 typedef struct { char a; byte    b; } Qadgop_byte    ;  
00013 typedef struct { char a; short   b; } Qadgop_short   ;
00014 typedef struct { char a; int     b; } Qadgop_int     ;
00015 typedef struct { char a; float   b; } Qadgop_float   ;
00016 typedef struct { char a; double  b; } Qadgop_double  ;
00017 typedef struct { char a; complex b; } Qadgop_complex ;
00018 typedef struct { char a; rgb     b; } Qadgop_rgb     ;
00019 typedef struct { char a; rgba    b; } Qadgop_rgba    ;
00020 
00021 
00022 
00023 static int   type_alignment[NI_NUM_BASIC_TYPES+1] ;
00024 static int   type_size     [NI_NUM_BASIC_TYPES+1] ;
00025 static char *type_name     [NI_NUM_BASIC_TYPES+1] = {
00026   "byte"  , "short"  , "int"     ,
00027   "float" , "double" , "complex" ,
00028   "rgb"   , "rgba"   , "String"
00029 } ;
00030 
00031 static char *type_alias[NI_NUM_BASIC_TYPES+1] = {   
00032   "uint8"   , "int16"   , "int32"     ,
00033   "float32" , "float64" , "complex64" ,
00034   "rgb8"    , "rgba8"   , "CString"
00035 } ;
00036 
00037 
00038 
00039 typedef struct { char a; void *b; } Qadgop_pointer ;
00040 static int pointer_alignment ;
00041 static int pointer_size ;
00042 
00043 
00044 
00045 
00046 static Htable *rowtype_table = NULL ;
00047 
00048 
00049 
00050 
00051 static NI_rowtype **rowtype_array = NULL ;
00052 static int         rowtype_num    = 0    ;
00053 
00054 
00055 
00056 
00057 #define ROWTYPE_OFFSET     1001
00058 
00059 
00060 
00061 
00062 
00063 #define ROWTYPE_BASE_CODE (ROWTYPE_OFFSET-NI_NUM_BASIC_TYPES-1)
00064 
00065 
00066 
00067 #define ROWTYPE_is_builtin_code(cc) ((cc) >= 0 && (cc) < ROWTYPE_OFFSET)
00068 
00069 
00070 
00071 #define ROWTYPE_register(rr)                               \
00072  do{ int nn ;                                              \
00073      if( rowtype_table == NULL ) setup_basic_types() ;     \
00074      addto_Htable( (rr)->name , (rr) , rowtype_table ) ;   \
00075      nn = rowtype_num + 1 ;                                \
00076      rowtype_array = NI_realloc( rowtype_array ,           \
00077                                  NI_rowtype*,              \
00078                                 sizeof(NI_rowtype *)*nn ); \
00079      rowtype_array[nn-1] = rr ;  rowtype_num = nn ;        \
00080  } while(0)
00081 
00082 
00083 
00084 
00085 static int ROWTYPE_debug = 0 ;
00086 
00087 
00088 
00089 void NI_rowtype_debug( int n ){ ROWTYPE_debug = n ; }
00090 
00091 
00092 
00093 
00094 static void setup_basic_types(void)
00095 {
00096    NI_rowtype *rt ;
00097    int ii ;
00098 
00099    if( rowtype_table != NULL ) return ;  
00100 
00101    
00102 
00103    type_alignment[NI_BYTE   ] = offsetof(Qadgop_byte   ,b) ;
00104    type_alignment[NI_SHORT  ] = offsetof(Qadgop_short  ,b) ;
00105    type_alignment[NI_INT    ] = offsetof(Qadgop_int    ,b) ;
00106    type_alignment[NI_FLOAT  ] = offsetof(Qadgop_float  ,b) ;
00107    type_alignment[NI_DOUBLE ] = offsetof(Qadgop_double ,b) ;
00108    type_alignment[NI_COMPLEX] = offsetof(Qadgop_complex,b) ;
00109    type_alignment[NI_RGB    ] = offsetof(Qadgop_rgb    ,b) ;
00110    type_alignment[NI_RGBA   ] = offsetof(Qadgop_rgba   ,b) ;
00111 
00112    type_size[NI_BYTE   ] = sizeof(byte   ) ;
00113    type_size[NI_SHORT  ] = sizeof(short  ) ;
00114    type_size[NI_INT    ] = sizeof(int    ) ;
00115    type_size[NI_FLOAT  ] = sizeof(float  ) ;
00116    type_size[NI_DOUBLE ] = sizeof(double ) ;
00117    type_size[NI_COMPLEX] = sizeof(complex) ;
00118    type_size[NI_RGB    ] = sizeof(rgb    ) ;
00119    type_size[NI_RGBA   ] = sizeof(rgba   ) ;
00120 
00121    
00122 
00123    rowtype_table = new_Htable(19) ;
00124 
00125    for( ii=0 ; ii < NI_NUM_BASIC_TYPES ; ii++ ){
00126 
00127      rt              = NI_new( NI_rowtype ) ;
00128      rt->code        = ii ;
00129      rt->size        = type_size[ii] ;          
00130      rt->psiz        = rt->size ;               
00131      rt->algn        = type_alignment[ii] ;     
00132      rt->name        = NI_strdup(type_name[ii]);
00133      rt->userdef     = NI_strdup(type_name[ii]);
00134      rt->flag        = 0 ;
00135 
00136      rt->comp_num    = 1 ;                      
00137      rt->comp_typ    = NI_malloc(int, sizeof(int)) ; 
00138      rt->comp_typ[0] = ii ;
00139      rt->comp_dim    = NI_malloc(int, sizeof(int)) ;
00140      rt->comp_dim[0] = -1 ;                     
00141 
00142      rt->part_num    = 1 ;                      
00143      rt->part_typ    = NI_malloc(int, sizeof(int)) ; 
00144      rt->part_typ[0] = ii ;
00145      rt->part_off    = NI_malloc(int, sizeof(int)) ;
00146      rt->part_off[0] = 0 ;
00147      rt->part_siz    = NI_malloc(int, sizeof(int)) ;
00148      rt->part_siz[0] = type_size[ii] ;
00149      rt->part_dim    = NI_malloc(int, sizeof(int)) ;
00150      rt->part_dim[0] = -1 ;                     
00151      rt->part_rtp    = NI_malloc(NI_rowtype*, sizeof(NI_rowtype *)) ;
00152      rt->part_rtp[0] = rt ;
00153 
00154      ROWTYPE_register( rt ) ;                   
00155    }
00156 
00157    
00158 
00159    pointer_alignment = offsetof(Qadgop_pointer,b) ;
00160    pointer_size      = sizeof(void *) ;
00161 
00162    
00163 
00164    type_alignment[NI_STRING] = pointer_alignment ;
00165    type_size     [NI_STRING] = pointer_size ;
00166 
00167    rt              = NI_new( NI_rowtype ) ;
00168    rt->code        = NI_STRING ;
00169    rt->size        = pointer_size ;
00170    rt->psiz        = 0 ;                       
00171    rt->algn        = pointer_alignment ;
00172    rt->name        = NI_strdup("String") ;
00173    rt->userdef     = NI_strdup("String") ;
00174    rt->flag        = ROWTYPE_VARSIZE_MASK ;    
00175 
00176    rt->comp_num    = 1 ;
00177    rt->comp_typ    = NI_malloc(int, sizeof(int)) ;
00178    rt->comp_typ[0] = NI_STRING ;
00179    rt->comp_dim    = NI_malloc(int, sizeof(int)) ;
00180    rt->comp_dim[0] = -1 ;
00181 
00182    rt->part_num    = 1 ;
00183    rt->part_typ    = NI_malloc(int, sizeof(int)) ;
00184    rt->part_typ[0] = NI_STRING ;
00185    rt->part_off    = NI_malloc(int, sizeof(int)) ;
00186    rt->part_off[0] = 0 ;
00187    rt->part_siz    = NI_malloc(int, sizeof(int)) ;
00188    rt->part_siz[0] = pointer_size ;
00189    rt->part_dim    = NI_malloc(int, sizeof(int)) ;
00190    rt->part_dim[0] = -1 ;
00191 
00192    rt->part_rtp    = NI_malloc(NI_rowtype*, sizeof(NI_rowtype *)) ;
00193    rt->part_rtp[0] = rt ;
00194 
00195    ROWTYPE_register( rt ) ;
00196 
00197    if( ROWTYPE_debug )
00198      profile_Htable( "rowtype_table" , rowtype_table ) ;
00199 }
00200 
00201 
00202 
00203 
00204 #undef  ERREX
00205 #define ERREX(str)                                                            \
00206  do { fprintf(stderr,"** NI_rowtype_define('%s','%s'): %s\n",tname,tdef,str); \
00207       return -1 ; } while(0)
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 int NI_rowtype_define( char *tname , char *tdef )
00267 {
00268    NI_rowtype *rt , *qt ;
00269    int ii,jj , id,jd,kd,isdim,nn , almax,cbase,np,pb , last_size ;
00270    NI_str_array *sar ;
00271    char *tp,*sp,*bp , str[256] ;
00272 
00273    
00274 
00275    if( !NI_is_name(tname) )              ERREX("bad typename") ;
00276    if( strlen(tname) > 255 )             ERREX("toolong typename") ;
00277    if( tdef  == NULL || *tdef  == '\0' ) ERREX("empty type definition") ;
00278 
00279    
00280 
00281    if( rowtype_table == NULL ) setup_basic_types() ;
00282 
00283    
00284    
00285 
00286    rt = NI_rowtype_find_name( tname ) ;
00287    if( rt != NULL ){
00288      if( strcmp(rt->userdef,tdef) != 0 ){
00289        fprintf(stderr,
00290                 "++ NI_rowtype_define: illegal attempt to redefine type '%s'\n"
00291                 "++          old definition: %s\n"
00292                 "++ (failed) new definition: %s\n" ,
00293                tname , rt->userdef , tdef ) ;
00294      }
00295      return rt->code ;
00296    }
00297 
00298    
00299 
00300    sar = NI_decode_string_list( tdef , ",;" ) ;
00301 
00302    if( sar == NULL || sar->num < 1 ){
00303      NI_free(sar) ; ERREX("illegal definition") ;
00304    }
00305 
00306    
00307 
00308    rt          = NI_new( NI_rowtype ) ;
00309    rt->name    = NI_strdup( tname ) ;
00310    rt->userdef = NI_strdup( tdef ) ;
00311    rt->flag    = 0 ;
00312 
00313    
00314 
00315    rt->part_num = rt->comp_num = 0 ;
00316 
00317    for( ii=0 ; ii < sar->num ; ii++ ){
00318 
00319      tp = sar->str[ii] ;
00320      id = 0 ; kd = strlen(tp) ; 
00321      if( kd == 0 ){
00322       delete_rowtype(rt); NI_delete_str_array(sar); ERREX("empty component name?");
00323      }
00324 
00325      
00326 
00327      sp = strchr(tp,'*') ;   
00328      bp = strchr(tp,'[') ;   
00329 
00330      if( sp != NULL || bp != NULL ){            
00331 
00332        if( sp != NULL && bp != NULL ){          
00333         delete_rowtype(rt); NI_delete_str_array(sar); ERREX("two repeat counts?");
00334        }
00335 
00336        if( sp != NULL ){                        
00337          nn = 0 ;                               
00338          id = (sp-tp)+1 ;                       
00339        } else {                                 
00340          kd = (bp-tp) ;                         
00341          nn = kd+1 ;                            
00342        }
00343 
00344        jd = -1 ;
00345        if( tp[nn] != '#' ){                     
00346          isdim = 0 ;
00347          sscanf( tp+nn , "%d" , &jd ) ;
00348          if( jd <= 0 ){
00349           delete_rowtype(rt); NI_delete_str_array(sar); ERREX("bad repeat number");
00350          }
00351        } else {                                 
00352          isdim = 1 ;
00353          sscanf( tp+nn+1 , "%d" , &jd ) ;       
00354          if( jd <= 0 || jd > ii ){              
00355            delete_rowtype(rt); NI_delete_str_array(sar); ERREX("bad #index");
00356          }
00357          if( rt->comp_typ[jd-1] != NI_INT ||    
00358              rt->comp_dim[jd-1] >= 0        ){  
00359            delete_rowtype(rt); NI_delete_str_array(sar); ERREX("non-int #index");
00360          }
00361        }
00362      } else {
00363        isdim = 0 ; jd = 1 ;                     
00364      }
00365 
00366      
00367 
00368      if( kd-id < 1 || kd-id > 255 ){
00369       delete_rowtype(rt); NI_delete_str_array(sar); ERREX("toolong component name");
00370      }
00371 
00372      NI_strncpy( str , tp+id , kd-id+1 ) ;  
00373      qt = NI_rowtype_find_name( str ) ;     
00374      if( qt == NULL ){
00375        delete_rowtype(rt); NI_delete_str_array(sar); ERREX("bad component type");
00376      }
00377 
00378      if( !isdim ){  
00379 
00380        rt->comp_typ = NI_realloc( rt->comp_typ, int, sizeof(int)*(rt->comp_num+jd) );
00381        rt->comp_dim = NI_realloc( rt->comp_dim, int, sizeof(int)*(rt->comp_num+jd) );
00382 
00383        for( jj=0 ; jj < jd ; jj++ ){
00384          rt->comp_typ[rt->comp_num + jj] = qt->code ;
00385          rt->comp_dim[rt->comp_num + jj] = -1 ;        
00386        }
00387 
00388        rt->comp_num += jd ;                 
00389        rt->part_num += jd * qt->part_num ;  
00390 
00391        if( ROWTYPE_is_varsize(qt) )         
00392          rt->flag |= ROWTYPE_VARSIZE_MASK ; 
00393 
00394      } else {       
00395                     
00396                     
00397 
00398        
00399 
00400        if( ROWTYPE_is_varsize(qt) ){
00401          delete_rowtype(rt); NI_delete_str_array(sar);
00402          ERREX("variable dim array must have fixed dim type");
00403        }
00404 
00405        rt->comp_typ = NI_realloc( rt->comp_typ, int, sizeof(int)*(rt->comp_num+1) );
00406        rt->comp_dim = NI_realloc( rt->comp_dim, int, sizeof(int)*(rt->comp_num+1) );
00407 
00408        rt->comp_typ[rt->comp_num] = qt->code ;  
00409        rt->comp_dim[rt->comp_num] = jd-1 ;      
00410                                                 
00411        rt->comp_num ++ ;  
00412        rt->part_num ++ ;  
00413 
00414        rt->flag |= ROWTYPE_VARSIZE_MASK ;   
00415 
00416      }
00417 
00418    } 
00419 
00420    NI_delete_str_array(sar) ;                  
00421 
00422    if( rt->part_num == 0 ){ delete_rowtype(rt); ERREX("no components?"); }
00423 
00424    
00425 
00426 
00427    rt->part_off = NI_malloc(int, sizeof(int)          * rt->part_num ) ;
00428    rt->part_typ = NI_malloc(int, sizeof(int)          * rt->part_num ) ;
00429    rt->part_dim = NI_malloc(int, sizeof(int)          * rt->part_num ) ;
00430    rt->part_siz = NI_malloc(int, sizeof(int)          * rt->part_num ) ;
00431    rt->part_rtp = NI_malloc(NI_rowtype*, sizeof(NI_rowtype *) * rt->part_num ) ;
00432 
00433    almax = 1 ;  
00434    cbase = 0 ;  
00435    id    = 0 ;  
00436 
00437    for( ii=0 ; ii < rt->comp_num ; ii++ ){
00438 
00439                                     
00440      if( rt->comp_dim[ii] >= 0 ){   
00441                                     
00442 
00443        if( pointer_alignment > 1 ){            
00444          jd = cbase % pointer_alignment ;      
00445          if( jd > 0 ) cbase += (pointer_alignment-jd) ;
00446        }
00447 
00448        
00449 
00450 
00451 
00452 
00453 
00454        rt->part_typ[id] = rt->comp_typ[ii] ;
00455        rt->part_off[id] = cbase ;
00456        rt->part_siz[id] = pointer_size ;
00457        rt->part_rtp[id] = NI_rowtype_find_code( rt->part_typ[id] ) ;
00458 
00459        
00460        
00461 
00462        for( jd=kd=0 ; jd < rt->comp_dim[ii] ; jd++ ){
00463          if( rt->comp_dim[jd] >= 0 ){   
00464            kd++ ;
00465          } else {                      
00466            qt = NI_rowtype_find_code( rt->comp_typ[jd] ) ;
00467            kd += qt->part_num ;
00468          }
00469        }
00470        rt->part_dim[id] = kd ;    
00471 
00472        kd = pointer_alignment ;
00473        if( kd > almax ) almax = kd ;
00474 
00475        id++ ; cbase += pointer_size ;
00476 
00477      } else {      
00478 
00479        qt = NI_rowtype_find_code( rt->comp_typ[ii] ) ;  
00480 
00481        
00482 
00483        if( qt->algn > 1 ){
00484          jd = cbase % qt->algn ;
00485          if( jd > 0 ) cbase += (qt->algn-jd) ;
00486        }
00487 
00488        pb = id ;                    
00489        np = qt->part_num ;                 
00490 
00491        rt->part_typ[id] = qt->part_typ[0] ;  
00492        rt->part_off[id] = cbase ;             
00493        rt->part_dim[id] = -1 ;   
00494        rt->part_rtp[id] = NI_rowtype_find_code( rt->part_typ[id] ) ;
00495 
00496        kd = rt->part_rtp[id]->algn ;                 
00497        if( kd > almax ) almax = kd ;   
00498 
00499        last_size = rt->part_rtp[id]->size ;           
00500        rt->part_siz[id] = last_size ;
00501 
00502        id++ ;  
00503 
00504        
00505 
00506        for( jj=1 ; jj < np ; jj++,id++ ){
00507 
00508          rt->part_typ[id] = qt->part_typ[jj] ;     
00509          rt->part_rtp[id] = NI_rowtype_find_code( rt->part_typ[id] ) ;
00510 
00511          if( qt->part_dim[jj] < 0 ){        
00512 
00513            nn = last_size ;                        
00514            jd = rt->part_off[id-1] ;               
00515            kd = rt->part_rtp[id]->algn ;           
00516            if( kd > almax ) almax = kd ; 
00517 
00518            nn += jd ;  
00519            if( kd > 1 ){                           
00520              jd = nn % kd ;                        
00521              if( jd > 0 ) nn += (kd-jd) ;          
00522            }
00523            rt->part_off[id] = nn ;
00524            rt->part_dim[id] = -1 ;                
00525 
00526            last_size = rt->part_rtp[id]->size ;        
00527            rt->part_siz[id] = last_size ;
00528 
00529          } else {                           
00530 
00531            nn = last_size ;
00532            jd = rt->part_off[id-1] ;
00533            kd = pointer_alignment ;        
00534            if( kd > almax ) almax = kd ;
00535            nn += jd ;
00536            if( kd > 1 ){
00537              jd = nn % kd ;
00538              if( jd > 0 ) nn += (kd-jd) ;
00539            }
00540            rt->part_off[id] = nn ;
00541            last_size = pointer_size ;
00542            rt->part_siz[id] = last_size ;
00543 
00544            
00545 
00546 
00547 
00548            rt->part_dim[id] = pb + qt->part_dim[jj] ;
00549 
00550          }
00551 
00552        } 
00553 
00554        
00555 
00556 
00557        cbase += qt->size ;
00558 
00559      } 
00560 
00561    } 
00562 
00563    
00564 
00565 
00566 
00567 
00568 
00569    rt->algn = almax ;
00570    if( rt->algn > 1 ){
00571      jd = cbase % rt->algn ;
00572      if( jd > 0 ) cbase += (rt->algn-jd) ;
00573    }
00574    rt->size = cbase ;  
00575 
00576 
00577 
00578    
00579 
00580 
00581 
00582 
00583    rt->psiz = 0 ;
00584    if( !ROWTYPE_is_varsize(rt) ){
00585      for( ii=0 ; ii < rt->part_num ; ii++ )
00586        rt->psiz += rt->part_siz[ii] ;
00587    }
00588 
00589    
00590 
00591 
00592 
00593 
00594    rt->code = ROWTYPE_BASE_CODE + rowtype_num ;
00595 
00596 
00597 
00598    if( ROWTYPE_debug ){
00599      fprintf(stderr,"\n") ;
00600      fprintf(stderr,"NI_rowtype_define: '%s' = '%s'\n",tname,tdef) ;
00601      fprintf(stderr,"  code     = %d\n",rt->code) ;
00602      fprintf(stderr,"  size     = %d\n",rt->size) ;
00603      fprintf(stderr,"  psiz     = %d\n",rt->psiz) ;
00604      fprintf(stderr,"  algn     = %d\n",rt->algn) ;
00605      fprintf(stderr,"  flag     = %d\n",rt->flag) ;
00606 
00607      fprintf(stderr,"  comp_num = %d\n",rt->part_num) ;
00608 
00609      fprintf(stderr,"  comp_typ = " ) ;
00610      for( ii=0 ; ii < rt->comp_num ; ii++ ) fprintf(stderr,"%4d ",rt->comp_typ[ii]) ;
00611      fprintf(stderr,"\n") ;
00612 
00613      fprintf(stderr,"  comp_dim = " ) ;
00614      for( ii=0 ; ii < rt->comp_num ; ii++ ) fprintf(stderr,"%4d ",rt->comp_dim[ii]) ;
00615      fprintf(stderr,"\n") ;
00616 
00617      fprintf(stderr,"  part_num = %d\n",rt->part_num) ;
00618 
00619      fprintf(stderr,"  part_typ = " ) ;
00620      for( ii=0 ; ii < rt->part_num ; ii++ ) fprintf(stderr,"%4d ",rt->part_typ[ii]) ;
00621      fprintf(stderr,"\n") ;
00622 
00623      fprintf(stderr,"  part_off = " ) ;
00624      for( ii=0 ; ii < rt->part_num ; ii++ ) fprintf(stderr,"%4d ",rt->part_off[ii]) ;
00625      fprintf(stderr,"\n") ;
00626 
00627      fprintf(stderr,"  part_siz = " ) ;
00628      for( ii=0 ; ii < rt->part_num ; ii++ ) fprintf(stderr,"%4d ",rt->part_siz[ii]) ;
00629      fprintf(stderr,"\n") ;
00630 
00631      fprintf(stderr,"  part_dim = " ) ;
00632      for( ii=0 ; ii < rt->part_num ; ii++ ) fprintf(stderr,"%4d ",rt->part_dim[ii]) ;
00633      fprintf(stderr,"\n") ;
00634    }
00635 
00636    
00637 
00638 
00639    ROWTYPE_register(rt) ;
00640    return rt->code ;
00641 }
00642 
00643 
00644 
00645 
00646 NI_procins * NI_rowtype_procins( NI_rowtype *rt )  
00647 {
00648    NI_procins *npi ;
00649    char *rhs ;
00650 
00651    if( rt == NULL ) return NULL ;
00652 
00653    npi = NI_new_processing_instruction( "ni_do" ) ;
00654    NI_set_attribute( npi , "ni_verb" , "typedef" ) ;
00655 
00656    rhs = NI_malloc(char,strlen(rt->name)+strlen(rt->userdef)+4) ;
00657    sprintf( rhs , "%s %s" , rt->name , rt->userdef ) ;
00658    NI_set_attribute( npi , "ni_object" , rhs ) ;
00659    NI_free( rhs ) ;
00660    return npi ;
00661 }
00662 
00663 
00664 
00665 
00666 
00667 
00668 
00669 
00670 NI_rowtype * NI_rowtype_find_name( char *nn )
00671 {
00672    NI_rowtype *rt ; int ii ;
00673    static int busy=0 ;       
00674 
00675    if( nn == NULL || *nn == '\0' ) return NULL ;
00676    if( rowtype_table == NULL ) setup_basic_types() ;
00677    rt = (NI_rowtype *) findin_Htable(nn,rowtype_table) ;
00678    if( rt != NULL ) return rt ;
00679 
00680    
00681 
00682    for( ii=0 ; ii <= NI_NUM_BASIC_TYPES ; ii++ )
00683      if( strcmp(type_alias[ii],nn) == 0 ) return rowtype_array[ii] ;
00684 
00685    
00686 
00687 
00688    if( busy ) return NULL ;   
00689 
00690    ii = strlen(nn) ;
00691    if( ii < 12 || strncmp(nn,"VECTOR_",7) != 0 || strchr(nn+7,'_') == NULL )
00692      return NULL ;
00693 
00694    { char bt[32] , rt[64] ; int tt , dd ;
00695 
00696      
00697 
00698      for( ii=7 ; ii < 32 && nn[ii] != '\0' && nn[ii] != '_' ; ii++ )
00699        bt[ii-7] = nn[ii] ;
00700      if( nn[ii] != '_' ) return NULL ;   
00701      bt[ii-7] = '\0' ;                   
00702 
00703      
00704 
00705      for( tt=0 ; tt <= NI_NUM_BASIC_TYPES ; tt++ )
00706        if( strcmp(type_name[tt],bt) == 0 ) break ;
00707 
00708      if( tt > NI_NUM_BASIC_TYPES ){
00709        for( tt=0 ; tt <= NI_NUM_BASIC_TYPES ; tt++ )
00710          if( strcmp(type_alias[tt],bt) == 0 ) break ;
00711        if( tt > NI_NUM_BASIC_TYPES ) return NULL ;
00712      }
00713 
00714      
00715 
00716      dd = 0 ; sscanf( nn+ii+1 , "%d" , &dd ) ;
00717      if( dd <= 0 ) return NULL ;
00718 
00719      
00720 
00721      sprintf(rt,"%s[%d]",type_name[tt],dd) ;
00722 
00723      busy = 1 ;                        
00724      tt = NI_rowtype_define( nn , rt ) ;
00725      busy = 0 ;
00726      if( tt >= ROWTYPE_OFFSET ) return rowtype_array[tt-ROWTYPE_BASE_CODE] ;
00727    }
00728 
00729    return NULL ;
00730 }
00731 
00732 
00733 
00734 
00735 NI_rowtype * NI_rowtype_find_code( int nn )
00736 {
00737    if( nn < 0 ) return NULL ;
00738    if( rowtype_table == NULL ) setup_basic_types() ;
00739    if( nn >= ROWTYPE_OFFSET ) nn = nn - ROWTYPE_BASE_CODE ;
00740    if( nn < 0 || nn >= rowtype_num ) return NULL ;
00741    return rowtype_array[nn] ;
00742 }
00743 
00744 
00745 
00746 
00747 
00748 
00749 int NI_rowtype_name_to_code( char *nn )
00750 {
00751    NI_rowtype *rt = NI_rowtype_find_name( nn ) ;
00752    if( rt != NULL ) return rt->code ;
00753    return -1 ;
00754 }
00755 
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 char * NI_rowtype_code_to_name( int nn )
00764 {
00765    NI_rowtype *rt = NI_rowtype_find_code( nn ) ;
00766    if( rt != NULL ) return rt->name ;
00767    return NULL ;
00768 }
00769 
00770 
00771 
00772 
00773 
00774 
00775 
00776 char * NI_rowtype_code_to_alias( int nn )   
00777 {
00778    if( rowtype_table == NULL ) setup_basic_types() ;
00779    if( nn <= NI_NUM_BASIC_TYPES ) return type_alias[nn] ;
00780    return NI_rowtype_code_to_name( nn ) ;
00781 }
00782 
00783 
00784 
00785 
00786 
00787 
00788 
00789 
00790 
00791 
00792 
00793 
00794 int NI_rowtype_name_to_size( char *nn )
00795 {
00796    NI_rowtype *rt = NI_rowtype_find_name( nn ) ;
00797    if( rt != NULL ) return rt->size ;
00798    return -1 ;
00799 }
00800 
00801 
00802 
00803 
00804 
00805 
00806 int NI_rowtype_code_to_size( int dtyp )
00807 {
00808    static int last_dtyp=-1 , last_size=-1 ;         
00809    NI_rowtype *rt ;
00810 
00811    if( rowtype_table == NULL )  setup_basic_types() ;
00812    if( dtyp <  0              ) return -1 ;
00813    if( dtyp <  ROWTYPE_OFFSET ) return type_size[dtyp] ;
00814    if( dtyp == last_dtyp      ) return last_size ;
00815 
00816    rt = NI_rowtype_find_code(dtyp) ;
00817    if( rt != NULL ){
00818      last_dtyp = dtyp; last_size = rt->size; return last_size;
00819    }
00820    return -1 ;  
00821 }
00822 
00823 
00824 
00825 
00826 
00827 
00828 
00829 
00830 int NI_rowtype_vsize( NI_rowtype *rt , void *dpt )
00831 {
00832    int ii,jj , ss ;
00833    char *dat = (char *)dpt ;
00834 
00835    if( rt == NULL              ) return 0;        
00836    if( !ROWTYPE_is_varsize(rt) ) return rt->psiz; 
00837    if( dat == NULL             ) return 0;        
00838 
00839    
00840 
00841 
00842    for( ii=ss=0 ; ii < rt->part_num ; ii++ ){
00843      if( rt->part_typ[ii] == NI_STRING ){      
00844        char *str = *((char **)((dat) + (rt)->part_off[ii])) ;
00845        ss += NI_strlen(str) ;
00846      } else if( rt->part_dim[ii] < 0 ){        
00847        ss += rt->part_siz[ii] ;
00848      } else {                                  
00849        jj = ROWTYPE_part_dimen(rt,dat,ii) ;    
00850        ss += jj * rt->part_rtp[ii]->psiz ;     
00851      }                                         
00852    }
00853 
00854    return ss ;
00855 }
00856 
00857 
00858 
00859 
00860 
00861 
00862 
00863 void NI_val_to_text( NI_rowtype *rt , char *dpt , char *wbuf )
00864 {
00865    int jj = strlen(wbuf) ;
00866 
00867    switch( rt->code ){
00868 
00869      
00870 
00871      default:{
00872        if( rt != NULL ){
00873          int ii ;
00874          for( ii=0 ; ii < rt->part_num ; ii++ )   
00875            NI_val_to_text( rt->part_rtp[ii] , dpt + rt->part_off[ii] , wbuf ) ;
00876        }
00877      }
00878      break ;
00879 
00880      
00881 
00882      case NI_BYTE:{
00883        byte *vpt = (byte *)dpt ;
00884        sprintf(wbuf+jj," %u",(unsigned int)vpt[0]) ;
00885      }
00886      break ;
00887 
00888      case NI_SHORT:{
00889        short *vpt = (short *)dpt ;
00890        sprintf(wbuf+jj," %d",(int)vpt[0]) ;
00891      }
00892      break ;
00893 
00894      case NI_INT:{
00895        int *vpt = (int *)dpt ;
00896        sprintf(wbuf+jj," %d",vpt[0]) ;
00897      }
00898      break ;
00899 
00900      
00901 
00902      case NI_RGB:{
00903        rgb *vpt = (rgb *)dpt ;
00904        sprintf(wbuf+jj,"  %u %u %u",vpt[0].r,vpt[0].g,vpt[0].b) ;
00905      }
00906      break ;
00907 
00908      case NI_RGBA:{
00909        rgba *vpt = (rgba *)dpt ;
00910        sprintf(wbuf+jj,"  %u %u %u %u",
00911                vpt[0].r,vpt[0].g,vpt[0].b,vpt[0].a) ;
00912      }
00913      break ;
00914 
00915      
00916 
00917 
00918      case NI_FLOAT:{
00919        float *vpt = (float *)dpt ;
00920        char fbuf[32] ; int ff ;
00921        sprintf(fbuf,"%12.6g",vpt[0]) ;
00922        for( ff=strlen(fbuf) ; fbuf[ff]==' ' ; ff-- ) fbuf[ff] = '\0' ;
00923        for( ff=0 ; fbuf[ff] == ' ' ; ff++ ) ;
00924        sprintf(wbuf+jj," %s",fbuf+ff) ;
00925      }
00926      break ;
00927 
00928      case NI_DOUBLE:{
00929        double *vpt = (double *)dpt ;
00930        char fbuf[32] ; int ff ;
00931        sprintf(fbuf,"%18.12g",vpt[0]) ;
00932        for( ff=strlen(fbuf) ; fbuf[ff]==' ' ; ff-- ) fbuf[ff] = '\0' ;
00933        for( ff=0 ; fbuf[ff] == ' ' ; ff++ ) ;
00934        sprintf(wbuf+jj," %s",fbuf+ff) ;
00935      }
00936      break ;
00937 
00938      case NI_COMPLEX:{
00939        complex *vpt = (complex *)dpt ;
00940        char fbuf[32],gbuf[32] ; int ff,gg ;
00941        sprintf(fbuf,"%12.6g",vpt[0].r) ;
00942        for( ff=strlen(fbuf) ; fbuf[ff]==' ' ; ff-- ) fbuf[ff] = '\0' ;
00943        for( ff=0 ; fbuf[ff] == ' ' ; ff++ ) ;
00944        sprintf(gbuf,"%12.6g",vpt[0].i) ;
00945        for( gg=strlen(gbuf) ; gbuf[gg]==' ' ; gg-- ) gbuf[gg] = '\0' ;
00946        for( gg=0 ; gbuf[gg] == ' ' ; gg++ ) ;
00947        sprintf(wbuf+jj,"  %s %s",fbuf+ff,gbuf+gg) ;
00948      }
00949      break ;
00950 
00951      case NI_STRING:{                         
00952        char **vpt = (char **)dpt , *str ;
00953        str = quotize_string( *vpt ) ;
00954        sprintf(wbuf+jj," %s",str) ;
00955        NI_free(str) ;
00956      }
00957      break ;
00958 
00959    } 
00960 }
00961 
00962 
00963 
00964 
00965 
00966 
00967 void NI_multival_to_text( NI_rowtype *rt , int nv , char *dpt , char *wbuf )
00968 {
00969    int ii , jj=rt->size ;
00970 
00971    for( ii=0 ; ii < nv ; ii++ )
00972      NI_val_to_text( rt , dpt+ii*jj , wbuf ) ;
00973 }
00974 
00975 
00976 
00977 
00978 
00979 
00980 
00981 
00982 int NI_val_to_binary( NI_rowtype *rt , char *dpt , char *wbuf )
00983 {
00984    int jj=0 ;  
00985 
00986    if( rt->size == rt->psiz ){        
00987 
00988      jj = rt->size ;
00989      memcpy(wbuf,dpt,jj) ;
00990 
00991    } else if( !ROWTYPE_is_varsize(rt) ){  
00992                                   
00993      int ii ;
00994      for( ii=0 ; ii < rt->part_num ; ii++ ){
00995        memcpy(wbuf+jj,dpt+rt->part_off[ii],rt->part_siz[ii]) ;
00996        jj += rt->part_siz[ii] ;
00997      }
00998 
00999    }
01000 
01001    return jj ;
01002 }
01003 
01004 
01005 
01006 
01007 
01008 
01009 
01010 int NI_multival_to_binary( NI_rowtype *rt , int nv , char *dpt , char *wbuf )
01011 {
01012    int jj=0 ;
01013 
01014    if( rt->size == rt->psiz ){         
01015                                        
01016      jj = nv * rt->size ;
01017      memcpy(wbuf,dpt,jj);
01018 
01019    } else if( rt->psiz > 0 ){          
01020                                        
01021      int ii ;
01022      for( ii=0 ; ii < nv ; ii++ )
01023       jj += NI_val_to_binary( rt , dpt+(ii*rt->size) , wbuf+jj ) ;
01024 
01025    }
01026    return jj ;
01027 }
01028 
01029 
01030 
01031 
01032 
01033 int NI_has_String( NI_rowtype *rt )
01034 {
01035    int ii , jj ;
01036 
01037    if( rt == NULL ) return 0 ;
01038 
01039    
01040 
01041    if( ROWTYPE_is_builtin_code(rt->code) ) return (rt->code == NI_STRING) ;
01042 
01043    
01044 
01045    for( ii=0 ; ii < rt->part_num ; ii++ ){
01046      if( ROWTYPE_is_builtin_code(rt->part_rtp[ii]->code) ){ 
01047        if( rt->part_rtp[ii]->code == NI_STRING ) return 1;
01048      } else {                                              
01049        if( NI_has_String( rt->part_rtp[ii] )   ) return 1; 
01050      }
01051    }
01052    return 0 ;
01053 }
01054 
01055 
01056 
01057 
01058 
01059 
01060 int NI_write_rowtype( NI_stream_type *ns , NI_rowtype *rt ,
01061                       int ndat , void *dat , int tmode )
01062 {
01063    void *dpt = dat ;
01064    if( rt == NULL ) return -1 ;
01065    return NI_write_columns( ns , 1 , &(rt->code) , ndat , &dpt , tmode ) ;
01066 }
01067 
01068 
01069 
01070 
01071 
01072 
01073 
01074 
01075 
01076 
01077 
01078 
01079 
01080 
01081 
01082 
01083 
01084 
01085 
01086 
01087 
01088 
01089 int NI_write_columns( NI_stream_type *ns,
01090                       int col_num , int   *col_typ ,
01091                       int col_len , void **col_dpt , int tmode )
01092 {
01093    int ii,jj , row , dim , ntot,nout , col ;
01094    char *ptr , **col_dat=(char **)col_dpt ;
01095    int  nwbuf,bb=0,cc=0;
01096    char *wbuf=NULL ; 
01097    char *bbuf=NULL ; 
01098    char *cbuf=NULL ; 
01099 
01100    NI_rowtype **rt=NULL ;  
01101    int *vsiz=NULL , vsiz_tot=0 ;
01102    int *fsiz=NULL , fsiz_tot=0 ;
01103 
01104 # undef  FREEUP
01105 # define FREEUP do{ NI_free(wbuf); NI_free(bbuf); NI_free(cbuf); \
01106                     NI_free(rt)  ; NI_free(vsiz); NI_free(fsiz); \
01107                 } while(0)
01108 
01109    
01110 
01111    if( col_num <= 0    || col_len <= 0    ) return  0 ;
01112    if( col_typ == NULL || col_dat == NULL ) return -1 ;
01113    if( !NI_stream_writeable(ns)           ) return -1 ;
01114 
01115 #if 0
01116 fprintf(stderr,"NI_write_columns: col_num=%d col_len=%d tmode=%d\n",col_num,col_len,tmode) ;
01117 #endif
01118 
01119    
01120 
01121    if( ns->bad ){                        
01122      jj = NI_stream_goodcheck(ns,666) ;  
01123      if( jj < 1 ) return jj ;            
01124    }
01125 #if 1
01126    jj = NI_stream_writecheck(ns,666) ;
01127    if( jj < 0 ) return jj ;              
01128 #endif
01129 
01130    if( ns->type == NI_STRING_TYPE )  
01131      tmode = NI_TEXT_MODE ;
01132 
01133    
01134 
01135    rt   = NI_malloc(NI_rowtype*, sizeof(NI_rowtype *) * col_num ) ;
01136    vsiz = NI_malloc(int,  sizeof(int)          * col_num ) ;
01137    fsiz = NI_malloc(int,  sizeof(int)          * col_num ) ;
01138    for( col=0 ; col < col_num ; col++ ){
01139 
01140      
01141 
01142      rt[col] = NI_rowtype_find_code( col_typ[col] ) ;
01143 
01144      
01145 
01146      if( rt[col] == NULL || col_dat[col] == NULL ){ FREEUP; return -1; }
01147 
01148      vsiz[col] = ROWTYPE_is_varsize(rt[col]) ;         
01149      fsiz[col] = rt[col]->size ;         
01150      vsiz_tot += vsiz[col] ;
01151      fsiz_tot += fsiz[col] ;
01152 
01153      
01154 
01155      if( tmode != NI_TEXT_MODE && NI_has_String(rt[col]) ) tmode = NI_TEXT_MODE;
01156    }
01157 
01158    
01159 
01160 
01161 
01162    if( col_num == 1 && tmode == NI_BINARY_MODE && fsiz[0] == rt[0]->psiz ){
01163 #if 0
01164 int ct = NI_clock_time() ;
01165 #endif
01166      nout = NI_stream_write( ns , col_dat[0] , fsiz[0]*col_len ) ;
01167 #if 0
01168 ct = NI_clock_time()-ct ;
01169 fprintf(stderr,"NI_write_columns FAST case: %d bytes in %d ms\n",fsiz[0]*col_len,ct) ;
01170 #endif
01171      FREEUP ; return nout ;
01172    }
01173 
01174    
01175 
01176    switch( tmode ){
01177      default:             tmode = NI_TEXT_MODE ; 
01178      case NI_TEXT_MODE:   nwbuf = 6*fsiz_tot ; break ;
01179 
01180      case NI_BASE64_MODE:
01181      case NI_BINARY_MODE: nwbuf =   fsiz_tot ; break ;
01182    }
01183    wbuf = NI_malloc(char, nwbuf+128) ;  
01184 
01185    
01186 
01187    if( tmode == NI_BASE64_MODE ){
01188      bbuf = NI_malloc(char,   nwbuf+128) ; bb = 0 ;  
01189      cbuf = NI_malloc(char, 2*nwbuf+128) ; cc = 0 ;  
01190      load_encode_table() ;
01191    }
01192 
01193    
01194 
01195 
01196 
01197 # undef  ADDOUT
01198 # define ADDOUT                              \
01199   if( nout < 0 ){                            \
01200     fprintf(stderr,"NIML:: write abort!\n"); \
01201     FREEUP ; return -1 ;                     \
01202   } else ntot+=nout
01203 
01204    
01205 
01206 
01207    ntot = 0 ;  
01208 
01209    for( row=0 ; row < col_len ; row++ ){
01210 
01211      
01212 
01213      if( vsiz_tot ){
01214        for( jj=col=0 ; col < col_num ; col++ ){
01215         ptr = col_dat[col] + fsiz[col]*row ;     
01216         jj += NI_rowtype_vsize( rt[col] , ptr ); 
01217        }
01218        if( tmode == NI_TEXT_MODE ) jj *= 6 ;
01219        if( jj > nwbuf ){                     
01220          nwbuf = jj ;
01221          wbuf  = NI_realloc(wbuf, char,nwbuf+128) ;
01222          if( tmode == NI_BASE64_MODE ){          
01223            bbuf = NI_realloc(bbuf, char,  nwbuf+128) ;
01224            cbuf = NI_realloc(cbuf, char,2*nwbuf+128) ;
01225          }
01226        }
01227      }
01228 
01229      
01230 
01231      switch( tmode ){
01232        case NI_TEXT_MODE:    wbuf[0] = '\0'; break; 
01233        case NI_BASE64_MODE:
01234        case NI_BINARY_MODE:  jj = 0 ;        break; 
01235      }
01236 
01237      
01238 
01239      for( col=0 ; col < col_num ; col++ ){
01240       ptr = col_dat[col] + fsiz[col]*row ; 
01241                                            
01242 
01243       
01244 
01245       
01246 
01247 
01248       for( ii=0 ; ii < rt[col]->part_num ; ii++ ){ 
01249 
01250        if( rt[col]->part_dim[ii] < 0 ){             
01251          switch( tmode ){           
01252 
01253            case NI_TEXT_MODE:              
01254              NI_val_to_text( rt[col]->part_rtp[ii],
01255                              ptr+rt[col]->part_off[ii], wbuf ) ;
01256            break ;
01257 
01258            case NI_BASE64_MODE:            
01259            case NI_BINARY_MODE:
01260              jj += NI_val_to_binary( rt[col]->part_rtp[ii],
01261                                      ptr+rt[col]->part_off[ii], wbuf+jj ) ;
01262            break ;
01263          }
01264 
01265        } else {                           
01266 
01267          char **apt = (char **)(ptr+rt[col]->part_off[ii]); 
01268                                                            
01269 
01270          dim = ROWTYPE_part_dimen(rt[col],ptr,ii) ;      
01271          if( dim > 0 && *apt != NULL ){
01272            switch( tmode ){
01273              case NI_TEXT_MODE:
01274                NI_multival_to_text( rt[col]->part_rtp[ii] , dim ,
01275                                     *apt , wbuf ) ;
01276              break ;
01277              case NI_BASE64_MODE:
01278              case NI_BINARY_MODE:
01279                jj += NI_multival_to_binary( rt[col]->part_rtp[ii] , dim ,
01280                                             *apt , wbuf+jj ) ;
01281              break ;
01282            }
01283          }
01284        }
01285 
01286       } 
01287      } 
01288 
01289      
01290 
01291      switch( tmode ){
01292 
01293        case NI_TEXT_MODE:     
01294          strcat(wbuf,"\n") ;
01295          nout = NI_stream_writestring( ns , wbuf ) ;
01296          ADDOUT ;
01297        break ;
01298 
01299        case NI_BINARY_MODE:   
01300          nout = NI_stream_write( ns , wbuf , jj ) ;
01301 #ifdef NIML_DEBUG
01302 if( nout != jj ) NI_dpr("NI_write_columns: col#%d sends %d bytes; nout=%d\n",col,jj,nout) ;
01303 #endif
01304          ADDOUT ;
01305        break ;
01306 
01307        case NI_BASE64_MODE:{  
01308          int nb , nb3 , nb64 , pp,qq ;
01309          byte a,b,c,w,x,y,z ;
01310 
01311          
01312 
01313 
01314 
01315          memcpy(bbuf+bb,wbuf,jj) ;       
01316          nb = jj+bb ;                    
01317          if( nb < 3 ){ bb = nb; break; } 
01318          nb3 = 3*(nb/3) ;                
01319 
01320          
01321          
01322 
01323          for( qq=pp=0 ; pp < nb3 ; ){
01324            a = bbuf[pp++] ; b = bbuf[pp++] ; c = bbuf[pp++] ;
01325            B64_encode3(a,b,c,w,x,y,z) ;
01326            cbuf[qq++] = w ; cbuf[qq++] = x ;
01327            cbuf[qq++] = y ; cbuf[qq++] = z ;
01328            cc += 4; if( cc > 64 ){ cbuf[qq++]=B64_EOL2; cc=0; }
01329          }
01330 
01331          
01332 
01333          nout = NI_stream_write( ns , cbuf , qq ) ;
01334          ADDOUT ;
01335 
01336          
01337 
01338          bb = nb - nb3 ;  
01339          if( bb > 0 ){
01340            bbuf[0] = bbuf[nb3] ;                
01341            if( bb > 1 ) bbuf[1] = bbuf[nb3+1] ; 
01342          }
01343        }
01344        break ;
01345      }
01346 
01347    } 
01348 
01349    
01350 
01351 
01352 
01353    if( tmode == NI_BASE64_MODE ){
01354      if( bb > 0 ){                  
01355        byte w,x,y,z , a=bbuf[0],b=bbuf[1] ;
01356        if( bb == 2 ) B64_encode2(a,b,w,x,y,z) ;
01357        else          B64_encode1(a,w,x,y,z) ;
01358        cbuf[0] = w ; cbuf[1] = x ;
01359        cbuf[2] = y ; cbuf[3] = z ; cbuf[4] = B64_EOL2 ;
01360        nout = NI_stream_write( ns , cbuf , 5 ) ;
01361        ADDOUT ;
01362      } else if( cc > 0 ){           
01363        cbuf[0] = B64_EOL2 ;
01364        nout = NI_stream_write( ns , cbuf , 1 ) ;
01365        ADDOUT ;
01366      }
01367    }
01368 
01369    
01370 
01371    FREEUP ;
01372    return ntot ;
01373 }
01374 
01375 
01376 
01377 
01378 
01379 
01380 
01381 
01382 
01383 
01384 
01385 
01386 
01387 
01388 
01389 
01390 
01391 
01392 
01393 
01394 
01395 
01396 
01397 
01398 
01399 
01400 
01401 
01402 
01403 
01404 
01405 
01406 
01407 
01408 
01409 
01410 
01411 int NI_read_columns( NI_stream_type *ns,
01412                      int col_num, int   *col_typ,
01413                      int col_len, void **col_dpt, int tmode, int flags )
01414 {
01415    int ii,jj , row , dim , nin , col , nn ;
01416    char *ptr , **col_dat=(char **)col_dpt ;
01417 
01418    NI_rowtype **rt=NULL ;  
01419    int *vsiz=NULL , vsiz_tot=0 ;
01420    int *fsiz=NULL , fsiz_tot=0 ;
01421 
01422    int (*ReadFun)( NI_stream_type *, NI_rowtype *, void *, int ) ;
01423    int ltend = (flags & NI_LTEND_MASK) != 0 ;
01424    int swap  = (flags & NI_SWAP_MASK)  != 0 ;
01425    int ReadFlag ;
01426    int open_ended = (col_len==0) , row_top ;  
01427 
01428 # undef  FREEUP
01429 # define FREEUP do{ NI_free(rt); NI_free(vsiz); NI_free(fsiz); } while(0)
01430 
01431    
01432 
01433    if( col_num <= 0    || col_len <  0    ) return  0 ;
01434    if( col_typ == NULL || col_dat == NULL ) return -1 ;
01435    if( !NI_stream_readable(ns)            ) return -1 ;
01436 
01437 #ifdef NIML_DEBUG
01438 NI_dpr("ENTER NI_read_columns\n") ;
01439 #endif
01440 
01441    
01442 
01443    if( ns->bad ){                        
01444      jj = NI_stream_goodcheck(ns,666) ;  
01445      if( jj < 1 ) return jj ;            
01446    }
01447    jj = NI_stream_hasinput(ns,666) ;     
01448    if( jj < 0 ) return jj ;              
01449 
01450    
01451 
01452    rt   = NI_malloc(NI_rowtype*,  sizeof(NI_rowtype *) * col_num ) ;
01453    vsiz = NI_malloc(int,  sizeof(int)          * col_num ) ;
01454    fsiz = NI_malloc(int,  sizeof(int)          * col_num ) ;
01455    if( open_ended ) col_len = 1 ;
01456    for( col=0 ; col < col_num ; col++ ){
01457 
01458      rt[col] = NI_rowtype_find_code( col_typ[col] ) ;
01459      if( rt[col] == NULL ){ FREEUP; return -1; }
01460      if( tmode != NI_TEXT_MODE && NI_has_String(rt[col]) ){ FREEUP; return -1; }
01461 
01462      vsiz[col] = ROWTYPE_is_varsize(rt[col]) ;     
01463      fsiz[col] = rt[col]->size ;      
01464      vsiz_tot += vsiz[col] ;
01465      fsiz_tot += fsiz[col] ;
01466 
01467      
01468 
01469      if( col_dat[col] == NULL ){
01470        col_dat[col] = NI_malloc(char,  fsiz[col]*col_len ) ; 
01471      } else {
01472        if( open_ended ){ FREEUP; return -1; }
01473        memset( col_dat[col], 0 , fsiz[col]*col_len ) ; 
01474      }
01475    }
01476 
01477    
01478 
01479 
01480 
01481    if( col_num == 1              &&
01482        fsiz[0] == rt[0]->psiz    &&    
01483        tmode   == NI_BINARY_MODE &&
01484        !open_ended                 ){
01485 
01486      nin = NI_stream_readbuf( ns , col_dat[0] , fsiz[0]*col_len ) ;
01487      if( nin < fsiz[0] ){ FREEUP; return (nin >= 0) ? 0 : -1 ; }  
01488      nin = nin / fsiz[0] ;  
01489      goto ReadFinality ;    
01490    }
01491 
01492    
01493 
01494    if( col_num == 1              &&
01495        fsiz[0] == rt[0]->psiz    &&    
01496        tmode   == NI_BASE64_MODE &&
01497        !open_ended                 ){
01498 
01499      nin = NI_stream_readbuf64( ns , col_dat[0] , fsiz[0]*col_len ) ;
01500      if( nin < fsiz[0] ){ FREEUP; return (nin >= 0) ? 0 : -1 ; }  
01501      nin = nin / fsiz[0] ;  
01502      goto ReadFinality ;    
01503    }
01504 
01505    
01506 
01507    switch( tmode ){
01508      case NI_TEXT_MODE:   ReadFun = NI_text_to_val  ; ReadFlag = ltend; break;
01509      case NI_BINARY_MODE: ReadFun = NI_binary_to_val; ReadFlag = swap ; break;
01510      case NI_BASE64_MODE: ReadFun = NI_base64_to_val; ReadFlag = swap ; break;
01511      default:
01512        fprintf(stderr,"\n** NI_read_columns: unknown input tmode=%d\n",tmode);
01513        FREEUP ; return -1 ;
01514    }
01515 
01516    
01517 
01518    row_top = (open_ended) ? 1999999999 : col_len ; 
01519 
01520    for( row=0 ; row < row_top ; row++ ){                  
01521                                                           
01522 
01523 #ifdef NIML_DEBUG
01524 NI_dpr(" Starting row #%d\n",row) ;
01525 #endif
01526 
01527      
01528 
01529      if( open_ended && row >= col_len ){
01530 #ifdef NIML_DEBUG
01531 NI_dpr("  Extending column lengths!\n") ;
01532 #endif
01533        jj = (int)(1.2*col_len+32) ;
01534        for( col=0 ; col < col_num ; col++ ){
01535          col_dat[col] = NI_realloc( col_dat[col] , char, fsiz[col]*jj ) ;
01536          memset( col_dat[col]+fsiz[col]*col_len, 0 , fsiz[col]*(jj-col_len) ) ;
01537        }
01538        col_len = jj ;
01539      }
01540 
01541      
01542 
01543      for( col=0 ; col < col_num ; col++ ){
01544        ptr = col_dat[col] + fsiz[col]*row ;         
01545        nn  = ReadFun( ns, rt[col], ptr, ReadFlag ) ; 
01546        if( !nn ) break ;
01547      }
01548      if( !nn ) break ;                             
01549    }
01550 
01551    if( row == 0 ){                                
01552      if( open_ended ){
01553        for( col=0 ; col < col_num ; col++ ) NI_free(col_dat[col]) ;
01554      }
01555      FREEUP; return -1;
01556    }
01557 
01558    nin = row ;                                   
01559 
01560    if( open_ended && nin < col_len ){                   
01561      for( col=0 ; col < col_num ; col++ )
01562        col_dat[col] = NI_realloc( col_dat[col] , char, fsiz[col]*nin ) ;
01563    }
01564 
01565    
01566 
01567 ReadFinality:
01568 
01569    if( tmode != NI_TEXT_MODE && swap ){
01570      for( col=0 ; col < col_num ; col++ )
01571        NI_swap_column( rt[col] , nin , col_dat[col] ) ;
01572    }
01573 
01574 #ifdef NIML_DEBUG
01575 NI_dpr("Leaving NI_read_columns\n") ;
01576 #endif
01577 
01578    FREEUP ; return nin ;
01579 }
01580 
01581 
01582 
01583 
01584 
01585 
01586 
01587 
01588 
01589 
01590 
01591 int NI_binary_to_val( NI_stream_type *ns, NI_rowtype *rt, void *dpt, int swap )
01592 {
01593    int nn , jj ;
01594 
01595    if( rt->code == NI_STRING ) return 0 ;            
01596 
01597    if( rt->size == rt->psiz ){        
01598                                
01599 
01600      jj = NI_stream_readbuf( ns , (char *)dpt , rt->size ) ;
01601      return (jj == rt->size) ;
01602 
01603    } else {                                              
01604 
01605      char *dat = (char *)dpt , **aaa = NULL ;
01606      int ii                  ,  naaa = 0 , iaaa = 0 ;
01607 
01608      if( ROWTYPE_is_varsize(rt) ){         
01609        for( naaa=ii=0 ; ii < rt->part_num ; ii++ )
01610          if( rt->part_dim[ii] >= 0 ) naaa++ ;    
01611        if( naaa > 0 )
01612          aaa = NI_malloc(char*, sizeof(char *)*naaa) ;  
01613      }                                    
01614 
01615      
01616 
01617 
01618      for( nn=1,ii=0 ; ii < rt->part_num ; ii++ ){
01619 
01620        if( rt->part_dim[ii] < 0 ){            
01621 
01622          nn = NI_binary_to_val( ns, rt->part_rtp[ii], dat+rt->part_off[ii], 0 );
01623 
01624        } else {                                    
01625 
01626          char **apt = (char **)(dat+rt->part_off[ii]); 
01627                                                  
01628          int dim = ROWTYPE_part_dimen(rt,dat,ii) ;  
01629          int siz = rt->part_rtp[ii]->size ;          
01630 
01631          if( swap ) NI_swap4( 1 , &dim ) ;   
01632                                             
01633 
01634          if( dim > 0 ){                         
01635            *apt = NI_malloc(char,  siz * dim );            
01636 
01637            if( siz != rt->part_rtp[ii]->psiz ){     
01638             for( jj=0 ; jj < dim ; jj++ ){       
01639               nn = NI_binary_to_val( ns, rt->part_rtp[ii],
01640                                      *apt + siz * jj , 0  ) ;
01641               if( !nn ) break ;                              
01642             }
01643 
01644            } else {              
01645              jj = NI_stream_readbuf( ns , *apt , siz*dim ) ;
01646              nn = ( jj == siz*dim ) ;
01647            }
01648 
01649          } else {
01650            *apt = NULL ;                    
01651          }
01652          aaa[iaaa++] = *apt ;              
01653                                           
01654        }
01655 
01656        if( !nn ) break ;                            
01657      } 
01658 
01659      
01660 
01661      if( !nn ){
01662        for( ii=0 ; ii < iaaa ; ii++ ) NI_free( aaa[ii] ) ;
01663      }
01664      NI_free( aaa ) ;  
01665    }
01666 
01667    return nn ;
01668 }
01669 
01670 
01671 
01672 
01673 
01674 
01675 
01676 
01677 
01678 
01679 
01680 int NI_base64_to_val( NI_stream_type *ns, NI_rowtype *rt, void *dpt, int swap )
01681 {
01682    int nn , jj ;
01683 
01684    if( rt->code == NI_STRING ) return 0 ;            
01685 
01686    if( rt->size == rt->psiz ){        
01687                                
01688 
01689      jj = NI_stream_readbuf64( ns , (char *)dpt , rt->size ) ;
01690      return (jj == rt->size) ;
01691 
01692    } else {                                              
01693 
01694      char *dat = (char *)dpt , **aaa = NULL ;
01695      int ii                  ,  naaa = 0 , iaaa = 0 ;
01696 
01697      if( ROWTYPE_is_varsize(rt) ){         
01698        for( naaa=ii=0 ; ii < rt->part_num ; ii++ )
01699          if( rt->part_dim[ii] >= 0 ) naaa++ ;    
01700        if( naaa > 0 )
01701          aaa = NI_malloc(char*, sizeof(char *)*naaa) ;  
01702      }                                    
01703 
01704      
01705 
01706 
01707      for( nn=1,ii=0 ; ii < rt->part_num ; ii++ ){
01708 
01709        if( rt->part_dim[ii] < 0 ){            
01710 
01711          nn = NI_base64_to_val( ns, rt->part_rtp[ii], dat+rt->part_off[ii], 0 );
01712 
01713        } else {                                    
01714 
01715          char **apt = (char **)(dat+rt->part_off[ii]); 
01716                                                  
01717          int dim = ROWTYPE_part_dimen(rt,dat,ii) ;  
01718          int siz = rt->part_rtp[ii]->size ;          
01719 
01720          if( swap ) NI_swap4( 1 , &dim ) ;   
01721                                             
01722 
01723          if( dim > 0 ){                         
01724            *apt = NI_malloc(char,  siz * dim );            
01725 
01726            if( siz != rt->part_rtp[ii]->psiz ){     
01727             for( jj=0 ; jj < dim ; jj++ ){       
01728               nn = NI_base64_to_val( ns, rt->part_rtp[ii],
01729                                      *apt + siz * jj , 0  ) ;
01730               if( !nn ) break ;                              
01731             }
01732 
01733            } else {              
01734              jj = NI_stream_readbuf64( ns , *apt , siz*dim ) ;
01735              nn = ( jj == siz*dim ) ;
01736            }
01737 
01738          } else {
01739            *apt = NULL ;                    
01740          }
01741          aaa[iaaa++] = *apt ;              
01742                                           
01743        }
01744 
01745        if( !nn ) break ;                            
01746      } 
01747 
01748      
01749 
01750      if( !nn ){
01751        for( ii=0 ; ii < iaaa ; ii++ ) NI_free( aaa[ii] ) ;
01752      }
01753      NI_free( aaa ) ;  
01754    }
01755 
01756    return nn ;
01757 }
01758 
01759 
01760 
01761 
01762 
01763 
01764 
01765 
01766 
01767 int NI_text_to_val( NI_stream_type *ns, NI_rowtype *rt, void *dpt, int ltend )
01768 {
01769    int nn ;
01770 
01771    switch( rt->code ){
01772 
01773      
01774 
01775      default:{
01776        char *dat = (char *)dpt , **aaa = NULL ;
01777        int ii , jj ,              naaa = 0 , iaaa = 0 ;
01778 
01779        if( ROWTYPE_is_varsize(rt) ){         
01780          for( naaa=ii=0 ; ii < rt->part_num ; ii++ )
01781            if( rt->part_dim[ii] >= 0 ) naaa++ ;    
01782          if( naaa > 0 )
01783            aaa = NI_malloc(char*, sizeof(char *)*naaa) ;  
01784        }                                    
01785 
01786        
01787 
01788        for( nn=1,ii=0 ; ii < rt->part_num ; ii++ ){
01789 
01790          if( rt->part_dim[ii] < 0 ){                 
01791 
01792            nn = NI_text_to_val( ns, rt->part_rtp[ii],
01793                                 dat+rt->part_off[ii], ltend );
01794 
01795          } else {                                         
01796 
01797            char **apt = (char **)(dat+rt->part_off[ii]); 
01798                                                    
01799            int dim = ROWTYPE_part_dimen(rt,dat,ii) ;  
01800            int siz = rt->part_rtp[ii]->size ;   
01801            if( dim > 0 ){
01802              *apt = NI_malloc(char, siz * dim );                  
01803              for( jj=0 ; jj < dim ; jj++ ){        
01804                nn = NI_text_to_val( ns, rt->part_rtp[ii],
01805                                     *apt + siz * jj , ltend ) ;
01806                if( !nn ) break ;
01807              }
01808            } else {
01809              *apt = NULL ;                    
01810            }
01811            aaa[iaaa++] = *apt ;              
01812 
01813          }
01814 
01815          if( !nn ) break ;                            
01816        } 
01817 
01818        
01819 
01820        if( !nn ){
01821          for( ii=0 ; ii < iaaa ; ii++ ) NI_free( aaa[ii] ) ;
01822          NI_free( aaa ) ;
01823          return 0 ;
01824        }
01825        NI_free( aaa ) ;  
01826      }
01827      break ;
01828 
01829      
01830 
01831      case NI_STRING:{
01832         char *val=NULL ;
01833         char **vpt = (char **) dpt ;
01834         nn = NI_decode_one_string( ns , &val , ltend ) ;
01835         if( !nn || val == NULL ) return 0 ;
01836         unescape_inplace(val) ;
01837         *vpt = val ;
01838      }
01839      break ;
01840 
01841      
01842 
01843      case NI_BYTE:{
01844         double val ;
01845         byte *vpt = (byte *) dpt ;
01846         nn = NI_decode_one_double( ns , &val , ltend ) ;
01847         if( !nn ) return 0 ;
01848         *vpt = (byte) val ;
01849      }
01850      break ;
01851 
01852      case NI_SHORT:{
01853         double val ;
01854         short *vpt = (short *) dpt ;
01855         nn = NI_decode_one_double( ns , &val , ltend ) ;
01856         if( !nn ) return 0 ;
01857         *vpt = (short) val ;
01858      }
01859      break ;
01860 
01861      case NI_INT:{
01862         double val ;
01863         int *vpt = (int *) dpt ;
01864         nn = NI_decode_one_double( ns , &val , ltend ) ;
01865         if( !nn ) return 0 ;
01866         *vpt = (int) val ;
01867      }
01868      break ;
01869 
01870      case NI_FLOAT:{
01871         double val ;
01872         float *vpt = (float *) dpt ;
01873         nn = NI_decode_one_double( ns , &val , ltend ) ;
01874         if( !nn ) return 0 ;
01875         *vpt = (float) val ;
01876      }
01877      break ;
01878 
01879      case NI_DOUBLE:{
01880         double val ;
01881         double *vpt = (double *) dpt ;
01882         nn = NI_decode_one_double( ns , &val , ltend ) ;
01883         if( !nn ) return 0 ;
01884         *vpt = (double) val ;
01885      }
01886      break ;
01887 
01888      case NI_COMPLEX:{
01889         double v1,v2 ;
01890         complex *vpt = (complex *) dpt ;
01891         nn = NI_decode_one_double( ns , &v1 , ltend ) ;
01892         if( !nn ) return 0 ;
01893         nn = NI_decode_one_double( ns , &v2 , ltend ) ;
01894         if( !nn ) return 0 ;
01895         vpt->r = (float) v1 ;
01896         vpt->i = (float) v2 ;
01897      }
01898      break ;
01899 
01900      case NI_RGB:{
01901         double v1,v2,v3 ;
01902         rgb *vpt = (rgb *) dpt ;
01903         nn = NI_decode_one_double( ns , &v1 , ltend ) ;
01904         if( !nn ) return 0 ;
01905         nn = NI_decode_one_double( ns , &v2 , ltend ) ;
01906         if( !nn ) return 0 ;
01907         nn = NI_decode_one_double( ns , &v3 , ltend ) ;
01908         if( !nn ) return 0 ;
01909         vpt->r = (byte) v1 ;
01910         vpt->g = (byte) v2 ;
01911         vpt->b = (byte) v3 ;
01912      }
01913      break ;
01914 
01915      case NI_RGBA:{
01916         double v1,v2,v3,v4 ;
01917         rgba *vpt = (rgba *) dpt ;
01918         nn = NI_decode_one_double( ns , &v1 , ltend ) ;
01919         if( !nn ) return 0 ;
01920         nn = NI_decode_one_double( ns , &v2 , ltend ) ;
01921         if( !nn ) return 0 ;
01922         nn = NI_decode_one_double( ns , &v3 , ltend ) ;
01923         if( !nn ) return 0 ;
01924         nn = NI_decode_one_double( ns , &v4 , ltend ) ;
01925         if( !nn ) return 0 ;
01926         vpt->r = (byte) v1 ;
01927         vpt->g = (byte) v2 ;
01928         vpt->b = (byte) v3 ;
01929         vpt->a = (byte) v4 ;
01930      }
01931      break ;
01932 
01933    } 
01934 
01935    return 1 ;  
01936 }
01937 
01938 
01939 
01940 
01941 
01942 void NI_swap_column( NI_rowtype *rt , int nrow , char *dat )
01943 {
01944    if( rt == NULL || nrow <= 0 || dat == NULL ) return ;  
01945 
01946    switch( rt->code ){
01947 
01948      case NI_RGB:
01949      case NI_RGBA:
01950      case NI_STRING:
01951      case NI_BYTE:    return ;   
01952 
01953      
01954 
01955      case NI_SHORT:
01956        NI_swap2( nrow , dat ) ;
01957      return ;
01958 
01959      case NI_INT:
01960      case NI_FLOAT:
01961        NI_swap4( nrow , dat ) ;
01962      return ;
01963 
01964      case NI_DOUBLE:
01965        NI_swap8( nrow , dat ) ;
01966      return ;
01967 
01968      case NI_COMPLEX:
01969        NI_swap4( 2*nrow , dat ) ;
01970      return ;
01971 
01972      
01973 
01974      default:{
01975        int ii , row , fsiz = rt->size ;
01976        char *ptr ;
01977 
01978        for( row=0 ; row < nrow ; row++ ){
01979          ptr = dat + fsiz*row ;     
01980 
01981          
01982 
01983          for( ii=0 ; ii < rt->part_num ; ii++ ){
01984 
01985            if( rt->part_dim[ii] < 0 ){                     
01986 
01987              NI_swap_column( rt->part_rtp[ii] , 1 , ptr+rt->part_off[ii] ) ;
01988 
01989            } else {                                         
01990 
01991              char **apt = (char **)(ptr+rt->part_off[ii]); 
01992                                                           
01993              int dim = ROWTYPE_part_dimen(rt,dat,ii) ;  
01994              NI_swap_column( rt->part_rtp[ii] , dim , *apt ) ;
01995 
01996            }
01997          } 
01998        } 
01999      }
02000      return ;
02001    }
02002 }
02003 
02004 
02005 
02006 
02007 
02008 
02009 
02010 void NI_free_column( NI_rowtype *rt , int col_len , void *cpt )
02011 {
02012    char *dat=(char *)cpt , *ptr ;
02013    int ii , jj ;
02014 
02015    if( rt == NULL || dat == NULL || col_len < 1 ) return ; 
02016 
02017    
02018 
02019    if( ROWTYPE_is_varsize(rt) ){
02020      for( ii=0 ; ii < col_len ; ii++ ){            
02021        ptr = dat + rt->size * ii ;            
02022        for( jj=0 ; jj < rt->part_num ; jj++ ){       
02023          if( rt->part_typ[jj] == NI_STRING ||
02024              rt->part_dim[jj] >= 0           ){
02025            char **apt = (char **)(ptr+rt->part_off[jj]) ;
02026            NI_free(*apt) ; *apt = NULL ;
02027          }
02028        }
02029      }
02030    }
02031 
02032    
02033 
02034    NI_free(cpt) ; return ;
02035 }
02036 
02037 
02038 
02039 
02040 
02041 
02042 void * NI_copy_column( NI_rowtype *rt , int col_len , void *cpt )
02043 {
02044    char *dat=(char *)cpt , *ndat , *nptr , *qpt ;
02045    int ii , jj , kk ;
02046 
02047    if( rt == NULL || dat == NULL || col_len < 1 ) return NULL ;
02048 
02049    
02050 
02051    ndat = NI_malloc(char,  rt->size * col_len ) ;  
02052    memcpy( ndat , dat , rt->size * col_len ) ;     
02053 
02054    
02055 
02056 
02057 
02058    if( ROWTYPE_is_varsize(rt) ){
02059      for( ii=0 ; ii < col_len ; ii++ ){                 
02060        nptr = ndat + rt->size * ii ;                   
02061        for( jj=0 ; jj < rt->part_num ; jj++ ){            
02062 
02063          if( rt->part_typ[jj] == NI_STRING ){               
02064            char **apt = (char **)(nptr+rt->part_off[jj]) ;   
02065            qpt = NI_strdup(*apt) ; *apt = qpt ;
02066          } else if( rt->part_dim[jj] >= 0 ){
02067            char **apt = (char **)(nptr+rt->part_off[jj]) ;   
02068            if( *apt != NULL ){
02069              kk  = ROWTYPE_part_dimen(rt,nptr,jj) * rt->part_rtp[jj]->size ;
02070              qpt = NI_malloc(char, kk) ; memcpy(qpt,*apt,kk) ; *apt = qpt ;
02071            }
02072          }
02073        }
02074      }
02075    }
02076 
02077    return ndat ;
02078 }
02079 
02080 
02081 
02082 
02083 
02084 
02085 
02086 int NI_size_column( NI_rowtype *rt , int col_len , void *cpt )
02087 {
02088    char *dat = (char *)cpt ;
02089    int ii , ndat ;
02090 
02091    if( rt == NULL || col_len <= 0 )
02092      return 0;                                    
02093    if( !ROWTYPE_is_varsize(rt) || dat == NULL )
02094      return (col_len*rt->psiz);                   
02095 
02096    
02097 
02098    ndat = 0 ;
02099    for( ii=0 ; ii < col_len ; ii++ )
02100      ndat += NI_rowtype_vsize( rt , dat + ii*rt->size ) ;
02101 
02102    return ndat ;
02103 }