15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2002 The RE2 Authors.  All Rights Reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// license that can be found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace re2 {
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void StringAppendV(string* dst, const char* format, va_list ap) {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First try with a small fixed size buffer
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char space[1024];
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible for methods that use a va_list to invalidate
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the data in it upon use.  The fix is to make a copy
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the structure before using it and use that copy instead.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list backup_ap;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_copy(backup_ap, ap);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = vsnprintf(space, sizeof(space), format, backup_ap);
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end(backup_ap);
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((result >= 0) && (result < sizeof(space))) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It fit
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dst->append(space, result);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Repeatedly increase buffer size until it fits
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int length = sizeof(space);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result < 0) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Older behavior: just try doubling the buffer size
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length *= 2;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We need exactly "result+1" characters
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      length = result+1;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* buf = new char[length];
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Restore the va_list before we use it again
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_copy(backup_ap, ap);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = vsnprintf(buf, length, format, backup_ap);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_end(backup_ap);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((result >= 0) && (result < length)) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // It fit
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dst->append(buf, result);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete[] buf;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete[] buf;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string StringPrintf(const char* format, ...) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list ap;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_start(ap, format);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string result;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringAppendV(&result, format, ap);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end(ap);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SStringPrintf(string* dst, const char* format, ...) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list ap;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_start(ap, format);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dst->clear();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringAppendV(dst, format, ap);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end(ap);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StringAppendF(string* dst, const char* format, ...) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_list ap;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_start(ap, format);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringAppendV(dst, format, ap);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  va_end(ap);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace re2
79