From f6c7948c12455c55f19ac27f328478b486f8098e Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Wed, 22 Apr 2015 13:19:46 +0100 Subject: [PATCH] Add format_to allowing formating to an existing buffer --- src/file.cc | 9 +++++--- src/string.cc | 54 +++++++++++++++++++++++++++++++++++------------ src/string.hh | 8 +++++++ src/unit_tests.cc | 3 +++ 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/file.cc b/src/file.cc index ee367144..4c5f5a0e 100644 --- a/src/file.cc +++ b/src/file.cc @@ -231,10 +231,13 @@ void write_buffer_to_backup_file(Buffer& buffer) StringView dir, file; std::tie(dir,file) = split_path(path); - String pattern = dir.empty() ? format(".{}.kak.XXXXXX", file) - : format("{}/.{}.kak.XXXXXX", dir, file); + char pattern[PATH_MAX]; + if (dir.empty()) + format_to(pattern, ".{}.kak.XXXXXX", file); + else + format_to(pattern, "{}/.{}.kak.XXXXXX", dir, file); - int fd = mkstemp(&pattern[0]); + int fd = mkstemp(pattern); if (fd >= 0) { write_buffer_to_fd(buffer, fd); diff --git a/src/string.cc b/src/string.cc index df360ae0..bc02b4a3 100644 --- a/src/string.cc +++ b/src/string.cc @@ -214,29 +214,28 @@ Vector wrap_lines(StringView text, CharCount max_width) return lines; } -String format(StringView fmt, ArrayView params) +template +void format_impl(StringView fmt, ArrayView params, AppendFunc append) { - ByteCount size = fmt.length(); - for (auto& s : params) size += s.length(); - String res; - res.reserve(size); - int implicitIndex = 0; for (auto it = fmt.begin(), end = fmt.end(); it != end;) { auto opening = std::find(it, end, '{'); - res += StringView{it, opening}; if (opening == end) - break; - - if (opening != it && *(opening-1) == '\\') { - res.back() = '{'; + append(StringView{it, opening}); + break; + } + else if (opening != it and *(opening-1) == '\\') + { + append(StringView{it, opening-1}); + append('{'); it = opening + 1; } else { - auto closing = std::find(it, end, '}'); + append(StringView{it, opening}); + auto closing = std::find(opening, end, '}'); if (closing == end) throw runtime_error("Format string error, unclosed '{'"); int index; @@ -248,11 +247,40 @@ String format(StringView fmt, ArrayView params) if (index >= params.size()) throw runtime_error("Format string parameter index too big"); - res += params[index]; + append(params[index]); implicitIndex = index+1; it = closing+1; } } +} + +StringView format_to(ArrayView buffer, StringView fmt, ArrayView params) +{ + char* ptr = buffer.begin(); + const char* end = buffer.end(); + format_impl(fmt, params, [&](StringView s) mutable { + for (auto c : s) + { + if (ptr == end) + throw runtime_error("buffer is too small"); + *ptr++ = c; + } + }); + if (ptr == end) + throw runtime_error("buffer is too small"); + *ptr = 0; + + return { buffer.begin(), ptr }; +} + +String format(StringView fmt, ArrayView params) +{ + ByteCount size = fmt.length(); + for (auto& s : params) size += s.length(); + String res; + res.reserve(size); + + format_impl(fmt, params, [&](StringView s) { res += s; }); return res; } diff --git a/src/string.hh b/src/string.hh index a6a267cb..da235744 100644 --- a/src/string.hh +++ b/src/string.hh @@ -311,6 +311,14 @@ String format(StringView fmt, Types... params) return format(fmt, ArrayView{detail::format_param(params)...}); } +StringView format_to(ArrayView buffer, StringView fmt, ArrayView params); + +template +StringView format_to(ArrayView buffer, StringView fmt, Types... params) +{ + return format_to(buffer, fmt, ArrayView{detail::format_param(params)...}); +} + } #endif // string_hh_INCLUDED diff --git a/src/unit_tests.cc b/src/unit_tests.cc index 5c43c848..58f34a98 100644 --- a/src/unit_tests.cc +++ b/src/unit_tests.cc @@ -140,6 +140,9 @@ void test_string() kak_assert(format("Youhou {1} {} {0} \\{}", 10, "hehe", 5) == "Youhou hehe 5 10 {}"); + char buffer[20]; + kak_assert(format_to(buffer, "Hey {}", 15) == "Hey 15"); + kak_assert(str_to_int("5") == 5); kak_assert(str_to_int(to_string(INT_MAX)) == INT_MAX); kak_assert(str_to_int(to_string(INT_MIN)) == INT_MIN);