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_util.c

Go to the documentation of this file.
00001 #include "niml_private.h"
00002 
00003 /****************************************************************************/
00004 /************* Debugging function *******************************************/
00005 /****************************************************************************/
00006 
00007 FILE *dfp = NULL ;                  /* debug file pointer */
00008 
00009 void NI_dpr( char *fmt , ... )      /* print debug stuff */
00010 {
00011   va_list vararg_ptr ;
00012   char *nms ;
00013   if( dfp == NULL ) return ;        /* printing turned off? */
00014   va_start( vararg_ptr , fmt ) ;
00015   vfprintf(dfp,fmt,vararg_ptr) ;    /* do printing */
00016 
00017   nms = NI_malloc_status() ;        /* 18 Nov 2002 */
00018   if( nms != NULL ) fprintf(dfp,"     NI_malloc status: %s\n",nms) ;
00019 
00020   fflush(dfp); va_end(vararg_ptr);  /* cleanup */
00021 }
00022 
00023 /****************************************************************************/
00024 /*********************** NIML Utility functions *****************************/
00025 /****************************************************************************/
00026 
00027 /*--------------------------------------------------------------------------*/
00028 /*! Return the file length (-1 if file not found).
00029 ----------------------------------------------------------------------------*/
00030 
00031 long NI_filesize( char *pathname )
00032 {
00033    static struct stat buf ; int ii ;
00034 
00035    if( pathname == NULL ) return -1 ;
00036    ii = stat( pathname , &buf ) ; if( ii != 0 ) return -1 ;
00037    return buf.st_size ;
00038 }
00039 
00040 /*-------------------------------------------------------------------*/
00041 /*!  Sleep a given # of milliseconds (uses the Unix select routine).
00042 ---------------------------------------------------------------------*/
00043 
00044 void NI_sleep( int msec )
00045 {
00046    struct timeval tv ;
00047    if( msec <= 0 ) return ;             /* can't wait into the past */
00048    tv.tv_sec  = msec/1000 ;
00049    tv.tv_usec = (msec%1000)*1000 ;
00050    select( 1 , NULL,NULL,NULL , &tv ) ;
00051    return ;
00052 }
00053 
00054 /*---------------------------------------------------------------*/
00055 /*! Return time elapsed since first call to this routine (msec).
00056 
00057     Note this will overflow an int after 24+ days.  You probably
00058     don't want to use this if the program will be running
00059     continuously for such a long time.
00060 -----------------------------------------------------------------*/
00061 
00062 int NI_clock_time(void)
00063 {
00064    struct timeval  new_tval ;
00065    struct timezone tzone ;
00066    static struct timeval old_tval ;
00067    static int first = 1 ;
00068 
00069    gettimeofday( &new_tval , &tzone ) ;
00070 
00071    if( first ){
00072       old_tval = new_tval ;
00073       first    = 0 ;
00074       return 0 ;
00075    }
00076 
00077    if( old_tval.tv_usec > new_tval.tv_usec ){
00078       new_tval.tv_usec += 1000000 ;
00079       new_tval.tv_sec -- ;
00080    }
00081 
00082    return (int)( (new_tval.tv_sec  - old_tval.tv_sec )*1000.0
00083                 +(new_tval.tv_usec - old_tval.tv_usec)*0.001 + 0.5 ) ;
00084 }
00085 
00086 /*---------------------------------------------------------------------------*/
00087 /*! Replacement for mktemp(). */
00088 
00089 char * NI_mktemp( char *templ )
00090 {
00091    int nt ; char *xx,*uu ; struct stat buf ;
00092 
00093    if( templ == NULL || templ[0] == '\0' ) return NULL ;
00094 
00095    nt = strlen(templ) ;
00096    if( nt < 6 ){ templ[0] = '\0'; return NULL; }
00097    xx = templ+(nt-6) ;
00098    if( strcmp(xx,"XXXXXX") != 0 ){ templ[0] = '\0'; return NULL; }
00099 
00100    while(1){
00101      uu = UUID_idcode() ;
00102      memcpy( xx , uu , 6 ) ;
00103      nt = stat( templ , &buf ) ;
00104      if( nt != 0 ) return templ ;
00105    }
00106 }
00107 
00108 /*************************************************************************/
00109 /****************** NIML string utilities ********************************/
00110 /*************************************************************************/
00111 
00112 /*--------------------------------------------------------------------------*/
00113 /*! Like strncpy, but better (result always ends in NUL char).
00114 
00115     If dest is NULL, does nothing.  If src is NULL, put a NUL char
00116     in dest[0].
00117 ----------------------------------------------------------------------------*/
00118 
00119 char * NI_strncpy( char *dest , const char *src , size_t n )
00120 {
00121    if( dest == NULL || n == 0 ) return NULL ;
00122    if( src  == NULL || n == 1 ){ dest[0] = '\0' ; return dest ; }
00123    strncpy( dest , src , n-1 ) ;
00124    dest[n-1] = '\0' ; return dest ;
00125 }
00126 
00127 /*------------------------------------------------------------------------*/
00128 /*! Like strlen, but better (input=NULL ==> output=0).
00129 --------------------------------------------------------------------------*/
00130 
00131 int NI_strlen( char *str )
00132 {
00133    if( str == NULL ) return 0 ;
00134    return strlen(str) ;
00135 }
00136 
00137 /*------------------------------------------------------------------------*/
00138 /*! Like strdup, but better (input=NULL ==> output=NULL).
00139 --------------------------------------------------------------------------*/
00140 
00141 char * NI_strdup( char *str )
00142 {
00143    int nn ; char *dup ;
00144    if( str == NULL ) return NULL ;
00145    nn = NI_strlen(str); dup = NI_malloc(char, nn+1); strcpy(dup,str); return dup;
00146 }
00147 
00148 /*------------------------------------------------------------------------*/
00149 /*! Find a string in an array of strings; return index (-1 if not found).
00150 --------------------------------------------------------------------------*/
00151 
00152 int string_index( char *targ, int nstr, char *str[] )
00153 {
00154    int ii ;
00155 
00156    if( nstr < 1 || str == NULL || targ == NULL ) return -1 ;
00157 
00158    for( ii=0 ; ii < nstr ; ii++ )
00159      if( str[ii] != NULL && strcmp(str[ii],targ) == 0 ) return ii ;
00160 
00161    return -1 ;
00162 }
00163 
00164 /*------------------------------------------------------------------------*/
00165 /*! Un-escape a C string inplace.  (This can be done since the replacement
00166     is always smaller than the input.)  Escapes recognized are:
00167       -  &lt;   ->  <
00168       -  &gt;   ->  >
00169       -  &quot; ->  "
00170       -  &apos; ->  '
00171       -  &amp;  ->  &
00172     Also replace CR LF pair (Microsoft), or CR alone (Macintosh) with
00173     LF (Unix), per the XML standard.
00174     Return value is number of replacements made.
00175 --------------------------------------------------------------------------*/
00176 
00177 #undef  CR
00178 #undef  LF
00179 #define CR 0x0D
00180 #define LF 0x0A
00181 
00182 int unescape_inplace( char *str )
00183 {
00184    int ii,jj , nn,ll ;
00185 
00186    if( str == NULL ) return 0 ;                /* no string? */
00187    ll = NI_strlen(str) ;
00188 
00189    /* scan for escapes: &something; */
00190 
00191    for( ii=jj=nn=0 ; ii<ll ; ii++,jj++ ){ /* scan at ii; put results in at jj */
00192 
00193       if( str[ii] == '&' ){  /* start of escape? */
00194 
00195               if( ii+3 < ll        &&   /* &lt; */
00196                   str[ii+1] == 'l' &&
00197                   str[ii+2] == 't' &&
00198                   str[ii+3] == ';'   ){ str[jj] = '<' ; ii += 3 ; nn++ ; }
00199 
00200          else if( ii+3 < ll        &&   /* &gt; */
00201                   str[ii+1] == 'g' &&
00202                   str[ii+2] == 't' &&
00203                   str[ii+3] == ';'   ){ str[jj] = '>' ; ii += 3 ; nn++ ; }
00204 
00205          else if( ii+5 < ll        &&   /* &quot; */
00206                   str[ii+1] == 'q' &&
00207                   str[ii+2] == 'u' &&
00208                   str[ii+3] == 'o' &&
00209                   str[ii+4] == 't' &&
00210                   str[ii+5] == ';'   ){ str[jj] = '"' ; ii += 5 ; nn++ ; }
00211 
00212          else if( ii+5 < ll        &&   /* &apos; */
00213                   str[ii+1] == 'a' &&
00214                   str[ii+2] == 'p' &&
00215                   str[ii+3] == 'o' &&
00216                   str[ii+4] == 's' &&
00217                   str[ii+5] == ';'   ){ str[jj] = '\'' ; ii += 5 ; nn++ ; }
00218 
00219          else if( ii+4 < ll        &&  /* &amp; */
00220                   str[ii+1] == 'a' &&
00221                   str[ii+2] == 'm' &&
00222                   str[ii+3] == 'p' &&
00223                   str[ii+4] == ';'   ){ str[jj] = '&' ; ii += 4 ; nn++ ; }
00224 
00225          /* although the comments above don't mention it,
00226             we also look for XML style numeric escapes
00227             of the forms &#32; (decimal) and &#xfd; (hex) */
00228 
00229          else if( ii+3 < ll        &&
00230                   str[ii+1] == '#' &&
00231                   isdigit(str[ii+2]) ){   /* &#dec; */
00232 
00233             unsigned int val='?' ; int kk=ii+3 ;
00234             while( kk < ll && str[kk] != ';' ) kk++ ;
00235             sscanf( str+ii+2 , "%u" , &val ) ;
00236             str[jj] = (char) val ; ii = kk ; nn++ ;
00237          }
00238 
00239          else if( ii+4 < ll        &&
00240                   str[ii+1] == '#' &&
00241                   str[ii+2] == 'x' &&
00242                   isxdigit(str[ii+3]) ){   /* &#hex; */
00243 
00244             unsigned int val='?' ; int kk=ii+4 ;
00245             while( kk < ll && str[kk] != ';' ) kk++ ;
00246             sscanf( str+ii+3 , "%x" , &val ) ;
00247             str[jj] = (char) val ; ii = kk ; nn++ ;
00248          }
00249 
00250          /* didn't start a recognized escape, so just copy as normal */
00251 
00252          else if( jj < ii ){ str[jj] = str[ii] ; }
00253 
00254       } else if( str[ii] == CR ) {  /* is a carriage return */
00255 
00256          if( str[ii+1] == LF ){ str[jj] = LF ; ii++ ; nn++ ; }  /* CR LF */
00257          else                 { str[jj] = LF ;      ; nn++ ; }  /* CR only */
00258 
00259       } else { /* is a normal character, just copy to output */
00260 
00261               if( jj < ii ){ str[jj] = str[ii] ; }
00262       }
00263 
00264       /* at this point, ii=index of last character used up in scan
00265                         jj=index of last character written to (jj <= ii) */
00266 
00267    } /* end of loop scanning over input/output string */
00268 
00269    if( jj < ll ) str[jj] = '\0' ; /* end string properly */
00270 
00271    return nn ;
00272 }
00273 
00274 /*------------------------------------------------------------------------*/
00275 /*! Quotize (and escapize) one string, returning a new string.
00276     Approximately speaking, this is the inverse of unescape_inplace().
00277 --------------------------------------------------------------------------*/
00278 
00279 char * quotize_string( char *str )
00280 {
00281    int ii,jj , lstr,lout ;
00282    char *out ;
00283 
00284    lstr = NI_strlen(str) ;
00285    if( lstr == 0 ){ out = NI_malloc(char, 4); strcpy(out,"\"\""); return out; }
00286    lout = 4 ;                      /* length of output */
00287    for( ii=0 ; ii < lstr ; ii++ ){ /* count characters for output */
00288       switch( str[ii] ){
00289          case '&':  lout += 5 ; break ;  /* replace '&' with "&amp;" */
00290 
00291          case '<':
00292          case '>':  lout += 4 ; break ;  /* replace '<' with "&lt;" */
00293 
00294          case '"' :
00295          case '\'': lout += 6 ; break ;  /* replace '"' with "&quot;" */
00296 
00297          case CR:
00298          case LF:   lout += 6 ; break ;  /* replace CR with "&#x0d;"
00299                                                     LF with "&#x0a;" */
00300 
00301          default: lout++ ; break ;      /* copy all other chars */
00302       }
00303    }
00304    out = NI_malloc(char, lout) ;              /* allocate output string */
00305    out[0] = '"' ;                       /* opening quote mark */
00306    for( ii=0,jj=1 ; ii < lstr ; ii++ ){
00307       switch( str[ii] ){
00308          default: out[jj++] = str[ii] ; break ;  /* normal characters */
00309 
00310          case '&':  memcpy(out+jj,"&amp;",5)  ; jj+=5 ; break ;
00311 
00312          case '<':  memcpy(out+jj,"&lt;",4)   ; jj+=4 ; break ;
00313          case '>':  memcpy(out+jj,"&gt;",4)   ; jj+=4 ; break ;
00314 
00315          case '"' : memcpy(out+jj,"&quot;",6) ; jj+=6 ; break ;
00316 
00317          case '\'': memcpy(out+jj,"&apos;",6) ; jj+=6 ; break ;
00318 
00319          case CR:   memcpy(out+jj,"&#x0d;",6) ; jj+=6 ; break ;  /* 15 Oct 2002 */
00320          case LF:   memcpy(out+jj,"&#x0a;",6) ; jj+=6 ; break ;
00321       }
00322    }
00323    out[jj++] = '"'  ;  /* closing quote mark */
00324    out[jj]   = '\0' ;  /* terminate the string */
00325    return out ;
00326 }
00327 
00328 /*------------------------------------------------------------------------*/
00329 /*! Quotize an array of strings into one string,
00330     separating substrings with sep (setting sep=0 means use commas).
00331 --------------------------------------------------------------------------*/
00332 
00333 char * quotize_string_vector( int num , char **str , char sep )
00334 {
00335    char *out , **qstr ;
00336    int ii , ntot , ll,nn ;
00337 
00338    /* handle special cases */
00339 
00340    if( num <= 0 || str == NULL )
00341       return quotize_string(NULL) ;      /* will be string of 2 quotes */
00342 
00343    if( num == 1 )
00344       return quotize_string( str[0] ) ;  /* just quotize the only string */
00345 
00346    /* default separator */
00347 
00348    if( sep == '\0' ) sep = ',' ;
00349 
00350    /* temp array for quotized individual sub-strings */
00351 
00352    qstr = NI_malloc(char*, sizeof(char *)*num) ;
00353 
00354    for( ntot=ii=0 ; ii < num ; ii++ ){       /* quotize each input string */
00355       qstr[ii] = quotize_string( str[ii] ) ;
00356       ntot += NI_strlen( qstr[ii] ) ;      /* length of all quotized strings */
00357    }
00358 
00359    /* make output, put 1st sub-string into it */
00360 
00361    out = NI_malloc(char, ntot) ;
00362    strcpy( out , qstr[0] ) ; NI_free(qstr[0]) ;
00363    for( ii=1 ; ii < num ; ii++ ){
00364       ll = strlen(out) ;  /* put separator at end of output string, */
00365       out[ll-1] = sep ;   /* in place of the closing " mark.       */
00366 
00367       strcat(out,qstr[ii]+1) ;  /* catenate with next sub-string, */
00368                                 /* but skip the opening " mark.  */
00369       NI_free(qstr[ii]) ;       /* toss the quotized trash */
00370    }
00371 
00372    NI_free(qstr) ; return out ;
00373 }
00374 
00375 /*------------------------------------------------------------------------*/
00376 /*! Quotize a bunch of ints int a string like "1,32,-12".
00377 --------------------------------------------------------------------------*/
00378 
00379 char * quotize_int_vector( int num , int *vec , char sep )
00380 {
00381    int ii , jj ;
00382    char *out , **qstr ;
00383 
00384    if( num <= 0 || vec == NULL )
00385       return quotize_string(NULL) ;
00386 
00387    qstr = NI_malloc(char*, sizeof(char *)*num) ;  /* temp array of strings */
00388    for( ii=0 ; ii < num ; ii++ ){
00389       qstr[ii] = NI_malloc(char, 16) ;           /* max size of printed int */
00390       sprintf(qstr[ii],"%d",vec[ii]) ;               /* print int */
00391       for( jj=strlen(qstr[ii])-1 ;                   /* clip */
00392            jj > 0 && isspace(qstr[ii][jj]) ; jj-- )  /* trailing */
00393         qstr[ii][jj] = '\0' ;                        /* blanks */
00394    }
00395 
00396    out = quotize_string_vector( num , qstr , sep ) ;
00397 
00398    for( ii=0 ; ii < num ; ii++ ) NI_free(qstr[ii]) ;
00399 
00400    NI_free(qstr) ; return out ;
00401 }
00402 
00403 /*------------------------------------------------------------------------*/
00404 /*! Quotize a bunch of floats into a string like "-2.71828,3.1416,1.111".
00405 --------------------------------------------------------------------------*/
00406 
00407 char * quotize_float_vector( int num , float *vec , char sep )
00408 {
00409    int ii , jj , ff ;
00410    char *out , **qstr , fbuf[32] ;
00411 
00412    if( num <= 0 || vec == NULL )
00413       return quotize_string(NULL) ;
00414 
00415    qstr = NI_malloc(char*, sizeof(char *)*num) ;
00416    for( ii=0 ; ii < num ; ii++ ){
00417       sprintf(fbuf," %12.6g",vec[ii]) ;
00418       for( ff=strlen(fbuf) ; fbuf[ff]==' ' ; ff-- ) /* skip trailing blanks */
00419         fbuf[ff] = '\0' ;
00420       for( ff=0 ; fbuf[ff] == ' ' ; ff++ ) ;         /* skip leading blanks */
00421       qstr[ii] = NI_strdup(fbuf+ff) ;              /* array of temp strings */
00422    }
00423 
00424    out = quotize_string_vector( num , qstr , sep ) ;
00425 
00426    for( ii=0 ; ii < num ; ii++ ) NI_free(qstr[ii]) ;
00427 
00428    NI_free(qstr) ; return out ;
00429 }
00430 
00431 /*------------------------------------------------------------------------*/
00432 /*! Check a string for 'nameness' - that is, consists only of legal
00433     characters for a NIML 'Name' and also starts with an alphabetic
00434     character.  Returns 1 if it is a Name and 0 if is not.
00435 --------------------------------------------------------------------------*/
00436 
00437 int NI_is_name( char *str )
00438 {
00439    int ii , ll ;
00440 
00441    if( str == NULL || str[0] == '\0' || !isalpha(str[0]) ) return 0 ;
00442 
00443    for( ii=1 ; str[ii] != '\0' ; ii++ )
00444      if( !IS_NAME_CHAR(str[ii]) ) return 0 ; /* this one is bad */
00445 
00446    return 1 ;                      /* all were good ==> success */
00447 }
00448 
00449 /*------------------------------------------------------------------------*/
00450 /*! Find a trailing name in a pathname.
00451 
00452    For example, for fname = "/bob/cox/is/the/author/of/NIML",
00453      - the lev=0 trailing name is "NIML",
00454      - the lev=1 trailing name is "of/NIML",
00455      - the lev=2 trailing name is "author/of/NIML", and so on.
00456    That is, "lev" is the number of directory names above the last name
00457    to keep.  The pointer returned is to some place in the middle of fname;
00458    that is, this is not a malloc()-ed string, so don't try to free() it!.
00459 --------------------------------------------------------------------------*/
00460 
00461 char * trailname( char *fname , int lev )
00462 {
00463    int fpos , flen , flev ;
00464 
00465    if( fname == NULL || (flen=strlen(fname)) <= 1 ) return fname ;
00466 
00467    if( lev < 0 ) lev = 0 ;
00468 
00469    flev = 0 ;
00470    fpos = flen ;
00471    if( fname[fpos-1] == '/' ) fpos-- ;  /* skip trailing slash */
00472 
00473    /* fpos   = index of latest character I've accepted,
00474       fpos-1 = index of next character to examine,
00475       flev   = number of directory levels found so far */
00476 
00477    while( fpos > 0 ){
00478 
00479       if( fname[fpos-1] == '/' ){
00480          flev++ ; if( flev >  lev ) break ;  /* reached the lev we like */
00481       }
00482       fpos-- ;  /* scan backwards */
00483    }
00484 
00485    return (fname+fpos) ;
00486 }
 

Powered by Plone

This site conforms to the following standards: