| 114 | |
| 115 | PRINTF_FORMAT_STRING_FUNC(1, 0) |
| 116 | std::string StrFormatImp(const char* msg, va_list args) { |
| 117 | // we might need a second shot at this, so pre-emptivly make a copy |
| 118 | va_list args_cp; |
| 119 | va_copy(args_cp, args); |
| 120 | |
| 121 | // Use std::array for first attempt to avoid one memory allocation guess what |
| 122 | // the size might be |
| 123 | std::array<char, 256> local_buff = {}; |
| 124 | |
| 125 | // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation |
| 126 | // in the android-ndk |
| 127 | auto ret = vsnprintf(local_buff.data(), local_buff.size(), msg, args_cp); |
| 128 | |
| 129 | va_end(args_cp); |
| 130 | |
| 131 | // handle empty expansion |
| 132 | if (ret == 0) { |
| 133 | return {}; |
| 134 | } |
| 135 | if (static_cast<std::size_t>(ret) < local_buff.size()) { |
| 136 | return std::string(local_buff.data()); |
| 137 | } |
| 138 | |
| 139 | // we did not provide a long enough buffer on our first attempt. |
| 140 | // add 1 to size to account for null-byte in size cast to prevent overflow |
| 141 | std::size_t size = static_cast<std::size_t>(ret) + 1; |
| 142 | auto buff_ptr = std::unique_ptr<char[]>(new char[size]); |
| 143 | // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation |
| 144 | // in the android-ndk |
| 145 | vsnprintf(buff_ptr.get(), size, msg, args); |
| 146 | return std::string(buff_ptr.get()); |
| 147 | } |
| 148 | |
| 149 | } // end namespace |
| 150 | |