root/ompi/mca/io/romio321/romio/adio/common/strfns.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ADIOI_Strncpy
  2. ADIOI_Strnapp
  3. ADIOI_Strdup
  4. ADIOI_Snprintf

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
   2 /* 
   3  *
   4  *   Copyright (C) 1997 University of Chicago. 
   5  *   See COPYRIGHT notice in top-level directory.
   6  */
   7 
   8 #include "adio.h"
   9 
  10 /* style: allow:sprintf:3 sig:0 */
  11 
  12 /* 
  13  * Below are the "safe" versions of the various string and printf
  14  * operations. They are directly taken from MPICH, with MPIU replaced by ADIOI.
  15  */
  16 
  17 /*
  18  * ADIOI_Strncpy - Copy at most n character.  Stop once a null is reached.
  19  *
  20  * This is different from strncpy, which null pads so that exactly
  21  * n characters are copied.  The strncpy behavior is correct for many 
  22  * applications because it guarantees that the string has no uninitialized
  23  * data.
  24  *
  25  * If n characters are copied without reaching a null, return an error.
  26  * Otherwise, return 0.
  27  *
  28  */
  29 /*@ ADIOI_Strncpy - Copy a string with a maximum length
  30   
  31 Input Parameters:
  32 +   instr - String to copy
  33 -   maxlen - Maximum total length of 'outstr'
  34 
  35 Output Parameters:
  36 .   outstr - String to copy into
  37 
  38     Notes:
  39     This routine is the routine that you wish 'strncpy' was.  In copying 
  40     'instr' to 'outstr', it stops when either the end of 'outstr' (the 
  41     null character) is seen or the maximum length 'maxlen' is reached.
  42     Unlike 'strncpy', it does not add enough nulls to 'outstr' after 
  43     copying 'instr' in order to move precisely 'maxlen' characters.  
  44     Thus, this routine may be used anywhere 'strcpy' is used, without any
  45     performance cost related to large values of 'maxlen'.
  46 
  47   Module:
  48   Utility
  49   @*/
  50 int ADIOI_Strncpy( char *dest, const char *src, size_t n )
  51 {
  52     char * restrict d_ptr = dest;
  53     const char * restrict s_ptr = src;
  54     register int i;
  55 
  56     i = (int)n;
  57     while (*s_ptr && i-- > 0) {
  58         *d_ptr++ = *s_ptr++;
  59     }
  60     
  61     if (i > 0) { 
  62         *d_ptr = 0;
  63         return 0;
  64     }
  65     else
  66         /* We may want to force an error message here, at least in the
  67            debugging version */
  68         return 1;
  69 }
  70 
  71 /* Append src to dest, but only allow dest to contain n characters (including
  72    any null, which is always added to the end of the line */
  73 /*@ ADIOI_Strnapp - Append to a string with a maximum length
  74 
  75 Input Parameters:
  76 +   instr - String to copy
  77 -   maxlen - Maximum total length of 'outstr'
  78 
  79 Output Parameters:
  80 .   outstr - String to copy into
  81 
  82     Notes:
  83     This routine is similar to 'strncat' except that the 'maxlen' argument
  84     is the maximum total length of 'outstr', rather than the maximum 
  85     number of characters to move from 'instr'.  Thus, this routine is
  86     easier to use when the declared size of 'instr' is known.
  87 
  88   Module:
  89   Utility
  90   @*/
  91 int ADIOI_Strnapp( char *dest, const char *src, size_t n )
  92 {
  93     char * restrict d_ptr = dest;
  94     const char * restrict s_ptr = src;
  95     register int i;
  96 
  97     /* Get to the end of dest */
  98     i = (int)n;
  99     while (i-- > 0 && *d_ptr) d_ptr++;
 100     if (i <= 0) return 1;
 101 
 102     /* Append.  d_ptr points at first null and i is remaining space. */
 103     while (*s_ptr && i-- > 0) {
 104         *d_ptr++ = *s_ptr++;
 105     }
 106 
 107     /* We allow i >= (not just >) here because the first while decrements
 108        i by one more than there are characters, leaving room for the null */
 109     if (i >= 0) { 
 110         *d_ptr = 0;
 111         return 0;
 112     }
 113     else {
 114         /* Force the null at the end */
 115         *--d_ptr = 0;
 116     
 117         /* We may want to force an error message here, at least in the
 118            debugging version */
 119         return 1;
 120     }
 121 }
 122 
 123 /*@ 
 124   ADIOI_Strdup - Duplicate a string
 125 
 126   Synopsis:
 127 .vb
 128     char *ADIOI_Strdup( const char *str )
 129 .ve
 130 
 131 Input Parameters:
 132 . str - null-terminated string to duplicate
 133 
 134   Return value:
 135   A pointer to a copy of the string, including the terminating null.  A
 136   null pointer is returned on error, such as out-of-memory.
 137 
 138   Notes:
 139   Like 'ADIOI_Malloc' and 'ADIOI_Free', this will often be implemented as a 
 140   macro but may use 'ADIOI_trstrdup' to provide a tracing version.
 141 
 142   Module:
 143   Utility
 144   @*/
 145 char *ADIOI_Strdup( const char *str )
 146 {
 147     char *p = ADIOI_Malloc( strlen(str) + 1 );
 148     char *in_p = (char *)str;
 149     char *save_p;
 150 
 151     save_p = p;
 152     if (p) {
 153         while (*in_p) {
 154             *p++ = *in_p++;
 155         }
 156         *p = '\0';
 157     }
 158     return save_p;
 159 }
 160 
 161 
 162 /* 
 163  * We need an snprintf replacement for systems without one
 164  */
 165 #ifndef HAVE_SNPRINTF
 166 #include <ctype.h>
 167 /* FIXME: Really need a check for varargs.h vs stdarg.h */
 168 #include <stdarg.h>
 169 /* 
 170  * This is an approximate form which is suitable for most uses within
 171  * the MPICH code
 172  */
 173 int ADIOI_Snprintf( char *str, size_t size, const char *format, ... )
 174 {
 175     int n;
 176     const char *p;
 177     char *out_str = str;
 178     va_list list;
 179 
 180     va_start(list, format);
 181 
 182     p = format;
 183     while (*p && size > 0) {
 184         char *nf;
 185 
 186         nf = strchr(p, '%');
 187         if (!nf) {
 188             /* No more format characters */
 189             while (size-- > 0 && *p) {
 190                 *out_str++ = *p++;
 191             }
 192         }
 193         else {
 194             int nc;
 195             int width = -1;
 196 
 197             /* Copy until nf */
 198             while (p < nf && size-- > 0) {
 199                 *out_str++ = *p++;
 200             }
 201             /* p now points at nf */
 202             /* Handle the format character */
 203             nc = nf[1];
 204             if (isdigit(nc)) {
 205                 /* Get the field width */
 206                 /* FIXME : Assumes ASCII */
 207                 width = nc - '0';
 208                 p = nf + 2;
 209                 while (*p && isdigit(*p)) {
 210                     width = 10 * width + (*p++ - '0');
 211                 }
 212                 /* When there is no longer a digit, get the format 
 213                    character */
 214                 nc = *p++;
 215             }
 216             else {
 217                 /* Skip over the format string */
 218                 p += 2;
 219             }
 220 
 221             switch (nc) {
 222             case '%':
 223                 *out_str++ = '%';
 224                 size--;
 225                 break;
 226 
 227             case 'd':
 228             {
 229                 int val;
 230                 char tmp[20];
 231                 char *t = tmp;
 232                 /* Get the argument, of integer type */
 233                 val = va_arg( list, int );
 234                 sprintf( tmp, "%d", val );
 235                 if (width > 0) {
 236                     int tmplen = strlen(tmp);
 237                     /* If a width was specified, pad with spaces on the
 238                        left (on the right if %-3d given; not implemented yet */
 239                     while (size-- > 0 && width-- > tmplen) 
 240                         *out_str++ = ' ';
 241                 }
 242                 while (size-- > 0 && *t) {
 243                     *out_str++ = *t++;
 244                 }
 245             }
 246             break;
 247 
 248             case 'x':
 249             {
 250                 int val;
 251                 char tmp[20];
 252                 char *t = tmp;
 253                 /* Get the argument, of integer type */
 254                 val = va_arg( list, int );
 255                 sprintf( tmp, "%x", val );
 256                 if (width > 0) {
 257                     int tmplen = strlen(tmp);
 258                     /* If a width was specified, pad with spaces on the
 259                        left (on the right if %-3d given; not implemented yet */
 260                     while (size-- > 0 && width-- > tmplen) 
 261                         *out_str++ = ' ';
 262                 }
 263                 while (size-- > 0 && *t) {
 264                     *out_str++ = *t++;
 265                 }
 266             }
 267             break;
 268 
 269             case 'p':
 270             {
 271                 void *val;
 272                 char tmp[20];
 273                 char *t = tmp;
 274                 val = va_arg( list, void * );
 275                 sprintf( tmp, "%p", val );
 276                 if (width > 0) {
 277                     int tmplen = strlen(tmp);
 278                     /* If a width was specified, pad with spaces on the
 279                        left (on the right if %-3d given; not implemented yet */
 280                     while (size-- > 0 && width-- > tmplen) 
 281                         *out_str++ = ' ';
 282                 }
 283                 while (size-- > 0 && *t) {
 284                     *out_str++ = *t++;
 285                 }
 286             }
 287             break;
 288 
 289             case 's':
 290             {
 291                 char *s_arg;
 292                 /* Get the argument, of pointer to char type */
 293                 s_arg = va_arg( list, char * );
 294                 while (size-- > 0 && s_arg && *s_arg) {
 295                     *out_str++ = *s_arg++;
 296                 }
 297             }
 298             break;
 299 
 300             default:
 301                 /* Error, unknown case */
 302                 return -1;
 303                 break;
 304             }
 305         }
 306     }
 307 
 308     va_end(list);
 309 
 310     if (size-- > 0) *out_str++ = '\0';
 311 
 312     n = (int)(out_str - str);
 313     return n;
 314 }
 315 #endif

/* [<][>][^][v][top][bottom][index][help] */