| 76 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 77 | |
| 78 | void StringAppendV(std::string* dst, const char* format, va_list ap) { |
| 79 | // First try with a small fixed size buffer. |
| 80 | static const int kFixedBufferSize = 1024; |
| 81 | char fixed_buffer[kFixedBufferSize]; |
| 82 | |
| 83 | // It is possible for methods that use a va_list to invalidate |
| 84 | // the data in it upon use. The fix is to make a copy |
| 85 | // of the structure before using it and use that copy instead. |
| 86 | va_list backup_ap; |
| 87 | va_copy(backup_ap, ap); |
| 88 | int result = vsnprintf(fixed_buffer, kFixedBufferSize, format, backup_ap); |
| 89 | va_end(backup_ap); |
| 90 | |
| 91 | if (result < kFixedBufferSize) { |
| 92 | if (result >= 0) { |
| 93 | // Normal case - everything fits. |
| 94 | dst->append(fixed_buffer, result); |
| 95 | return; |
| 96 | } |
| 97 | |
| 98 | #ifdef _MSC_VER |
| 99 | // Error or MSVC running out of space. MSVC 8.0 and higher |
| 100 | // can be asked about space needed with the special idiom below: |
| 101 | va_copy(backup_ap, ap); |
| 102 | result = vsnprintf(nullptr, 0, format, backup_ap); |
| 103 | va_end(backup_ap); |
| 104 | #endif |
| 105 | |
| 106 | if (result < 0) { |
| 107 | // Just an error. |
| 108 | return; |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | // Increase the buffer size to the size requested by vsnprintf, |
| 113 | // plus one for the closing \0. |
| 114 | const int variable_buffer_size = result + 1; |
| 115 | std::unique_ptr<char[]> variable_buffer(new char[variable_buffer_size]); |
| 116 | |
| 117 | // Restore the va_list before we use it again. |
| 118 | va_copy(backup_ap, ap); |
| 119 | result = |
| 120 | vsnprintf(variable_buffer.get(), variable_buffer_size, format, backup_ap); |
| 121 | va_end(backup_ap); |
| 122 | |
| 123 | if (result >= 0 && result < variable_buffer_size) { |
| 124 | dst->append(variable_buffer.get(), result); |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | bool IsNotWhiteSpace(const int character) { |
| 129 | return character != ' ' && character != '\n' && character != '\r' && |