| 60 | } |
| 61 | |
| 62 | allocation_slot stack_allocator::format_string(char const* fmt, va_list v) |
| 63 | { |
| 64 | auto const pos = m_storage.size(); |
| 65 | std::size_t len = 512; |
| 66 | |
| 67 | for(;;) |
| 68 | { |
| 69 | if (std::numeric_limits<int>::max() - len <= pos) |
| 70 | return {}; |
| 71 | |
| 72 | m_storage.resize(pos + len + 1); |
| 73 | |
| 74 | va_list args; |
| 75 | va_copy(args, v); |
| 76 | |
| 77 | #ifdef __clang__ |
| 78 | #pragma clang diagnostic push |
| 79 | #pragma clang diagnostic ignored "-Wformat-nonliteral" |
| 80 | #endif |
| 81 | int const ret = std::vsnprintf(m_storage.data() + pos, len + 1, fmt, args); |
| 82 | #ifdef __clang__ |
| 83 | #pragma clang diagnostic pop |
| 84 | #endif |
| 85 | |
| 86 | va_end(args); |
| 87 | |
| 88 | if (ret < 0) |
| 89 | { |
| 90 | m_storage.resize(pos); |
| 91 | return copy_string("(format error)"); |
| 92 | } |
| 93 | if (static_cast<std::size_t>(ret) > len) |
| 94 | { |
| 95 | // try again |
| 96 | len = numeric_cast<std::size_t>(ret); |
| 97 | continue; |
| 98 | } |
| 99 | break; |
| 100 | } |
| 101 | |
| 102 | // +1 is to include the 0-terminator |
| 103 | m_storage.resize(pos + len + 1); |
| 104 | return allocation_slot(pos); |
| 105 | } |
| 106 | |
| 107 | allocation_slot stack_allocator::copy_buffer(span<char const> buf) |
| 108 | { |