Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

niml_elemio.c File Reference

#include "niml_private.h"

Go to the source code of this file.


Defines

#define clear_buffer(ns)   ( (ns)->nbuf = (ns)->npos = 0 )
#define NVBUF   127
#define IS_USELESS(c)   ( isspace(c) || iscntrl(c) )
#define IS_CRLF(c)   ( (c) == 0x0D || (c) == 0x0A )
#define AF   0
#define ADDOUT   if(nout<0){AF;fprintf(stderr,"NIML: write abort!\n");return -1;} else ntot+=nout
#define AF   NI_free(att)
#define AF   0

Functions

int scan_for_angles (NI_stream_type *, int)
int header_stuff_is_group (header_stuff *hs)
int header_stuff_is_procins (header_stuff *hs)
int NI_write_procins (NI_stream_type *ns, char *str)
void NI_read_header_only (int r)
void NI_skip_procins (int r)
void * NI_read_element_header (NI_stream_type *ns, int msec)
void * NI_read_element (NI_stream_type *ns, int msec)
int NI_decode_one_double (NI_stream_type *ns, double *val, int ltend)
int NI_decode_one_string (NI_stream_type *ns, char **str, int ltend)
void NI_reset_buffer (NI_stream_type *ns)
void NI_set_typename_mode (int nmode)
char * NI_type_name (int code)
int NI_write_element (NI_stream_type *ns, void *nini, int tmode)

Variables

int read_header_only = 0
int skip_procins = 0
int name_mode = NI_NAMEMODE_NORMAL

Define Documentation

#define ADDOUT   if(nout<0){AF;fprintf(stderr,"NIML: write abort!\n");return -1;} else ntot+=nout
 

#define AF   0
 

#define AF   NI_free(att)
 

#define AF   0
 

#define clear_buffer ns       ( (ns)->nbuf = (ns)->npos = 0 )
 

Definition at line 9 of file niml_elemio.c.

Referenced by NI_decode_one_double().

#define IS_CRLF c       ( (c) == 0x0D || (c) == 0x0A )
 

Definition at line 477 of file niml_elemio.c.

Referenced by NI_decode_one_double(), and NI_decode_one_string().

#define IS_USELESS c       ( isspace(c) || iscntrl(c) )
 

Definition at line 476 of file niml_elemio.c.

Referenced by NI_decode_one_double(), and NI_decode_one_string().

#define NVBUF   127
 

Definition at line 474 of file niml_elemio.c.

Referenced by NI_decode_one_double().


Function Documentation

int header_stuff_is_group header_stuff   hs [static]
 

Check if header_stuff marks this NIML element as a group. ----------------------------------------------------------------------

Definition at line 15 of file niml_elemio.c.

References get_header_attribute(), and header_stuff::name.

Referenced by NI_read_element().

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 }

int header_stuff_is_procins header_stuff   hs [static]
 

Check if header_stuff marks NIML element as a processing instruction. ----------------------------------------------------------------------

Definition at line 29 of file niml_elemio.c.

References header_stuff::name.

Referenced by NI_read_element().

00030 {
00031    if( hs == NULL ) return 0 ;
00032    if( hs->name != NULL && hs->name[0] == '?' ) return 1 ;
00033    return 0 ;
00034 }

int NI_decode_one_double NI_stream_type   ns,
double *    val,
int    ltend
 

From the NI_stream ns, starting at buffer position ns->npos, decode one number into *val.

  • Parameter ltend != 0 means to stop at '<' character [07 Jan 2003].
  • ltend != 0 also means to skip lines starting with '#' [20 Mar 2003].
  • ns->npos will be altered to reflect the current buffer position (one after the last character processed) when all is done.
  • Return value of this function is 1 if we succeeded, 0 if not. ------------------------------------------------------------------------

Definition at line 489 of file niml_elemio.c.

References NI_stream_type::bad, NI_stream_type::buf, clear_buffer, IS_CRLF, IS_USELESS, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_dpr(), NI_reset_buffer(), NI_stream_fillbuf(), NI_stream_type::npos, and NVBUF.

Referenced by NI_text_to_val().

00490 {
00491    int epos , num_restart, need_data, nn ;
00492    char vbuf[NVBUF+1] ;                    /* number string from buffer */
00493 
00494    /*-- check inputs for stupidness --*/
00495 
00496    if( ns == NULL || ns->bad == MARKED_FOR_DEATH || val == NULL ) return 0 ;
00497 
00498    /*--- might loop back here to check if have enough data for a number ---*/
00499 
00500    num_restart = 0 ;
00501 Restart:
00502    num_restart++ ; need_data = 0 ;
00503    if( num_restart > 19 ) return 0 ;  /*** too much ==> give up ***/
00504 
00505 #ifdef NIML_DEBUG
00506 NI_dpr(" {restart: npos=%d nbuf=%d}",ns->npos,ns->nbuf) ;
00507 #endif
00508 
00509    /*-- advance over useless characters in the buffer --*/
00510 
00511    while( ns->npos < ns->nbuf && IS_USELESS(ns->buf[ns->npos]) ) ns->npos++ ;
00512 
00513    /*-- check if we ran into the closing '<' prematurely
00514         (before any useful characters); if we did, then we are done --*/
00515 
00516    if( ltend && ns->npos < ns->nbuf && ns->buf[ns->npos] == '<' ) return 0 ;
00517 
00518    /*-- 20 Mar 2003: check if we ran into a comment character '#';
00519                      if we did, skip to the end of the line (or '<') --*/
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 ;  /* STOP HERE! */
00525        ns->npos++ ;
00526      }
00527      if( ns->npos < ns->nbuf ){ /* found end of line, so try again */
00528        num_restart = 0 ; goto Restart ;
00529      }
00530      /* if here, didn't find '<' or end of line in buffer */
00531      /* so reset pointer back to '#', then read more data */
00532      ns->npos = npold ; need_data = 1 ;
00533    }
00534 
00535    /*-- if we need some data, try to get some --*/
00536 
00537    if( !need_data )                        /* need at least 2 unused  */
00538      need_data = (ns->nbuf-ns->npos < 2) ; /* bytes to decode a number */
00539 
00540    /*-- An input value is decoded from a string of non-useless
00541         characters delimited by a useless character (or by the
00542         element closing '<').
00543         Note that the 1st character we are now at is non-useless.
00544         Scan forward to see if we have a useless character later. --*/
00545 
00546    if( !need_data ){  /* so have at least 2 characters */
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       /*- epos is either the delimiter position, or the end of data bytes -*/
00557 
00558       need_data = (epos == ns->nbuf) ; /* no delimiter ==> need more data */
00559 
00560 #ifdef NIML_DEBUG
00561 if( need_data ) NI_dpr(" {eob}") ;
00562 #endif
00563 
00564       /*- If the string of characters we have is not yet
00565           delimited, and it is too long to be a number,
00566           throw out all the data in the buffer and quit. -*/
00567 
00568       if( need_data && epos-ns->npos > NVBUF ){ clear_buffer(ns); return 0; }
00569    }
00570 
00571    /*-- read more data now if it is needed --*/
00572 
00573    if( need_data ){
00574 
00575       NI_reset_buffer(ns) ; /* discard used up data in buffer */
00576 
00577       /*- read at least 1 byte,
00578           waiting up to 666 ms (unless the data stream goes bad) -*/
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 ;  /* check if buffer is adequate now */
00586 
00587       /*- if here, the stream went bad.  If there are still
00588           data bytes in the stream, we can try to interpret them.
00589           Otherwise, must quit without success.                  -*/
00590 
00591       if( ns->nbuf == 0 ){ ns->npos=0; return 0; }  /* quitting */
00592 
00593       epos = ns->nbuf ;
00594    }
00595 
00596    /*-- if here, try to interpret data bytes ns->npos .. epos-1 --*/
00597 
00598    nn = epos-ns->npos ; if( nn > NVBUF ) nn = NVBUF ;     /* # bytes to read   */
00599    memcpy( vbuf, ns->buf+ns->npos, nn ); vbuf[nn] = '\0'; /* put bytes in vbuf */
00600    *val = 0.0 ;                                           /* initialize val */
00601    sscanf( vbuf , "%lf" , val ) ;                         /* interpret them    */
00602    ns->npos = epos ; return 1 ;                           /* retire undefeated */
00603 }

int NI_decode_one_string NI_stream_type   ns,
char **    str,
int    ltend
 

From the NI_stream ns, starting at buffer position ns->npos, decode one string into newly NI_malloc()-ed space pointed to by *str.

  • Parameter ltend !=0 means to stop at '<' character [07 Jan 2003].
  • ltend != 0 also means to skip lines starting with '#' [20 Mar 2003].
  • Return value of this function is 1 if we succeeded, 0 if not.
  • ns->npos will be altered to reflect the current buffer position (one after the last character processed) when all is done. ------------------------------------------------------------------------

Definition at line 615 of file niml_elemio.c.

References NI_stream_type::bad, NI_stream_type::buf, find_string(), intpair::i, IS_CRLF, IS_QUOTE_CHAR, IS_USELESS, intpair::j, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_malloc, NI_reset_buffer(), NI_stream_fillbuf(), and NI_stream_type::npos.

Referenced by NI_text_to_val().

00616 {
00617    int epos , num_restart, need_data, nn ;
00618    intpair sp ;
00619 
00620    /*-- check inputs for stupidness --*/
00621 
00622    if( ns == NULL || ns->bad == MARKED_FOR_DEATH || str == NULL ) return 0 ;
00623 
00624    /*--- might loop back here to check if have enough data ---*/
00625 
00626    num_restart = 0 ;
00627 Restart:
00628    num_restart++ ; need_data = 0 ;
00629    if( num_restart > 19 ) return 0 ;  /*** give up ***/
00630 
00631    /*-- advance over useless characters in the buffer --*/
00632 
00633    while( ns->npos < ns->nbuf && IS_USELESS(ns->buf[ns->npos]) ) ns->npos++ ;
00634 
00635    /*-- check if we ran into the closing '<' prematurely
00636         (before any useful characters); if we did, then we are done --*/
00637 
00638    if( ltend && ns->npos < ns->nbuf && ns->buf[ns->npos] == '<' ) return 0 ;
00639 
00640    /*-- 20 Mar 2003: check if we ran into a comment character '#';
00641                      if we did, skip to the end of the line (or '<') --*/
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 ;  /* STOP HERE! */
00647        ns->npos++ ;
00648      }
00649      if( ns->npos < ns->nbuf ){ /* found end of line, so try again */
00650        num_restart = 0 ; goto Restart ;
00651      }
00652      /* if here, didn't find '<' or end of line in buffer */
00653      /* so reset pointer back to '#', then read more data */
00654      ns->npos = npold ; need_data = 1 ;
00655    }
00656 
00657    /*-- if we need some data, try to get some --*/
00658 
00659    if( !need_data )                        /* need at least 2 unused  */
00660      need_data = (ns->nbuf-ns->npos < 2) ; /* bytes to decode a string */
00661 
00662    if( !need_data ){  /* so have at least 2 characters */
00663 
00664       /* search for the string from here forward */
00665 
00666       sp = find_string( ns->npos , ns->nbuf , ns->buf ) ;
00667 
00668       need_data = (sp.i < 0)        ||  /* didn't find a string */
00669                   (sp.j <= sp.i)    ||  /* ditto */
00670                   (sp.j == ns->nbuf)  ; /* hit end of data bytes */
00671    }
00672 
00673    /*-- read more data now if it is needed --*/
00674 
00675    if( need_data ){
00676 
00677       NI_reset_buffer(ns) ; /* discard used up data in buffer */
00678 
00679       /*- read at least 1 byte,
00680           waiting up to 666 ms (unless the data stream goes bad) -*/
00681 
00682       nn = NI_stream_fillbuf( ns , 1 , 666 ) ;
00683 
00684       if( nn >= 0 ) goto Restart ;  /* check if buffer is adequate now */
00685 
00686       /*- if here, the stream went bad.  If there are still
00687           data bytes in the stream, we can try to interpret them.
00688           Otherwise, must quit without success.                  -*/
00689 
00690       if( ns->nbuf == 0 ){ ns->npos=0; return 0; }  /* quitting */
00691 
00692       sp.i = 0 ; sp.j = ns->nbuf ;
00693    }
00694 
00695    /*-- if here, data bytes sp.i .. sp.j-1 are the string --*/
00696 
00697    nn = sp.j - sp.i ;                       /* length of string */
00698    *str = NI_malloc(char, nn+1) ;           /* make the string */
00699    memcpy( *str , ns->buf+sp.i , nn ) ;     /* copy data to string */
00700    (*str)[nn] = '\0' ;                      /* terminate string */
00701 
00702    /* skip close quote character, if present */
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 }

void* NI_read_element NI_stream_type   ns,
int    msec
 

Read an element (maybe a group) from the stream, waiting up to msec milliseconds for the header to appear. (After that, this function may wait a long time for the rest of the element to appear, unless the data stream comes to a premature end.)

Return is NULL if nothing can be read at this time. Otherwise, use NI_element_type(return value) to determine if the element read is a data element or a group element.

Note that a header that is longer than ns->bufsize will never be read properly, since we must have the entire header in the buffer before processing it. This should only be a problem for deranged users. If such a vast header is encountered, it will be flushed.

If header start '<' and stop '>' are encountered, then this function will read data until it can create an element, or until the data stream is bad (i.e., the file ends, or the socket closes).

If NULL is returned, that can be because there is no data to read even in the buffer, or because the input data stream has gone bad (i.e., will return no more data ever). To check for the latter case, use NI_stream_readcheck().

If a "<ni_do ... />" or "<?ni_do ... ?>" element is encountered, it will not be returned to the caller. Instead, the actions it orders will be carried out in function NI_do(), and the function will loop back to find some other input. ----------------------------------------------------------------------

Definition at line 126 of file niml_elemio.c.

References NI_element::attr_lhs, NI_procins::attr_lhs, NI_element::attr_num, NI_procins::attr_num, NI_element::attr_rhs, NI_procins::attr_rhs, NI_stream_type::b64_numleft, NI_stream_type::bad, NI_stream_type::buf, destroy_header_stuff(), header_stuff::empty, header_stuff_is_group(), header_stuff_is_procins(), header_stuff::lhs, make_empty_data_element(), make_empty_group_element(), MARKED_FOR_DEATH, NI_element::name, NI_procins::name, header_stuff::name, header_stuff::nattr, NI_add_to_group(), NI_BASE64_MODE, NI_BINARY_MODE, NI_byteorder(), NI_clock_time(), NI_do(), NI_dpr(), NI_free, NI_free_element(), NI_LSB_FIRST, NI_LTEND_MASK, NI_malloc, NI_MSB_FIRST, NI_PROCINS_TYPE, NI_read_columns(), NI_reset_buffer(), NI_sleep(), NI_strdup(), NI_stream_goodcheck(), NI_stream_readcheck(), NI_SWAP_MASK, NI_TEXT_MODE, NI_stream_type::npos, parse_header_stuff(), read_header_only, header_stuff::rhs, scan_for_angles(), string_index(), swap, NI_procins::type, NI_element::vec, NI_element::vec_axis_len, NI_element::vec_filled, NI_element::vec_len, NI_element::vec_num, NI_element::vec_rank, and NI_element::vec_typ.

Referenced by AFNI_niml_workproc(), AFNI_start_version_check(), AIVVV_workproc(), Dtable_from_nimlstring(), main(), NI_read_element_header(), NI_read_file_nohead(), NI_suck_stream(), SUMA_FakeIt(), SUMA_LoadNimlDset(), SUMA_LoadVisualState(), SUMA_niml_workproc(), SUMA_OpenDrawnROI_NIML(), THD_load_3D(), THD_open_3D(), THD_open_nifti(), THD_read_niml_atr(), and XSAVE_input().

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 ;  /* bad input stream */
00135 
00136 #ifdef NIML_DEBUG
00137 NI_dpr("ENTER NI_read_element\n") ;
00138 #endif
00139 
00140    if( msec < 0 ) msec = 999999999 ;  /* a long time (11+ days) */
00141 
00142    /* if we have a socket that hasn't connected,
00143       then see if it can connect now            */
00144 
00145    if( ns->bad ){
00146      nn = NI_stream_goodcheck( ns , msec ) ;
00147      if( nn < 1 ) return NULL ;              /* didn't connect */
00148    }
00149 
00150    /*-- Try to find the element header --*/
00151 
00152    num_restart = 0 ;
00153 HeadRestart:                            /* loop back here to retry */
00154    num_restart++ ;
00155    mleft = msec - (NI_clock_time()-start_time) ;      /* time left */
00156    if( num_restart > 1 && mleft <= 0 ) return NULL ;  /* don't allow too many loops */
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 ) ;     /* look for '<stuff>' */
00164 
00165    /* didn't find it */
00166 
00167    if( nn < 0 ){
00168      if( NI_stream_readcheck(ns,0) < 0 ) return NULL ;   /* connection lost */
00169      NI_sleep(2); goto HeadRestart;                      /* try again */
00170    }
00171 
00172 #ifdef NIML_DEBUG
00173 NI_dpr("NI_read_element: found '<'\n") ;
00174 #endif
00175 
00176    /* ns->buf[ns->npos] = opening '<' ; ns->buf[nn-1] = closing '>' */
00177 
00178    /* see if we found '<>', which is meaningless,
00179       or a trailer '</stuff>', which is illegal here */
00180 
00181    if( nn - ns->npos <= 2 || ns->buf[ns->npos+1] == '/' ){
00182       ns->npos = nn; NI_reset_buffer(ns); /* toss the '<..>', try again */
00183 #ifdef NIML_DEBUG
00184 NI_dpr("NI_read_element: illegal header found? skipping\n") ;
00185 #endif
00186       goto HeadRestart ;
00187    }
00188 
00189    /*----- Parse the header data and prepare to make an element! -----*/
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 ){  /* something bad happened there */
00198      fprintf(stderr,"NI_read_element: bad element header found!\n") ;
00199      ns->npos = nn; NI_reset_buffer(ns); /* toss the '<..>', try again */
00200      goto HeadRestart ;
00201    }
00202 
00203    /*----- If here, have parsed a header (and will not HeadRestart).
00204            First, expunge the data bytes that were consumed to make
00205            the header; that is, we can then start reading data from
00206            ns->buf[ns->npos] .. ns->buf[ns->nbuf-1]                 --*/
00207 
00208    ns->npos = nn ;
00209 
00210 #ifdef NIML_DEBUG
00211 NI_dpr("NI_read_element: header parsed successfully\n") ;
00212 #endif
00213 
00214    /*--------------- Now make an element of some kind ---------------*/
00215 
00216    if( header_stuff_is_procins(hs) ){       /*--- a processing instruction ---*/
00217 
00218      NI_procins *npi ;
00219 
00220      if( strcmp(hs->name,"?ni_do") == 0 ){  /* 19 Apr 2005: special case! */
00221        NI_element *nel ;
00222        nel = make_empty_data_element( hs ) ;         /* temporary element */
00223        destroy_header_stuff( hs ) ;
00224        NI_do( ns , nel ) ;                        /* do the stuff it says */
00225        NI_free_element( nel ) ;                        /* then destroy it */
00226        if( ns->bad == MARKED_FOR_DEATH || ns->buf == NULL ) return NULL ;
00227        num_restart = 0 ; goto HeadRestart ;
00228      }
00229 
00230      /* 03 Jun 2005: if ordered to skip these things, do so */
00231 
00232      if( skip_procins ){
00233        destroy_header_stuff( hs ) ; num_restart = 0 ; goto HeadRestart ;
00234      }
00235 
00236      /* normal case: make a procins element and give it to the caller */
00237 
00238      npi       = NI_malloc(NI_procins,sizeof(NI_procins)) ;
00239      npi->type = NI_PROCINS_TYPE ;
00240      npi->name = NI_strdup( hs->name + 1 ) ; /* skip the '?' */
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    } /*--- end of reading a processing instruction ---*/
00255 
00256    else if( header_stuff_is_group(hs) ){           /*---- a group element ----*/
00257 
00258       NI_group *ngr ;
00259       void *nini ;
00260       int   empty=hs->empty ;
00261 
00262       read_header_only = 0 ;         /* 23 Mar 2003 */
00263 
00264       start_time = NI_clock_time() ; /* allow up to 10 sec for next */
00265       msec       = 9999 ;            /* element to appear, before giving up */
00266 
00267       ngr = make_empty_group_element( hs ) ;  /* copies name and attributes */
00268       destroy_header_stuff( hs ) ;
00269       if( empty ) return ngr ;  /* 03 Jun 2002: empty group is legal */
00270 
00271       /* we now have to read the elements within the group */
00272 
00273       num_restart = 0 ;
00274       while(1){           /* loop to find an element */
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 ) ;  /* find header/trailer '<...>' */
00282 
00283          mleft = msec - (NI_clock_time()-start_time) ;
00284          if( mleft < 0 ) mleft = 0 ;
00285 
00286          if( nn <= 0 ){  /* didn't find it */
00287            if( NI_stream_readcheck(ns,0) < 0 ) break ;  /* real bad */
00288            if( num_restart > 1 && mleft == 0 ) break ;  /* time's up */
00289            num_restart++ ;
00290            continue ;        /* try again (but not forever) */
00291          }
00292 
00293          /* check if we found a trailer element '</stuff>' */
00294 
00295          if( ns->buf[ns->npos+1] == '/' ){  /* trailer */
00296            ns->npos = nn ;                 /* so end the group */
00297            break ;
00298          }
00299 
00300          /* not a trailer, so try to make an element out of it */
00301 
00302          nini = NI_read_element( ns , mleft ) ;   /* recursion! */
00303          if( nini != NULL ){
00304             NI_add_to_group( ngr , nini ) ;  /* this is good */
00305             num_restart = 0 ;
00306             start_time = NI_clock_time() ;   /* restart the wait clock */
00307          } else {                            /* this is bad */
00308             if( NI_stream_readcheck(ns,0) < 0 ) break ;    /* real bad */
00309             mleft = msec - (NI_clock_time()-start_time) ;
00310             if( num_restart > 1 && mleft <= 0 ) break ;    /* time's up */
00311             num_restart++ ;
00312          }
00313       }
00314 
00315       /* and we are done */
00316 
00317       return ngr ;
00318 
00319    } /* end of reading group element */
00320 
00321    else {      /*------------------------ a data element ---------------------*/
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       /*-- check if this is an empty element --*/
00330 
00331       if( nel           == NULL ||     /* nel == NULL should never happen. */
00332           nel->vec_rank == 0    ||     /* These other cases are indication */
00333           nel->vec_num  == 0    ||     /* that this is an 'empty' element. */
00334           nel->vec_typ  == NULL ||     /* ==> The header is all there is.  */
00335           nel->vec      == NULL ||
00336           nel->name[0]  == '!'  ||     /* Stupid XML declaration */
00337           read_header_only        ){
00338 
00339 #ifdef NIML_DEBUG
00340 NI_dpr("NI_read_element: returning empty element\n") ;
00341 #endif
00342 
00343         /*-- 23 Aug 2002: do something, instead of returning data? --*/
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 ;   /* default: return element */
00358       }
00359 
00360       /*-- If here, must read data from the buffer into nel->vec --*/
00361 
00362       /* Find the form of the input */
00363 
00364       form = NI_TEXT_MODE ; /* default is text mode */
00365       swap = 0 ;            /* and (obviously) don't byte swap */
00366 
00367       ii = string_index( "ni_form" , nel->attr_num , nel->attr_lhs ) ;
00368 
00369       if( ii >= 0 && nel->attr_rhs[ii] != NULL ){ /* parse ni_form=rhs */
00370 
00371          /* binary or base64 mode? */
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 ;    /* 21 Apr 2005: reset Base64 leftovers */
00378          }
00379 
00380          /* check byteorder in header vs. this CPU */
00381 
00382          if( form != NI_TEXT_MODE ){
00383             int order=NI_MSB_FIRST ; /* default input byteorder */
00384             if( strstr(nel->attr_rhs[ii],"lsb") != NULL ) order = NI_LSB_FIRST;
00385             swap = ( order != NI_byteorder() ) ;  /* swap bytes? */
00386          }
00387       }
00388 
00389       /*-- 13 Feb 2003: Use new NI_read_columns() function to get data. --*/
00390 
00391       if( form == NI_TEXT_MODE ) ii = NI_LTEND_MASK ;  /* end on '<' char  */
00392       else if( swap )            ii = NI_SWAP_MASK  ;  /* swap binary data */
00393       else                       ii = 0 ;              /* no special flag  */
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       /* 27 Mar 2003: allow for case where vec_len is
00402                       inferred from how much data we read */
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       /*-- Now scan for the end-of-element marker '</something>' and
00413            skip all input bytes up to (and including) the final '>'. --*/
00414 
00415       num_restart = 0 ;
00416 TailRestart:
00417       num_restart++ ;
00418 
00419       if( num_restart < 99 ){  /* don't loop forever, dude */
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 ) ;  /* find '<...>' */
00428 
00429          /* if we didn't find '<...>' at all,
00430             then if the I/O stream is bad, just exit;
00431             otherwise, try scanning for '<...>' again */
00432 
00433          if( nn < 0 ){
00434            if( NI_stream_readcheck(ns,0) < 0 ) return nel ;
00435            goto TailRestart ;
00436          }
00437 
00438          /* we have '<...>', but make sure it starts with '</' */
00439 
00440          is_tail = ( ns->buf[ns->npos+1] == '/' ) ;
00441 
00442          if( !is_tail ){                         /* no '/'? */
00443            ns->npos = nn ; NI_reset_buffer(ns) ; /* skip '<...>' */
00444            goto TailRestart ;                    /* and try again */
00445          }
00446 
00447          ns->npos = nn ; /* skip '</...>' and we are done here! */
00448       }
00449 
00450       /*-- And are done with the input stream and the data element! --*/
00451 
00452 #ifdef NIML_DEBUG
00453 NI_dpr("NI_read_element: returning filled data element\n") ;
00454 #endif
00455 
00456       /*-- 23 Aug 2002: do something, instead of returning data? --*/
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    } /* end of reading data element */
00467 
00468    return NULL ; /* should never be reached */
00469 }

void* NI_read_element_header NI_stream_type   ns,
int    msec
 

Read only the header part of the next element. ----------------------------------------------------------------------

Definition at line 86 of file niml_elemio.c.

References NI_read_element(), and read_header_only.

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 }

void NI_read_header_only int    r
 

Definition at line 77 of file niml_elemio.c.

References r, and read_header_only.

Referenced by THD_open_3D().

00077 { read_header_only=r ; } /* 23 Mar 2003 */

void NI_reset_buffer NI_stream_type   ns
 

Reset the unscanned bytes in the buffer to start at position 0 instead of position ns->npos; then set ns->npos to 0. ------------------------------------------------------------------------

Definition at line 714 of file niml_elemio.c.

References NI_stream_type::bad, NI_stream_type::buf, MARKED_FOR_DEATH, NI_stream_type::nbuf, and NI_stream_type::npos.

Referenced by NI_decode_one_double(), NI_decode_one_string(), NI_read_element(), NI_stream_readbuf(), NI_stream_readbuf64(), and scan_for_angles().

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 ){          /* haven't used up all data yet */
00720      memmove( ns->buf, ns->buf+ns->npos, ns->nbuf-ns->npos ) ;
00721      ns->nbuf -= ns->npos ;
00722    } else {
00723      ns->nbuf = 0 ;                   /* all data in buffer is used up */
00724    }
00725    ns->npos = 0 ;              /* further scanning starts at beginning */
00726 }

void NI_set_typename_mode int    nmode
 

Set the mode for writing type names:

  • NI_NAMEMODE_NORMAL => byte , short, int , float , double , ...
  • NI_NAMEMODE_ALIAS => uint8, int16, int32, float32, float64, ... --------------------------------------------------------------------------

Definition at line 877 of file niml_elemio.c.

References name_mode, NI_ATTMODE_LAST, and NI_NAMEMODE_NORMAL.

00878 {
00879    if( nmode > 0 && nmode <= NI_ATTMODE_LAST ) name_mode = nmode ;
00880    else                                        name_mode = NI_NAMEMODE_NORMAL;
00881 }

void NI_skip_procins int    r
 

Definition at line 80 of file niml_elemio.c.

References r, and skip_procins.

Referenced by THD_load_3D(), and THD_open_3D().

00080 { skip_procins = r ; }       /* 03 Jun 2005 */

char* NI_type_name int    code
 

Return the type name given the integer code.

Definition at line 886 of file niml_elemio.c.

References name_mode, NI_NAMEMODE_ALIAS, NI_rowtype_code_to_alias(), and NI_rowtype_code_to_name().

Referenced by NI_write_element().

00887 {
00888    return (name_mode == NI_NAMEMODE_ALIAS) ? NI_rowtype_code_to_alias(code)
00889                                            : NI_rowtype_code_to_name (code) ;
00890 }

int NI_write_element NI_stream_type   ns,
void *    nini,
int    tmode
 

Write an element (data or group) to a stream. Return value is number of bytes written to the stream. If return is -1, something bad happened. You should then check the stream with NI_stream_goodcheck(), for example.

If the stream is temporarily unable to write (e.g., the socket buffer is full), then this function will wait until it is ready. If you don't want that behavior, you should use NI_stream_writecheck() before calling this function. --------------------------------------------------------------------------

Definition at line 904 of file niml_elemio.c.

References att_len, NI_element::attr_lhs, NI_group::attr_lhs, NI_procins::attr_lhs, NI_element::attr_num, NI_group::attr_num, NI_procins::attr_num, NI_element::attr_rhs, NI_group::attr_rhs, NI_procins::attr_rhs, NI_stream_type::bad, cbuf, NI_element::name, NI_group::name, NI_procins::name, NI_BASE64_MODE, NI_BINARY_MODE, NI_byteorder(), NI_dpr(), NI_ELEMENT_TYPE, NI_element_type(), NI_free, NI_GROUP_TYPE, NI_has_String(), NI_HEADERONLY_FLAG, NI_HEADERSHARP_FLAG, NI_is_name(), NI_LSB_FIRST, NI_malloc, NI_PROCINS_TYPE, NI_realloc, NI_rowtype_find_code(), NI_set_attribute(), NI_size_column(), NI_stream_goodcheck(), NI_stream_write(), NI_stream_writeable(), NI_stream_writecheck(), NI_stream_writestring(), NI_STRING_TYPE, NI_strlen(), NI_TEXT_MODE, NI_type_name(), NI_write_columns(), NI_element::outmode, NI_group::outmode, NI_group::part, NI_group::part_num, quotize_float_vector(), quotize_int_vector(), quotize_string(), quotize_string_vector(), tt, NI_stream_type::type, NI_element::vec, NI_element::vec_axis_delta, NI_element::vec_axis_label, NI_element::vec_axis_len, NI_element::vec_axis_origin, NI_element::vec_axis_unit, NI_element::vec_len, NI_element::vec_num, NI_element::vec_rank, and NI_element::vec_typ.

Referenced by AFNI_niml_redisplay_CB(), AFNI_niml_viewpoint_CB(), AFNI_version_check(), Dtable_to_nimlstring(), DWI_NIML_create_graph(), main(), nifti_set_afni_extension(), NIML_to_stderr(), SUMA_DsetInfo(), SUMA_Engine(), SUMA_FakeIt(), SUMA_nel_stdout(), SUMA_Paint_SO_ROIplanes_w(), SUMA_SaveVisualState(), SUMA_SendDset_Afni(), SUMA_SendToSuma(), SUMA_ShowNel(), SUMA_Write_DrawnROI_NIML(), THD_write_nimlatr(), v2s_write_outfile_niml(), and XSAVE_output().

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 ;  /* base64 stuff */
00911    int   bb=0 ,  cc=0 ;
00912 
00913    char *att_prefix , *att_equals , *att_trail ;
00914    int header_only , header_sharp , outmode ;
00915 
00916    /*--- 09 Mar 2005: outmode overrided tmode, if present ---*/
00917 
00918    switch( tt ){
00919      default: return -1 ;    /* bad input! */
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:{       /* 16 Mar 2005 */
00934        outmode = NI_TEXT_MODE ;
00935      }
00936      break ;
00937    }
00938    if( outmode >= 0 ) tmode = outmode ;
00939 
00940    /*--- determine special cases from the flags above bit #7 ---*/
00941 
00942    header_only  = ((tmode & NI_HEADERONLY_FLAG ) != 0) ;  /* 20 Feb 2003 */
00943    header_sharp = ((tmode & NI_HEADERSHARP_FLAG) != 0) ;  /* 20 Mar 2003 */
00944 
00945    /* ADDOUT = after writing, add byte count if OK, else quit */
00946    /* AF     = thing to do if ADDOUT is quitting */
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 ;  /* stupid user */
00957 
00958    if( ns->bad ){                        /* socket that hasn't connected yet */
00959 #ifdef NIML_DEBUG
00960 NI_dpr("NI_write_element: write socket not connected\n") ;
00961 #endif
00962       jj = NI_stream_goodcheck(ns,666) ; /* try to connect it */
00963       if( jj < 1 ) return jj ;           /* 0 is nothing yet, -1 is death */
00964 #ifdef NIML_DEBUG
00965 NI_dpr("NI_write_element: write socket now connected\n") ;
00966 #endif
00967    } else {                              /* check if good ns has gone bad */
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 )      /* string output only in text mode */
00974       tmode = NI_TEXT_MODE ;
00975 
00976    if( tmode != NI_TEXT_MODE ) header_sharp = 0 ;  /* 20 Mar 2003 */
00977 
00978    /*-- 15 Oct 2002: write attributes with lots of space, or little --*/
00979    /*-- 20 Mar 2003: modified for "#  lhs = rhs" type of header     --*/
00980 
00981    att_prefix = (header_sharp) ? (char *)"\n#  " /* write this before each attribute */
00982                                : (char *)"\n  " ;
00983 
00984    att_equals = (header_sharp) ? (char *)" = "   /* write this between lhs and rhs */
00985                                : (char *)"="    ;
00986 
00987    att_trail  = (header_sharp) ? (char *)"\n# "  /* write this before closing ">" */
00988                                : (char *)" "    ;
00989 
00990    /*------------------ write a processing instruction ------------------*/
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      /*- attributes -*/
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 ;   /*** done with processing instruction ***/
01024 
01025    /*------------------ write a group element ------------------*/
01026 
01027    } else if( tt == NI_GROUP_TYPE ){
01028 
01029       NI_group *ngr = (NI_group *) nini ;
01030       char *gname ;
01031 
01032       /* 24 Feb 2005: all group elements used to be named "ni_group",
01033                       but no more; now they have attribute ni_form="ni_group" */
01034 
01035       gname = ngr->name ;
01036       if( gname == NULL || *gname == '\0' ) gname = "ni_group" ;
01037 
01038       /*- group header -*/
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       /*- attributes -*/
01049 
01050       NI_set_attribute( ngr , "ni_form" , "ni_group" ) ;  /* 24 Feb 2005 */
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       /*- close group header -*/
01071 
01072       nout = NI_stream_writestring( ns , att_trail ) ; ADDOUT ;
01073       nout = NI_stream_writestring( ns , ">\n" ) ; ADDOUT ;
01074 
01075       /*- write the group parts (recursively) -*/
01076 
01077       for( ii=0 ; ii < ngr->part_num ; ii++ ){
01078         nout = NI_write_element( ns , ngr->part[ii] , tmode ) ; ADDOUT ;
01079       }
01080 
01081       /*- group trailer -*/
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 ;   /*** done with group element ***/
01093 
01094    /*------------------ write a data element ------------------*/
01095 
01096    } else if( tt == NI_ELEMENT_TYPE ){
01097 
01098       NI_element *nel = (NI_element *) nini ;
01099 
01100       /*- sanity check (should never fail) -*/
01101 
01102       jj = NI_strlen(nel->name) ; if( jj == 0 ) return -1 ;
01103 
01104       /*- select the data output mode -*/
01105 
01106       /* Strings can only be written in text mode */
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       /* space to hold attribute strings */
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)  /* free att if we have to quit early now */
01130 
01131       /* write start of header "<name" */
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       /*- write "special" attributes, if not an empty element -*/
01138 
01139       if( nel->vec_len > 0 && nel->vec_num > 0 ){
01140          int ll , tt ;
01141 
01142          /* ni_form (depends on tmode) */
01143 
01144          switch( tmode ){
01145            default:
01146            case NI_TEXT_MODE:
01147              *att = '\0' ;   /* text form is default */
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          /** do ni_type **/
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 ){  /* not the previous type */
01167              if( ll >= 0 ){              /* write the previous type out now */
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] ;     /* save new type code */
01173              jj = 1 ;                    /* it now has count 1 */
01174 
01175           } else {                       /* same as previous type */
01176              jj++ ;                      /* so add 1 to its count */
01177           }
01178          }
01179          /* write the last type we found */
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          /** do ni_dimen **/
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          /** 26 Mar 2003: write number of bytes of data contained herein **/
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          /* extras: ni_veclen and ni_vecnum attributes */
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          /* ni_delta */
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          /* ni_origin */
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          /* ni_units */
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          /* ni_axes */
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       /*- other attributes -*/
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          /* skip "special" attributes */
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 ; /* 13 Apr 2004 */
01277 
01278          kk = NI_strlen( nel->attr_rhs[ii] ) ;
01279 
01280          /* do the work */
01281 
01282          if( jj+kk+128 > att_len ){                 /* 13 Jun 2003 */
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]) ){           /* the 'normal' case */
01290            strcat(att,nel->attr_lhs[ii]) ;
01291          } else {                                        /* not legal in XML */
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] ) ; /* RHS always quoted */
01299             strcat(att,qtt) ; NI_free(qtt) ;
01300          }
01301          nout = NI_stream_writestring( ns , att ) ; ADDOUT ;
01302       }
01303 
01304       NI_free(att) ; att = NULL ; /* done with attributes */
01305 
01306 #undef  AF
01307 #define AF 0  /* nothing to do if we have to quit early */
01308 
01309       /*- close header -*/
01310 
01311       if( nel->vec_len == 0    ||     /* An 'empty' element (no data) */
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 ;                 /*** done with empty data element ***/
01323       }
01324 
01325       /*- if here, must write some data out -*/
01326 
01327       /* first, terminate the header,
01328          and allocate space for the write buffer (1 row at a time) */
01329 
01330       switch( tmode ){
01331          default:
01332          case NI_TEXT_MODE:
01333             btt = ">\n" ;                             /* add a newline */
01334          break ;
01335 
01336          case NI_BINARY_MODE:
01337             btt = ">" ;                               /* no newline   */
01338          break ;
01339 
01340          case NI_BASE64_MODE:
01341             btt = ">\n" ;                             /* add a newline */
01342          break ;
01343       }
01344 
01345       nout = NI_stream_writestring( ns , att_trail ) ; ADDOUT ;
01346       nout = NI_stream_writestring( ns , btt ) ; ADDOUT ;
01347 
01348       /*-- 13 Feb 2003: data output is now done elsewhere --*/
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       /*- write element trailer -*/
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 ;   /*** done with full data element ***/
01370 
01371    } /* end of write data element */
01372 
01373    return -1 ; /* should never be reachable */
01374 }

int NI_write_procins NI_stream_type   ns,
char *    str
 

Write a simple processing instruction to the stream:

  • "<?str ?>
    " will be written
  • Return value is the number of bytes written
  • Return 0 means that the stream wasn't ready to write
  • Return -1 means an error happened, and nothing was written
  • 17 Mar 2005 - RWCox ----------------------------------------------------------------------

Definition at line 45 of file niml_elemio.c.

References NI_stream_type::bad, free, IS_STRING_CHAR, malloc, NI_stream_goodcheck(), NI_stream_writeable(), NI_stream_writecheck(), and NI_stream_writestring().

Referenced by main(), and SUMA_SendDset_Afni().

00046 {
00047    char *buf ; int jj ;
00048 
00049    /* check inputs for good-ositifulness */
00050 
00051    if( !NI_stream_writeable(ns)             ) return -1 ;  /* stupid user */
00052    if( str == NULL || !IS_STRING_CHAR(*str) ) return -1 ;
00053 
00054    /* check if stream is ready to take data */
00055 
00056    if( ns->bad ){                       /* socket that hasn't connected yet */
00057      jj = NI_stream_goodcheck(ns,666) ; /* try to connect it */
00058      if( jj < 1 ) return jj ;           /* 0 is nothing yet, -1 is death */
00059    } else {                             /* check if good ns has gone bad */
00060      jj = NI_stream_writecheck(ns,666) ;
00061      if( jj < 0 ) return jj ;
00062    }
00063 
00064    /* write the processing instruction: "<?str ?>\n" */
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 }

int scan_for_angles NI_stream_type   ns,
int    msec
[static]
 

Scan stream for an element header or trailer:'<characters>', starting at byte offset ns->npos, and waiting msec milliseconds.

Returns with the stream buffer set so that the opening '<' is at ns->buf[ns->npos] and the closing '>' is at ns->buf[q-1], where q is this function's return value. Note that read operations may change ns->npos from its value when this function was called.

If the return value is -1, then we couldn't find a '<stuff>' string. This may be due to:

  • there is no '<...>' in the buffer, and we can't read from the input stream; call NI_readcheck(ns,0) to confirm this
  • time ran out (alas)
  • The '<...' part filled the entire buffer space. In this case, all the input buffer is thrown away - we don't support headers or trailers this long!
01 Jun 2005: skip XML comments, which are of the form "". ------------------------------------------------------------------------

Definition at line 750 of file niml_elemio.c.

References NI_stream_type::bad, NI_stream_type::buf, NI_stream_type::bufsize, free, malloc, MARKED_FOR_DEATH, NI_stream_type::nbuf, NI_clock_time(), NI_reset_buffer(), NI_stream_fillbuf(), and NI_stream_type::npos.

Referenced by NI_read_element().

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 ;  /* 1 => force rescan even if time is up */
00756 
00757    if( ns == NULL ) return -1 ;  /* bad input */
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 ;   /* a long time (11+ days) */
00764 
00765    /*-- Will loop back here if we have to re-read/re-scan --*/
00766 
00767    goal        = '<' ;  /* first goal is opening '<' (second goal is '>') */
00768    num_restart = 0   ;
00769 Restart:                                       /* loop back here to retry */
00770    num_restart++ ;
00771    mleft = msec - (NI_clock_time()-start_time) ;             /* time left */
00772 
00773    if( num_restart > 3 && mleft <= 0 && !caseb ){              /* failure */
00774       NI_reset_buffer(ns) ;                            /* and out of time */
00775       return -1 ;
00776    }
00777 
00778    /*-- scan ahead to find goal character in the buffer --*/
00779 
00780    while( epos < ns->nbuf && ns->buf[epos] != goal ) epos++ ;
00781 
00782    /*-- if we found our goal, do something about it --*/
00783 
00784    if( epos < ns->nbuf ){
00785 
00786      /*-- if our goal was the closing '>', we are done! (maybe) --*/
00787 
00788      if( goal == '>' ){
00789 
00790        /*- 01 Jun 2005: see if we are at a comment; if so, must start over -*/
00791 
00792        if( epos - ns->npos >= 4 && strncmp(ns->buf+ns->npos,"<!--",4) == 0 ){
00793 
00794          if( strncmp(ns->buf+epos-2,"-->",3) == 0 ){  /* got a full comment */
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) ;  /* skip it & try again */
00804            epos = 0 ; goal = '<' ;
00805          } else {                              /* '>' doesn't close comment! */
00806            epos++ ;                            /* so look for another one!!! */
00807          }
00808          caseb = 1 ; goto Restart ;
00809        }
00810 
00811        /*** not a comment, so we can exit triumphantly! ***/
00812 
00813        return epos+1 ;  /* marks the character after '>' */
00814      }
00815 
00816      /*-- if here, our goal was the opening '<';
00817           set the buffer position to this location,
00818           set the new goal, and scan for the new goal --*/
00819 
00820       ns->npos = epos ;  /* mark where we found '<' */
00821       goal     = '>'  ;  /* the new goal */
00822       caseb    = 1    ;  /* force rescan, even if time is up */
00823       goto Restart    ;  /* scan again! */
00824    }
00825 
00826    /*-- if we get to here, we didn't find our goal:
00827         (a) if the goal was the opening '<', then throw
00828              away all data in the buffer, and get some more data
00829         (b) if the goal was the closing '>', then we need more data
00830             in the buffer, but need to keep the existing data
00831         (c) UNLESS the buffer is full AND npos is zero
00832              - in this case, the universe ends right here and now --*/
00833 
00834    if( goal == '<' ){                    /* case (a) */
00835 
00836       ns->nbuf = ns->npos = epos = 0 ; caseb = 0 ;
00837 
00838    } else if( ns->nbuf < ns->bufsize || ns->npos > 0 ){  /* case (b) */
00839 
00840       NI_reset_buffer(ns) ; epos = ns->nbuf ; caseb = 1 ;
00841 
00842    } else {                              /* case (c) */
00843 
00844       ns->nbuf = 0 ; return -1 ;         /* death of Universe! */
00845    }
00846 
00847    /*-- if we are here, we need more data before scanning again --*/
00848 
00849    /*-- read at least nbmin bytes,
00850         waiting up to mleft ms (unless the data stream goes bad) --*/
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 ;    /* got new data => force rescan */
00858 
00859    if( nn >= 0     ) goto Restart ; /* scan some more for the goal */
00860 
00861    /*-- if here, the stream went bad, so exit --*/
00862 
00863    ns->nbuf = ns->npos = 0 ; return -1 ;
00864 }

Variable Documentation

int name_mode = NI_NAMEMODE_NORMAL [static]
 

Mode for writing names.

Definition at line 869 of file niml_elemio.c.

Referenced by NI_set_typename_mode(), and NI_type_name().

int read_header_only = 0 [static]
 

Definition at line 76 of file niml_elemio.c.

Referenced by NI_read_element(), NI_read_element_header(), and NI_read_header_only().

int skip_procins = 0 [static]
 

Definition at line 79 of file niml_elemio.c.

Referenced by NI_skip_procins().

 

Powered by Plone

This site conforms to the following standards: