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 }