00001 #include "niml_private.h"
00002 
00003 
00004 
00005 
00006 
00007 static int scan_for_angles( NI_stream_type *, int ) ;
00008 
00009 #define clear_buffer(ns) ( (ns)->nbuf = (ns)->npos = 0 )
00010 
00011 
00012 
00013 
00014 
00015 static int header_stuff_is_group( header_stuff *hs )  
00016 {
00017    char *atr ;
00018    if( hs == NULL ) return 0 ;
00019    if( strcmp(hs->name,"ni_group") == 0 ) return 1 ;
00020    atr = get_header_attribute( hs , "ni_form" ) ;
00021    if( atr != NULL && strcmp(atr,"ni_group") == 0 ) return 1 ;
00022    return 0 ;
00023 }
00024 
00025 
00026 
00027 
00028 
00029 static int header_stuff_is_procins( header_stuff *hs )
00030 {
00031    if( hs == NULL ) return 0 ;
00032    if( hs->name != NULL && hs->name[0] == '?' ) return 1 ;
00033    return 0 ;
00034 }
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 int NI_write_procins( NI_stream_type *ns , char *str )
00046 {
00047    char *buf ; int jj ;
00048 
00049    
00050 
00051    if( !NI_stream_writeable(ns)             ) return -1 ;  
00052    if( str == NULL || !IS_STRING_CHAR(*str) ) return -1 ;
00053 
00054    
00055 
00056    if( ns->bad ){                       
00057      jj = NI_stream_goodcheck(ns,666) ; 
00058      if( jj < 1 ) return jj ;           
00059    } else {                             
00060      jj = NI_stream_writecheck(ns,666) ;
00061      if( jj < 0 ) return jj ;
00062    }
00063 
00064    
00065 
00066    buf = (char *)malloc(strlen(str)+16) ;
00067    sprintf( buf , "<?%s ?>\n" , str ) ;
00068    jj = NI_stream_writestring( ns , buf ) ;
00069 
00070    free((void *)buf) ; return jj ;
00071 }
00072 
00073 
00074 
00075 
00076 static int read_header_only = 0 ;
00077 void NI_read_header_only( int r ){ read_header_only=r ; } 
00078 
00079 static int skip_procins = 0 ;
00080 void NI_skip_procins( int r ){ skip_procins = r ; }       
00081 
00082 
00083 
00084 
00085 
00086 void * NI_read_element_header( NI_stream_type *ns , int msec )
00087 {
00088    void *nini ;
00089    read_header_only = 1 ;
00090    nini = NI_read_element( ns , msec ) ;
00091    read_header_only = 0 ;
00092    return nini ;
00093 }
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 void * NI_read_element( NI_stream_type *ns , int msec )
00127 {
00128    int ii,nn,nhs , num_restart ;
00129    char *cstart , *cstop ;
00130    header_stuff *hs ;
00131    int start_time=NI_clock_time() , mleft ;
00132 
00133    if( ns == NULL || ns->bad == MARKED_FOR_DEATH || ns->buf == NULL )
00134      return NULL ;  
00135 
00136 #ifdef NIML_DEBUG
00137 NI_dpr("ENTER NI_read_element\n") ;
00138 #endif
00139 
00140    if( msec < 0 ) msec = 999999999 ;  
00141 
00142    
00143 
00144 
00145    if( ns->bad ){
00146      nn = NI_stream_goodcheck( ns , msec ) ;
00147      if( nn < 1 ) return NULL ;              
00148    }
00149 
00150    
00151 
00152    num_restart = 0 ;
00153 HeadRestart:                            
00154    num_restart++ ;
00155    mleft = msec - (NI_clock_time()-start_time) ;      
00156    if( num_restart > 1 && mleft <= 0 ) return NULL ;  
00157 
00158 #ifdef NIML_DEBUG
00159 NI_dpr("NI_read_element: HeadRestart scan_for_angles; num_restart=%d\n" ,
00160                num_restart ) ;
00161 #endif
00162 
00163    nn = scan_for_angles( ns , 0 ) ;     
00164 
00165    
00166 
00167    if( nn < 0 ){
00168      if( NI_stream_readcheck(ns,0) < 0 ) return NULL ;   
00169      NI_sleep(2); goto HeadRestart;                      
00170    }
00171 
00172 #ifdef NIML_DEBUG
00173 NI_dpr("NI_read_element: found '<'\n") ;
00174 #endif
00175 
00176    
00177 
00178    
00179 
00180 
00181    if( nn - ns->npos <= 2 || ns->buf[ns->npos+1] == '/' ){
00182       ns->npos = nn; NI_reset_buffer(ns); 
00183 #ifdef NIML_DEBUG
00184 NI_dpr("NI_read_element: illegal header found? skipping\n") ;
00185 #endif
00186       goto HeadRestart ;
00187    }
00188 
00189    
00190 
00191 #ifdef NIML_DEBUG
00192 NI_dpr("NI_read_element: parsing putative header\n") ;
00193 #endif
00194 
00195    hs = parse_header_stuff( nn - ns->npos , ns->buf + ns->npos , &nhs ) ;
00196 
00197    if( hs == NULL ){  
00198      fprintf(stderr,"NI_read_element: bad element header found!\n") ;
00199      ns->npos = nn; NI_reset_buffer(ns); 
00200      goto HeadRestart ;
00201    }
00202 
00203    
00204 
00205 
00206 
00207 
00208    ns->npos = nn ;
00209 
00210 #ifdef NIML_DEBUG
00211 NI_dpr("NI_read_element: header parsed successfully\n") ;
00212 #endif
00213 
00214    
00215 
00216    if( header_stuff_is_procins(hs) ){       
00217 
00218      NI_procins *npi ;
00219 
00220      if( strcmp(hs->name,"?ni_do") == 0 ){  
00221        NI_element *nel ;
00222        nel = make_empty_data_element( hs ) ;         
00223        destroy_header_stuff( hs ) ;
00224        NI_do( ns , nel ) ;                        
00225        NI_free_element( nel ) ;                        
00226        if( ns->bad == MARKED_FOR_DEATH || ns->buf == NULL ) return NULL ;
00227        num_restart = 0 ; goto HeadRestart ;
00228      }
00229 
00230      
00231 
00232      if( skip_procins ){
00233        destroy_header_stuff( hs ) ; num_restart = 0 ; goto HeadRestart ;
00234      }
00235 
00236      
00237 
00238      npi       = NI_malloc(NI_procins,sizeof(NI_procins)) ;
00239      npi->type = NI_PROCINS_TYPE ;
00240      npi->name = NI_strdup( hs->name + 1 ) ; 
00241 
00242      npi->attr_num = hs->nattr ;
00243      if( npi->attr_num > 0 ){
00244        npi->attr_lhs = hs->lhs ; hs->lhs = NULL ;
00245        npi->attr_rhs = hs->rhs ; hs->rhs = NULL ;
00246      } else {
00247        npi->attr_lhs = npi->attr_rhs = NULL ;
00248      }
00249 
00250      destroy_header_stuff( hs ) ;
00251 
00252      return npi ;
00253 
00254    } 
00255 
00256    else if( header_stuff_is_group(hs) ){           
00257 
00258       NI_group *ngr ;
00259       void *nini ;
00260       int   empty=hs->empty ;
00261 
00262       read_header_only = 0 ;         
00263 
00264       start_time = NI_clock_time() ; 
00265       msec       = 9999 ;            
00266 
00267       ngr = make_empty_group_element( hs ) ;  
00268       destroy_header_stuff( hs ) ;
00269       if( empty ) return ngr ;  
00270 
00271       
00272 
00273       num_restart = 0 ;
00274       while(1){           
00275 
00276 #ifdef NIML_DEBUG
00277 NI_dpr("NI_read_element: ni_group scan_for_angles; num_restart=%d\n",
00278                num_restart ) ;
00279 #endif
00280 
00281          nn = scan_for_angles( ns , 10 ) ;  
00282 
00283          mleft = msec - (NI_clock_time()-start_time) ;
00284          if( mleft < 0 ) mleft = 0 ;
00285 
00286          if( nn <= 0 ){  
00287            if( NI_stream_readcheck(ns,0) < 0 ) break ;  
00288            if( num_restart > 1 && mleft == 0 ) break ;  
00289            num_restart++ ;
00290            continue ;        
00291          }
00292 
00293          
00294 
00295          if( ns->buf[ns->npos+1] == '/' ){  
00296            ns->npos = nn ;                 
00297            break ;
00298          }
00299 
00300          
00301 
00302          nini = NI_read_element( ns , mleft ) ;   
00303          if( nini != NULL ){
00304             NI_add_to_group( ngr , nini ) ;  
00305             num_restart = 0 ;
00306             start_time = NI_clock_time() ;   
00307          } else {                            
00308             if( NI_stream_readcheck(ns,0) < 0 ) break ;    
00309             mleft = msec - (NI_clock_time()-start_time) ;
00310             if( num_restart > 1 && mleft <= 0 ) break ;    
00311             num_restart++ ;
00312          }
00313       }
00314 
00315       
00316 
00317       return ngr ;
00318 
00319    } 
00320 
00321    else {      
00322 
00323       NI_element *nel ;
00324       int form, swap, nbrow , row,col ;
00325 
00326       nel = make_empty_data_element( hs ) ;
00327       destroy_header_stuff( hs ) ;
00328 
00329       
00330 
00331       if( nel           == NULL ||     
00332           nel->vec_rank == 0    ||     
00333           nel->vec_num  == 0    ||     
00334           nel->vec_typ  == NULL ||     
00335           nel->vec      == NULL ||
00336           nel->name[0]  == '!'  ||     
00337           read_header_only        ){
00338 
00339 #ifdef NIML_DEBUG
00340 NI_dpr("NI_read_element: returning empty element\n") ;
00341 #endif
00342 
00343         
00344 
00345         if( nel != NULL && strcmp(nel->name,"ni_do") == 0 ){
00346           NI_do( ns , nel ) ;
00347           NI_free_element( nel ) ;
00348           if( ns->bad == MARKED_FOR_DEATH || ns->buf == NULL ) return NULL ;
00349           num_restart = 0 ; goto HeadRestart ;
00350         }
00351 
00352         if( read_header_only && nel->vec != NULL ){
00353           for( ii=0 ; ii < nel->vec_num ; ii++ ) NI_free(nel->vec[ii]) ;
00354           NI_free(nel->vec) ; nel->vec = NULL ;
00355         }
00356 
00357         return nel ;   
00358       }
00359 
00360       
00361 
00362       
00363 
00364       form = NI_TEXT_MODE ; 
00365       swap = 0 ;            
00366 
00367       ii = string_index( "ni_form" , nel->attr_num , nel->attr_lhs ) ;
00368 
00369       if( ii >= 0 && nel->attr_rhs[ii] != NULL ){ 
00370 
00371          
00372 
00373          if( strstr(nel->attr_rhs[ii],"binary") != NULL )
00374             form = NI_BINARY_MODE ;
00375          else if( strstr(nel->attr_rhs[ii],"base64") != NULL ){
00376             form = NI_BASE64_MODE ;
00377             ns->b64_numleft = 0 ;    
00378          }
00379 
00380          
00381 
00382          if( form != NI_TEXT_MODE ){
00383             int order=NI_MSB_FIRST ; 
00384             if( strstr(nel->attr_rhs[ii],"lsb") != NULL ) order = NI_LSB_FIRST;
00385             swap = ( order != NI_byteorder() ) ;  
00386          }
00387       }
00388 
00389       
00390 
00391       if( form == NI_TEXT_MODE ) ii = NI_LTEND_MASK ;  
00392       else if( swap )            ii = NI_SWAP_MASK  ;  
00393       else                       ii = 0 ;              
00394 
00395       row = NI_read_columns( ns ,
00396                              nel->vec_num, nel->vec_typ,
00397                              nel->vec_len, nel->vec    , form, ii );
00398 
00399       nel->vec_filled = (row >= 0) ? row : 0 ;
00400 
00401       
00402 
00403 
00404       if( nel->vec_len == 0 ){
00405         if( nel->vec_axis_len == NULL )
00406           nel->vec_axis_len = NI_malloc(int, sizeof(int)) ;
00407 
00408         nel->vec_axis_len[0] = nel->vec_len  = nel->vec_filled ;
00409         nel->vec_rank = 1 ;
00410       }
00411 
00412       
00413 
00414 
00415       num_restart = 0 ;
00416 TailRestart:
00417       num_restart++ ;
00418 
00419       if( num_restart < 99 ){  
00420          int is_tail ;
00421 
00422 #ifdef NIML_DEBUG
00423 NI_dpr("NI_read_element: TailRestart scan_for_angles; num_restart=%d\n" ,
00424                num_restart ) ;
00425 #endif
00426 
00427          nn = scan_for_angles( ns , 99 ) ;  
00428 
00429          
00430 
00431 
00432 
00433          if( nn < 0 ){
00434            if( NI_stream_readcheck(ns,0) < 0 ) return nel ;
00435            goto TailRestart ;
00436          }
00437 
00438          
00439 
00440          is_tail = ( ns->buf[ns->npos+1] == '/' ) ;
00441 
00442          if( !is_tail ){                         
00443            ns->npos = nn ; NI_reset_buffer(ns) ; 
00444            goto TailRestart ;                    
00445          }
00446 
00447          ns->npos = nn ; 
00448       }
00449 
00450       
00451 
00452 #ifdef NIML_DEBUG
00453 NI_dpr("NI_read_element: returning filled data element\n") ;
00454 #endif
00455 
00456       
00457 
00458       if( strcmp(nel->name,"ni_do") == 0 ){
00459         NI_do( ns , nel ) ;
00460         NI_free_element( nel ) ;
00461         num_restart = 0 ; goto HeadRestart ;
00462       }
00463 
00464       return nel ;
00465 
00466    } 
00467 
00468    return NULL ; 
00469 }
00470 
00471 
00472 
00473 #undef  NVBUF
00474 #define NVBUF 127  
00475 
00476 #define IS_USELESS(c) ( isspace(c) || iscntrl(c) )
00477 #define IS_CRLF(c)    ( (c) == 0x0D || (c) == 0x0A )
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 int NI_decode_one_double( NI_stream_type *ns, double *val , int ltend )
00490 {
00491    int epos , num_restart, need_data, nn ;
00492    char vbuf[NVBUF+1] ;                    
00493 
00494    
00495 
00496    if( ns == NULL || ns->bad == MARKED_FOR_DEATH || val == NULL ) return 0 ;
00497 
00498    
00499 
00500    num_restart = 0 ;
00501 Restart:
00502    num_restart++ ; need_data = 0 ;
00503    if( num_restart > 19 ) return 0 ;  
00504 
00505 #ifdef NIML_DEBUG
00506 NI_dpr(" {restart: npos=%d nbuf=%d}",ns->npos,ns->nbuf) ;
00507 #endif
00508 
00509    
00510 
00511    while( ns->npos < ns->nbuf && IS_USELESS(ns->buf[ns->npos]) ) ns->npos++ ;
00512 
00513    
00514 
00515 
00516    if( ltend && ns->npos < ns->nbuf && ns->buf[ns->npos] == '<' ) return 0 ;
00517 
00518    
00519 
00520 
00521    if( ltend && ns->npos < ns->nbuf && ns->buf[ns->npos] == '#' ){
00522      int npold = ns->npos ;
00523      while( ns->npos < ns->nbuf && !IS_CRLF(ns->buf[ns->npos]) ){
00524        if( ns->buf[ns->npos] == '<' ) return 0 ;  
00525        ns->npos++ ;
00526      }
00527      if( ns->npos < ns->nbuf ){ 
00528        num_restart = 0 ; goto Restart ;
00529      }
00530      
00531      
00532      ns->npos = npold ; need_data = 1 ;
00533    }
00534 
00535    
00536 
00537    if( !need_data )                        
00538      need_data = (ns->nbuf-ns->npos < 2) ; 
00539 
00540    
00541 
00542 
00543 
00544 
00545 
00546    if( !need_data ){  
00547 
00548 #ifdef NIML_DEBUG
00549 nn = ns->nbuf-ns->npos ; if( nn > 19 ) nn = 19 ;
00550 NI_dpr(" {buf=%.*s}" , nn , ns->buf+ns->npos ) ;
00551 #endif
00552 
00553       for( epos=ns->npos+1 ; epos < ns->nbuf ; epos++ )
00554         if( ns->buf[epos] == '<' || IS_USELESS(ns->buf[epos]) ) break ;
00555 
00556       
00557 
00558       need_data = (epos == ns->nbuf) ; 
00559 
00560 #ifdef NIML_DEBUG
00561 if( need_data ) NI_dpr(" {eob}") ;
00562 #endif
00563 
00564       
00565 
00566 
00567 
00568       if( need_data && epos-ns->npos > NVBUF ){ clear_buffer(ns); return 0; }
00569    }
00570 
00571    
00572 
00573    if( need_data ){
00574 
00575       NI_reset_buffer(ns) ; 
00576 
00577       
00578 
00579 
00580 #ifdef NIML_DEBUG
00581 NI_dpr(" {fill buf}") ;
00582 #endif
00583       nn = NI_stream_fillbuf( ns , 1 , 666 ) ;
00584 
00585       if( nn >= 0 ) goto Restart ;  
00586 
00587       
00588 
00589 
00590 
00591       if( ns->nbuf == 0 ){ ns->npos=0; return 0; }  
00592 
00593       epos = ns->nbuf ;
00594    }
00595 
00596    
00597 
00598    nn = epos-ns->npos ; if( nn > NVBUF ) nn = NVBUF ;     
00599    memcpy( vbuf, ns->buf+ns->npos, nn ); vbuf[nn] = '\0'; 
00600    *val = 0.0 ;                                           
00601    sscanf( vbuf , "%lf" , val ) ;                         
00602    ns->npos = epos ; return 1 ;                           
00603 }
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 int NI_decode_one_string( NI_stream_type *ns, char **str , int ltend )
00616 {
00617    int epos , num_restart, need_data, nn ;
00618    intpair sp ;
00619 
00620    
00621 
00622    if( ns == NULL || ns->bad == MARKED_FOR_DEATH || str == NULL ) return 0 ;
00623 
00624    
00625 
00626    num_restart = 0 ;
00627 Restart:
00628    num_restart++ ; need_data = 0 ;
00629    if( num_restart > 19 ) return 0 ;  
00630 
00631    
00632 
00633    while( ns->npos < ns->nbuf && IS_USELESS(ns->buf[ns->npos]) ) ns->npos++ ;
00634 
00635    
00636 
00637 
00638    if( ltend && ns->npos < ns->nbuf && ns->buf[ns->npos] == '<' ) return 0 ;
00639 
00640    
00641 
00642 
00643    if( ltend && ns->npos < ns->nbuf && ns->buf[ns->npos] == '#' ){
00644      int npold = ns->npos ;
00645      while( ns->npos < ns->nbuf && !IS_CRLF(ns->buf[ns->npos]) ){
00646        if( ns->buf[ns->npos] == '<' ) return 0 ;  
00647        ns->npos++ ;
00648      }
00649      if( ns->npos < ns->nbuf ){ 
00650        num_restart = 0 ; goto Restart ;
00651      }
00652      
00653      
00654      ns->npos = npold ; need_data = 1 ;
00655    }
00656 
00657    
00658 
00659    if( !need_data )                        
00660      need_data = (ns->nbuf-ns->npos < 2) ; 
00661 
00662    if( !need_data ){  
00663 
00664       
00665 
00666       sp = find_string( ns->npos , ns->nbuf , ns->buf ) ;
00667 
00668       need_data = (sp.i < 0)        ||  
00669                   (sp.j <= sp.i)    ||  
00670                   (sp.j == ns->nbuf)  ; 
00671    }
00672 
00673    
00674 
00675    if( need_data ){
00676 
00677       NI_reset_buffer(ns) ; 
00678 
00679       
00680 
00681 
00682       nn = NI_stream_fillbuf( ns , 1 , 666 ) ;
00683 
00684       if( nn >= 0 ) goto Restart ;  
00685 
00686       
00687 
00688 
00689 
00690       if( ns->nbuf == 0 ){ ns->npos=0; return 0; }  
00691 
00692       sp.i = 0 ; sp.j = ns->nbuf ;
00693    }
00694 
00695    
00696 
00697    nn = sp.j - sp.i ;                       
00698    *str = NI_malloc(char, nn+1) ;           
00699    memcpy( *str , ns->buf+sp.i , nn ) ;     
00700    (*str)[nn] = '\0' ;                      
00701 
00702    
00703 
00704    if( sp.j < ns->nbuf && IS_QUOTE_CHAR(ns->buf[sp.j]) ) sp.j++ ;
00705 
00706    ns->npos = sp.j ; return 1 ;
00707 }
00708 
00709 
00710 
00711 
00712 
00713 
00714 void NI_reset_buffer( NI_stream_type *ns )
00715 {
00716    if( ns == NULL || ns->npos <= 0 || ns->nbuf <= 0 ) return ;
00717    if( ns->buf == NULL || ns->bad == MARKED_FOR_DEATH ) return ;
00718 
00719    if( ns->npos < ns->nbuf ){          
00720      memmove( ns->buf, ns->buf+ns->npos, ns->nbuf-ns->npos ) ;
00721      ns->nbuf -= ns->npos ;
00722    } else {
00723      ns->nbuf = 0 ;                   
00724    }
00725    ns->npos = 0 ;              
00726 }
00727 
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 
00736 
00737 
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 
00749 
00750 static int scan_for_angles( NI_stream_type *ns, int msec )
00751 {
00752    int nn, epos, need_data, num_restart ;
00753    char goal ;
00754    int start_time = NI_clock_time() , mleft , nbmin ;
00755    int caseb=0 ;  
00756 
00757    if( ns == NULL ) return -1 ;  
00758 
00759    if( ns->buf == NULL || ns->bad == MARKED_FOR_DEATH ) return -1 ;
00760 
00761    epos = ns->npos ;
00762 
00763    if( msec < 0 ) msec = 999999999 ;   
00764 
00765    
00766 
00767    goal        = '<' ;  
00768    num_restart = 0   ;
00769 Restart:                                       
00770    num_restart++ ;
00771    mleft = msec - (NI_clock_time()-start_time) ;             
00772 
00773    if( num_restart > 3 && mleft <= 0 && !caseb ){              
00774       NI_reset_buffer(ns) ;                            
00775       return -1 ;
00776    }
00777 
00778    
00779 
00780    while( epos < ns->nbuf && ns->buf[epos] != goal ) epos++ ;
00781 
00782    
00783 
00784    if( epos < ns->nbuf ){
00785 
00786      
00787 
00788      if( goal == '>' ){
00789 
00790        
00791 
00792        if( epos - ns->npos >= 4 && strncmp(ns->buf+ns->npos,"<!--",4) == 0 ){
00793 
00794          if( strncmp(ns->buf+epos-2,"-->",3) == 0 ){  
00795 
00796 #if 0
00797 { int ncp = 1+epos-ns->npos ; char *cpt=malloc(10+ncp) ;
00798   memcpy(cpt,ns->buf+ns->npos,ncp) ; cpt[ncp] = '\0' ;
00799   fprintf(stderr, "\nSkipping NIML comment: '%s'\n",cpt); free(cpt);
00800 }
00801 #endif
00802          
00803            ns->npos = epos+1 ; NI_reset_buffer(ns) ;  
00804            epos = 0 ; goal = '<' ;
00805          } else {                              
00806            epos++ ;                            
00807          }
00808          caseb = 1 ; goto Restart ;
00809        }
00810 
00811        
00812 
00813        return epos+1 ;  
00814      }
00815 
00816      
00817 
00818 
00819 
00820       ns->npos = epos ;  
00821       goal     = '>'  ;  
00822       caseb    = 1    ;  
00823       goto Restart    ;  
00824    }
00825 
00826    
00827 
00828 
00829 
00830 
00831 
00832 
00833 
00834    if( goal == '<' ){                    
00835 
00836       ns->nbuf = ns->npos = epos = 0 ; caseb = 0 ;
00837 
00838    } else if( ns->nbuf < ns->bufsize || ns->npos > 0 ){  
00839 
00840       NI_reset_buffer(ns) ; epos = ns->nbuf ; caseb = 1 ;
00841 
00842    } else {                              
00843 
00844       ns->nbuf = 0 ; return -1 ;         
00845    }
00846 
00847    
00848 
00849    
00850 
00851 
00852    if( mleft <= 0 ) mleft = 1 ;
00853    nbmin = (goal == '<') ? 4 : 1 ;
00854 
00855    nn = NI_stream_fillbuf( ns , nbmin , mleft ) ;
00856 
00857    if( nn >= nbmin ) caseb = 1 ;    
00858 
00859    if( nn >= 0     ) goto Restart ; 
00860 
00861    
00862 
00863    ns->nbuf = ns->npos = 0 ; return -1 ;
00864 }
00865 
00866 
00867 
00868 
00869 static int name_mode = NI_NAMEMODE_NORMAL ;
00870 
00871 
00872 
00873 
00874 
00875 
00876 
00877 void NI_set_typename_mode( int nmode )
00878 {
00879    if( nmode > 0 && nmode <= NI_ATTMODE_LAST ) name_mode = nmode ;
00880    else                                        name_mode = NI_NAMEMODE_NORMAL;
00881 }
00882 
00883 
00884 
00885 
00886 char * NI_type_name( int code )
00887 {
00888    return (name_mode == NI_NAMEMODE_ALIAS) ? NI_rowtype_code_to_alias(code)
00889                                            : NI_rowtype_code_to_name (code) ;
00890 }
00891 
00892 
00893 
00894 
00895 
00896 
00897 
00898 
00899 
00900 
00901 
00902 
00903 
00904 int NI_write_element( NI_stream_type *ns , void *nini , int tmode )
00905 {
00906    char *wbuf , *att=NULL , *qtt , *btt ;
00907    int  nwbuf , ii,jj,row,col , tt=NI_element_type(nini) , ntot=0,nout ;
00908    int  att_len , kk ;
00909 
00910    char *bbuf , *cbuf ;  
00911    int   bb=0 ,  cc=0 ;
00912 
00913    char *att_prefix , *att_equals , *att_trail ;
00914    int header_only , header_sharp , outmode ;
00915 
00916    
00917 
00918    switch( tt ){
00919      default: return -1 ;    
00920 
00921      case NI_GROUP_TYPE:{
00922        NI_group *ngr = (NI_group *) nini ;
00923        outmode = ngr->outmode ;
00924      }
00925      break ;
00926 
00927      case NI_ELEMENT_TYPE:{
00928        NI_element *nel = (NI_element *) nini ;
00929        outmode = nel->outmode ;
00930      }
00931      break ;
00932 
00933      case NI_PROCINS_TYPE:{       
00934        outmode = NI_TEXT_MODE ;
00935      }
00936      break ;
00937    }
00938    if( outmode >= 0 ) tmode = outmode ;
00939 
00940    
00941 
00942    header_only  = ((tmode & NI_HEADERONLY_FLAG ) != 0) ;  
00943    header_sharp = ((tmode & NI_HEADERSHARP_FLAG) != 0) ;  
00944 
00945    
00946    
00947 
00948 #ifdef NIML_DEBUG
00949 NI_dpr("ENTER NI_write_element\n") ;
00950 #endif
00951 
00952 #undef  AF
00953 #define AF     0
00954 #define ADDOUT if(nout<0){AF;fprintf(stderr,"NIML: write abort!\n");return -1;} else ntot+=nout
00955 
00956    if( !NI_stream_writeable(ns) ) return -1 ;  
00957 
00958    if( ns->bad ){                        
00959 #ifdef NIML_DEBUG
00960 NI_dpr("NI_write_element: write socket not connected\n") ;
00961 #endif
00962       jj = NI_stream_goodcheck(ns,666) ; 
00963       if( jj < 1 ) return jj ;           
00964 #ifdef NIML_DEBUG
00965 NI_dpr("NI_write_element: write socket now connected\n") ;
00966 #endif
00967    } else {                              
00968       jj = NI_stream_writecheck(ns,666) ;
00969       if( jj < 0 ) return jj ;
00970    }
00971 
00972    tmode &= 255 ;
00973    if( ns->type == NI_STRING_TYPE )      
00974       tmode = NI_TEXT_MODE ;
00975 
00976    if( tmode != NI_TEXT_MODE ) header_sharp = 0 ;  
00977 
00978    
00979    
00980 
00981    att_prefix = (header_sharp) ? (char *)"\n#  " 
00982                                : (char *)"\n  " ;
00983 
00984    att_equals = (header_sharp) ? (char *)" = "   
00985                                : (char *)"="    ;
00986 
00987    att_trail  = (header_sharp) ? (char *)"\n# "  
00988                                : (char *)" "    ;
00989 
00990    
00991 
00992    if( tt == NI_PROCINS_TYPE ){
00993 
00994      NI_procins *npi = (NI_procins *)nini ;
00995 
00996      if( header_sharp ){ nout = NI_stream_writestring(ns,"# "); ADDOUT; }
00997 
00998      nout = NI_stream_writestring( ns , "<?"   )    ; ADDOUT ;
00999      nout = NI_stream_writestring( ns , npi->name ) ; ADDOUT ;
01000 
01001      
01002 
01003      for( ii=0 ; ii < npi->attr_num ; ii++ ){
01004 
01005        jj = NI_strlen( npi->attr_lhs[ii] ) ; if( jj == 0 ) continue ;
01006        nout = NI_stream_writestring( ns , " " ) ; ADDOUT ;
01007        if( NI_is_name(npi->attr_lhs[ii]) ){
01008          nout = NI_stream_write( ns , npi->attr_lhs[ii] , jj ) ;
01009        } else {
01010          att = quotize_string( npi->attr_lhs[ii] ) ;
01011          nout = NI_stream_writestring( ns , att ) ; NI_free(att) ;
01012        }
01013        ADDOUT ;
01014 
01015        jj = NI_strlen( npi->attr_rhs[ii] ) ; if( jj == 0 ) continue ;
01016        nout = NI_stream_writestring( ns , "=" ) ; ADDOUT ;
01017        att = quotize_string( npi->attr_rhs[ii] ) ;
01018        nout = NI_stream_writestring( ns , att ) ; NI_free(att) ; ADDOUT ;
01019      }
01020 
01021      nout = NI_stream_writestring( ns , " ?>\n" ) ; ADDOUT ;
01022 
01023      return ntot ;   
01024 
01025    
01026 
01027    } else if( tt == NI_GROUP_TYPE ){
01028 
01029       NI_group *ngr = (NI_group *) nini ;
01030       char *gname ;
01031 
01032       
01033 
01034 
01035       gname = ngr->name ;
01036       if( gname == NULL || *gname == '\0' ) gname = "ni_group" ;
01037 
01038       
01039 
01040       if( header_sharp ){ nout = NI_stream_writestring(ns,"# "); ADDOUT; }
01041 #if 1
01042       nout = NI_stream_writestring( ns , "<"   ) ; ADDOUT ;
01043       nout = NI_stream_writestring( ns , gname ) ; ADDOUT ;
01044 #else
01045       nout = NI_stream_writestring( ns , "<ni_group" ) ; ADDOUT ;
01046 #endif
01047 
01048       
01049 
01050       NI_set_attribute( ngr , "ni_form" , "ni_group" ) ;  
01051 
01052       for( ii=0 ; ii < ngr->attr_num ; ii++ ){
01053 
01054         jj = NI_strlen( ngr->attr_lhs[ii] ) ; if( jj == 0 ) continue ;
01055         nout = NI_stream_writestring( ns , att_prefix ) ; ADDOUT ;
01056         if( NI_is_name(ngr->attr_lhs[ii]) ){
01057           nout = NI_stream_write( ns , ngr->attr_lhs[ii] , jj ) ;
01058         } else {
01059           att = quotize_string( ngr->attr_lhs[ii] ) ;
01060           nout = NI_stream_writestring( ns , att ) ; NI_free(att) ;
01061         }
01062         ADDOUT ;
01063 
01064         jj = NI_strlen( ngr->attr_rhs[ii] ) ; if( jj == 0 ) continue ;
01065         nout = NI_stream_writestring( ns , att_equals ) ; ADDOUT ;
01066         att = quotize_string( ngr->attr_rhs[ii] ) ;
01067         nout = NI_stream_writestring( ns , att ) ; NI_free(att) ; ADDOUT ;
01068       }
01069 
01070       
01071 
01072       nout = NI_stream_writestring( ns , att_trail ) ; ADDOUT ;
01073       nout = NI_stream_writestring( ns , ">\n" ) ; ADDOUT ;
01074 
01075       
01076 
01077       for( ii=0 ; ii < ngr->part_num ; ii++ ){
01078         nout = NI_write_element( ns , ngr->part[ii] , tmode ) ; ADDOUT ;
01079       }
01080 
01081       
01082 
01083       if( header_sharp ){ nout = NI_stream_writestring(ns,"# "); ADDOUT; }
01084 #if 1
01085       nout = NI_stream_writestring( ns , "</"  ) ; ADDOUT ;
01086       nout = NI_stream_writestring( ns , gname ) ; ADDOUT ;
01087       nout = NI_stream_writestring( ns , ">\n" ) ; ADDOUT ;
01088 #else
01089       nout = NI_stream_writestring( ns , "</ni_group>\n" ) ; ADDOUT ;
01090 #endif
01091 
01092       return ntot ;   
01093 
01094    
01095 
01096    } else if( tt == NI_ELEMENT_TYPE ){
01097 
01098       NI_element *nel = (NI_element *) nini ;
01099 
01100       
01101 
01102       jj = NI_strlen(nel->name) ; if( jj == 0 ) return -1 ;
01103 
01104       
01105 
01106       
01107 
01108       if( tmode != NI_TEXT_MODE ){
01109         for( jj=0 ; jj < nel->vec_num ; jj++ ){
01110           if( NI_has_String(NI_rowtype_find_code(nel->vec_typ[jj])) ){
01111              tmode = NI_TEXT_MODE ; break ;
01112           }
01113         }
01114       }
01115 
01116       switch( tmode ){
01117          default: tmode = NI_TEXT_MODE ; break ;
01118 
01119          case NI_BINARY_MODE: break ;
01120          case NI_BASE64_MODE: break ;
01121       }
01122 
01123       
01124 
01125       att_len = 8192 + 64*nel->vec_num + 128*nel->vec_rank ;
01126       att     = NI_malloc(char, att_len ) ;
01127 
01128 #undef  AF
01129 #define AF NI_free(att)  
01130 
01131       
01132 
01133       if( header_sharp ){ nout = NI_stream_writestring(ns,"# "); ADDOUT; }
01134       strcpy(att,"<") ; strcat(att,nel->name) ;
01135       nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01136 
01137       
01138 
01139       if( nel->vec_len > 0 && nel->vec_num > 0 ){
01140          int ll , tt ;
01141 
01142          
01143 
01144          switch( tmode ){
01145            default:
01146            case NI_TEXT_MODE:
01147              *att = '\0' ;   
01148            break ;
01149 
01150            case NI_BINARY_MODE:
01151            case NI_BASE64_MODE:
01152              sprintf(att,"%sni_form%s\"%s.%s\"" ,
01153                     att_prefix , att_equals ,
01154                     (tmode == NI_BINARY_MODE)      ? "binary"   : "base64"  ,
01155                     (NI_byteorder()==NI_LSB_FIRST) ? "lsbfirst" : "msbfirst" );
01156             break ;
01157          }
01158          if( *att != '\0' ){
01159             nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01160          }
01161 
01162 
01163 
01164          sprintf(att,"%sni_type%s\"" , att_prefix , att_equals ) ;
01165          for( ll=-1,ii=0 ; ii < nel->vec_num ; ii++ ){
01166           if( nel->vec_typ[ii] != ll ){  
01167              if( ll >= 0 ){              
01168                 btt = att + strlen(att) ;
01169                 if( jj > 1 ) sprintf(btt,"%d*%s,",jj,NI_type_name(ll)) ;
01170                 else         sprintf(btt,"%s,"   ,   NI_type_name(ll)) ;
01171              }
01172              ll = nel->vec_typ[ii] ;     
01173              jj = 1 ;                    
01174 
01175           } else {                       
01176              jj++ ;                      
01177           }
01178          }
01179          
01180          btt = att + strlen(att) ;
01181          if( jj > 1 ) sprintf(btt,"%d*%s\"",jj,NI_type_name(ll)) ;
01182          else         sprintf(btt,"%s\""   ,   NI_type_name(ll)) ;
01183 
01184          nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01185 
01186 
01187 
01188          if( nel->vec_rank > 1 ){
01189            sprintf(att,"%sni_dimen%s" , att_prefix , att_equals ) ;
01190            qtt = quotize_int_vector( nel->vec_rank ,
01191                                    nel->vec_axis_len , ',' ) ;
01192            strcat(att,qtt) ; NI_free(qtt) ;
01193          } else {
01194            sprintf(att,"%sni_dimen%s\"%d\"",att_prefix,att_equals,nel->vec_len);
01195          }
01196          nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01197 
01198 #if 0
01199 
01200 
01201          for( jj=ii=0 ; ii < nel->vec_num ; ii++ )
01202             jj += NI_size_column( NI_rowtype_find_code(nel->vec_typ[ii]) ,
01203                                   nel->vec_len , nel->vec[ii] ) ;
01204          sprintf(att,"%sni_datasize%s\"%d\"" , att_prefix , att_equals , jj ) ;
01205          nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01206 #endif
01207 
01208 #if 0
01209          
01210 
01211          sprintf(att,"%sni_veclen%s\"%d\"", att_prefix,att_equals,nel->vec_len) ;
01212          nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01213 
01214          sprintf(att,"%sni_vecnum%s\"%d\"", att_prefix,att_equals,nel->vec_num) ;
01215          nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01216 #endif
01217          
01218 
01219          if( nel->vec_axis_delta != NULL ){
01220             sprintf(att,"%sni_delta%s",att_prefix,att_equals) ;
01221             qtt = quotize_float_vector( nel->vec_rank ,
01222                                         nel->vec_axis_delta , ',' ) ;
01223             strcat(att,qtt) ; NI_free(qtt) ;
01224             nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01225          }
01226 
01227          
01228 
01229          if( nel->vec_axis_origin != NULL ){
01230             sprintf(att,"%sni_origin%s",att_prefix,att_equals) ;
01231             qtt = quotize_float_vector( nel->vec_rank ,
01232                                         nel->vec_axis_origin , ',' ) ;
01233             strcat(att,qtt) ; NI_free(qtt) ;
01234             nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01235          }
01236 
01237          
01238 
01239          if( nel->vec_axis_unit != NULL ){
01240             sprintf(att,"%sni_units%s",att_prefix,att_equals) ;
01241             qtt = quotize_string_vector( nel->vec_rank ,
01242                                          nel->vec_axis_unit , ',' ) ;
01243             strcat(att,qtt) ; NI_free(qtt) ;
01244             nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01245          }
01246 
01247          
01248 
01249          if( nel->vec_axis_label != NULL ){
01250             sprintf(att,"%sni_axes%s",att_prefix,att_equals) ;
01251             qtt = quotize_string_vector( nel->vec_rank ,
01252                                          nel->vec_axis_label , ',' ) ;
01253             strcat(att,qtt) ; NI_free(qtt) ;
01254             nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01255          }
01256 
01257       }
01258 
01259       
01260 
01261       for( ii=0 ; ii < nel->attr_num ; ii++ ){
01262 
01263          jj = NI_strlen( nel->attr_lhs[ii] ) ; if( jj == 0 ) continue ;
01264 
01265          
01266 
01267          if( strcmp(nel->attr_lhs[ii],"ni_form")     == 0 ) continue ;
01268          if( strcmp(nel->attr_lhs[ii],"ni_type")     == 0 ) continue ;
01269          if( strcmp(nel->attr_lhs[ii],"ni_dimen")    == 0 ) continue ;
01270          if( strcmp(nel->attr_lhs[ii],"ni_veclen")   == 0 ) continue ;
01271          if( strcmp(nel->attr_lhs[ii],"ni_vecnum")   == 0 ) continue ;
01272          if( strcmp(nel->attr_lhs[ii],"ni_delta")    == 0 ) continue ;
01273          if( strcmp(nel->attr_lhs[ii],"ni_origin")   == 0 ) continue ;
01274          if( strcmp(nel->attr_lhs[ii],"ni_units")    == 0 ) continue ;
01275          if( strcmp(nel->attr_lhs[ii],"ni_axes")     == 0 ) continue ;
01276          if( strcmp(nel->attr_lhs[ii],"ni_datasize") == 0 ) continue ; 
01277 
01278          kk = NI_strlen( nel->attr_rhs[ii] ) ;
01279 
01280          
01281 
01282          if( jj+kk+128 > att_len ){                 
01283            att_len = jj+kk+128 ;
01284            att     = NI_realloc( att , char, att_len ) ;
01285          }
01286 
01287          strcpy(att,att_prefix) ;
01288 
01289          if( NI_is_name(nel->attr_lhs[ii]) ){           
01290            strcat(att,nel->attr_lhs[ii]) ;
01291          } else {                                        
01292            qtt = quotize_string( nel->attr_lhs[ii] ) ;
01293            strcat(att,qtt) ; NI_free(qtt) ;
01294          }
01295 
01296          if( kk > 0 ){
01297             strcat(att,att_equals) ;
01298             qtt = quotize_string( nel->attr_rhs[ii] ) ; 
01299             strcat(att,qtt) ; NI_free(qtt) ;
01300          }
01301          nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01302       }
01303 
01304       NI_free(att) ; att = NULL ; 
01305 
01306 #undef  AF
01307 #define AF 0  
01308 
01309       
01310 
01311       if( nel->vec_len == 0    ||     
01312           nel->vec_num == 0    ||
01313           nel->vec_typ == NULL ||
01314           nel->vec     == NULL   ){
01315 
01316         nout = NI_stream_writestring( ns , att_trail ) ; ADDOUT ;
01317         nout = NI_stream_writestring( ns , "/>\n" )    ; ADDOUT ;
01318 
01319 #ifdef NIML_DEBUG
01320   NI_dpr("NI_write_element: empty element '%s' had %d total bytes\n",nel->name,ntot) ;
01321 #endif
01322         return ntot ;                 
01323       }
01324 
01325       
01326 
01327       
01328 
01329 
01330       switch( tmode ){
01331          default:
01332          case NI_TEXT_MODE:
01333             btt = ">\n" ;                             
01334          break ;
01335 
01336          case NI_BINARY_MODE:
01337             btt = ">" ;                               
01338          break ;
01339 
01340          case NI_BASE64_MODE:
01341             btt = ">\n" ;                             
01342          break ;
01343       }
01344 
01345       nout = NI_stream_writestring( ns , att_trail ) ; ADDOUT ;
01346       nout = NI_stream_writestring( ns , btt ) ; ADDOUT ;
01347 
01348       
01349 
01350       if( !header_only ){
01351         nout = NI_write_columns( ns, nel->vec_num, nel->vec_typ,
01352                                      nel->vec_len, nel->vec    , tmode ) ;
01353         ADDOUT ;
01354       }
01355 #ifdef NIML_DEBUG
01356       else NI_dpr("NI_write_element: header_only case\n") ;
01357 #endif
01358 
01359       
01360 
01361       if( header_sharp ){ nout = NI_stream_writestring(ns,"# "); ADDOUT; }
01362       nout = NI_stream_writestring( ns , "</" ) ; ADDOUT ;
01363       nout = NI_stream_writestring( ns , nel->name ) ; ADDOUT ;
01364       nout = NI_stream_writestring( ns , ">\n\n" ) ; ADDOUT ;
01365 
01366 #ifdef NIML_DEBUG
01367   NI_dpr("NI_write_element: data element '%s' had %d total bytes\n",nel->name,ntot) ;
01368 #endif
01369       return ntot ;   
01370 
01371    } 
01372 
01373    return -1 ; 
01374 }