| 35 | |
| 36 | namespace { |
| 37 | inline int string_printf_impl(std::string& output, const char* format, |
| 38 | va_list args) { |
| 39 | // Tru to the space at the end of output for our output buffer. |
| 40 | // Find out write point then inflate its size temporarily to its |
| 41 | // capacity; we will later shrink it to the size needed to represent |
| 42 | // the formatted string. If this buffer isn't large enough, we do a |
| 43 | // resize and try again. |
| 44 | |
| 45 | const int write_point = output.size(); |
| 46 | int remaining = output.capacity() - write_point; |
| 47 | output.resize(output.capacity()); |
| 48 | |
| 49 | va_list copied_args; |
| 50 | va_copy(copied_args, args); |
| 51 | int bytes_used = vsnprintf(&output[write_point], remaining, format, |
| 52 | copied_args); |
| 53 | va_end(copied_args); |
| 54 | if (bytes_used < 0) { |
| 55 | return -1; |
| 56 | } else if (bytes_used < remaining) { |
| 57 | // There was enough room, just shrink and return. |
| 58 | output.resize(write_point + bytes_used); |
| 59 | } else { |
| 60 | output.resize(write_point + bytes_used + 1); |
| 61 | remaining = bytes_used + 1; |
| 62 | bytes_used = vsnprintf(&output[write_point], remaining, format, args); |
| 63 | if (bytes_used + 1 != remaining) { |
| 64 | return -1; |
| 65 | } |
| 66 | output.resize(write_point + bytes_used); |
| 67 | } |
| 68 | return 0; |
| 69 | } |
| 70 | |
| 71 | inline int string_printf_impl(std::string& output, size_t hint, |
| 72 | const char* format, va_list args) { |