Home | History | Annotate | Download | only in util
      1 // Copyright 2002 The RE2 Authors.  All Rights Reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 #include "util/util.h"
      6 
      7 #ifndef va_copy
      8 #define va_copy(d,s) ((d) = (s)) //KLUGE: for MS compilers
      9 #endif
     10 
     11 namespace re2 {
     12 
     13 static void StringAppendV(string* dst, const char* format, va_list ap) {
     14   // First try with a small fixed size buffer
     15   char space[1024];
     16 
     17   // It's possible for methods that use a va_list to invalidate
     18   // the data in it upon use.  The fix is to make a copy
     19   // of the structure before using it and use that copy instead.
     20   va_list backup_ap;
     21   va_copy(backup_ap, ap);
     22   int result = vsnprintf(space, sizeof(space), format, backup_ap);
     23   va_end(backup_ap);
     24 
     25   if ((result >= 0) && (result < sizeof(space))) {
     26     // It fit
     27     dst->append(space, result);
     28     return;
     29   }
     30 
     31   // Repeatedly increase buffer size until it fits
     32   int length = sizeof(space);
     33   while (true) {
     34     if (result < 0) {
     35       // Older behavior: just try doubling the buffer size
     36       length *= 2;
     37     } else {
     38       // We need exactly "result+1" characters
     39       length = result+1;
     40     }
     41     char* buf = new char[length];
     42 
     43     // Restore the va_list before we use it again
     44     va_copy(backup_ap, ap);
     45     result = vsnprintf(buf, length, format, backup_ap);
     46     va_end(backup_ap);
     47 
     48     if ((result >= 0) && (result < length)) {
     49       // It fit
     50       dst->append(buf, result);
     51       delete[] buf;
     52       return;
     53     }
     54     delete[] buf;
     55   }
     56 }
     57 
     58 string StringPrintf(const char* format, ...) {
     59   va_list ap;
     60   va_start(ap, format);
     61   string result;
     62   StringAppendV(&result, format, ap);
     63   va_end(ap);
     64   return result;
     65 }
     66 
     67 void SStringPrintf(string* dst, const char* format, ...) {
     68   va_list ap;
     69   va_start(ap, format);
     70   dst->clear();
     71   StringAppendV(dst, format, ap);
     72   va_end(ap);
     73 }
     74 
     75 void StringAppendF(string* dst, const char* format, ...) {
     76   va_list ap;
     77   va_start(ap, format);
     78   StringAppendV(dst, format, ap);
     79   va_end(ap);
     80 }
     81 
     82 }  // namespace re2
     83