Add format_to allowing formating to an existing buffer
This commit is contained in:
parent
8ff63198bc
commit
f6c7948c12
|
@ -231,10 +231,13 @@ void write_buffer_to_backup_file(Buffer& buffer)
|
||||||
StringView dir, file;
|
StringView dir, file;
|
||||||
std::tie(dir,file) = split_path(path);
|
std::tie(dir,file) = split_path(path);
|
||||||
|
|
||||||
String pattern = dir.empty() ? format(".{}.kak.XXXXXX", file)
|
char pattern[PATH_MAX];
|
||||||
: format("{}/.{}.kak.XXXXXX", dir, file);
|
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)
|
if (fd >= 0)
|
||||||
{
|
{
|
||||||
write_buffer_to_fd(buffer, fd);
|
write_buffer_to_fd(buffer, fd);
|
||||||
|
|
|
@ -214,29 +214,28 @@ Vector<StringView> wrap_lines(StringView text, CharCount max_width)
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
String format(StringView fmt, ArrayView<const StringView> params)
|
template<typename AppendFunc>
|
||||||
|
void format_impl(StringView fmt, ArrayView<const StringView> params, AppendFunc append)
|
||||||
{
|
{
|
||||||
ByteCount size = fmt.length();
|
|
||||||
for (auto& s : params) size += s.length();
|
|
||||||
String res;
|
|
||||||
res.reserve(size);
|
|
||||||
|
|
||||||
int implicitIndex = 0;
|
int implicitIndex = 0;
|
||||||
for (auto it = fmt.begin(), end = fmt.end(); it != end;)
|
for (auto it = fmt.begin(), end = fmt.end(); it != end;)
|
||||||
{
|
{
|
||||||
auto opening = std::find(it, end, '{');
|
auto opening = std::find(it, end, '{');
|
||||||
res += StringView{it, opening};
|
|
||||||
if (opening == end)
|
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;
|
it = opening + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto closing = std::find(it, end, '}');
|
append(StringView{it, opening});
|
||||||
|
auto closing = std::find(opening, end, '}');
|
||||||
if (closing == end)
|
if (closing == end)
|
||||||
throw runtime_error("Format string error, unclosed '{'");
|
throw runtime_error("Format string error, unclosed '{'");
|
||||||
int index;
|
int index;
|
||||||
|
@ -248,11 +247,40 @@ String format(StringView fmt, ArrayView<const StringView> params)
|
||||||
if (index >= params.size())
|
if (index >= params.size())
|
||||||
throw runtime_error("Format string parameter index too big");
|
throw runtime_error("Format string parameter index too big");
|
||||||
|
|
||||||
res += params[index];
|
append(params[index]);
|
||||||
implicitIndex = index+1;
|
implicitIndex = index+1;
|
||||||
it = closing+1;
|
it = closing+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView format_to(ArrayView<char> buffer, StringView fmt, ArrayView<const StringView> 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<const StringView> 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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -311,6 +311,14 @@ String format(StringView fmt, Types... params)
|
||||||
return format(fmt, ArrayView<const StringView>{detail::format_param(params)...});
|
return format(fmt, ArrayView<const StringView>{detail::format_param(params)...});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringView format_to(ArrayView<char> buffer, StringView fmt, ArrayView<const StringView> params);
|
||||||
|
|
||||||
|
template<typename... Types>
|
||||||
|
StringView format_to(ArrayView<char> buffer, StringView fmt, Types... params)
|
||||||
|
{
|
||||||
|
return format_to(buffer, fmt, ArrayView<const StringView>{detail::format_param(params)...});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // string_hh_INCLUDED
|
#endif // string_hh_INCLUDED
|
||||||
|
|
|
@ -140,6 +140,9 @@ void test_string()
|
||||||
|
|
||||||
kak_assert(format("Youhou {1} {} {0} \\{}", 10, "hehe", 5) == "Youhou hehe 5 10 {}");
|
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("5") == 5);
|
||||||
kak_assert(str_to_int(to_string(INT_MAX)) == INT_MAX);
|
kak_assert(str_to_int(to_string(INT_MAX)) == INT_MAX);
|
||||||
kak_assert(str_to_int(to_string(INT_MIN)) == INT_MIN);
|
kak_assert(str_to_int(to_string(INT_MIN)) == INT_MIN);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user