1// Copyright 2014 The Android Open Source Project 2// 3// This software is licensed under the terms of the GNU General Public 4// License version 2, as published by the Free Software Foundation, and 5// may be copied, distributed, and modified under those terms. 6// 7// This program is distributed in the hope that it will be useful, 8// but WITHOUT ANY WARRANTY; without even the implied warranty of 9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10// GNU General Public License for more details. 11 12#include "android/base/StringFormat.h" 13 14#include <stdio.h> 15 16namespace android { 17namespace base { 18 19String StringFormat(const char* format, ...) { 20 va_list args; 21 va_start(args, format); 22 String result = StringFormatWithArgs(format, args); 23 va_end(args); 24 return result; 25} 26 27String StringFormatWithArgs(const char* format, va_list args) { 28 String result; 29 StringAppendFormatWithArgs(&result, format, args); 30 return result; 31} 32 33void StringAppendFormat(String* string, const char* format, ...) { 34 va_list args; 35 va_start(args, format); 36 StringAppendFormatWithArgs(string, format, args); 37 va_end(args); 38} 39 40void StringAppendFormatWithArgs(String* string, 41 const char* format, 42 va_list args) { 43 size_t cur_size = string->size(); 44 size_t extra = 0; 45 for (;;) { 46 va_list args2; 47 va_copy(args2, args); 48 int ret = vsnprintf(&(*string)[cur_size], extra, format, args2); 49 va_end(args2); 50 51 if (ret == 0) { 52 // Nothing to do here. 53 break; 54 } 55 56 if (ret > 0) { 57 size_t ret_sz = static_cast<size_t>(ret); 58 if (extra == 0) { 59 // First pass, resize the string and try again. 60 extra = ret_sz + 1; 61 string->resize(cur_size + extra); 62 continue; 63 } 64 if (ret_sz < extra) { 65 // Second pass or later, success! 66 string->resize(cur_size + ret_sz); 67 return; 68 } 69 } 70 71 // NOTE: The MSVCRT.DLL implementation of snprintf() is broken and 72 // will return -1 in case of truncation. This code path is taken 73 // when this happens, or when |ret_sz| is equal or larger than 74 // |extra|. Grow the buffer to allow for more room, then try again. 75 extra += (extra >> 1) + 32; 76 string->resize(cur_size + extra); 77 } 78} 79 80 81} // namespace base 82} // namespace android 83