summaryrefslogtreecommitdiff
path: root/src/string.cc
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2015-04-22 13:19:46 +0100
committerMaxime Coste <frrrwww@gmail.com>2015-04-22 13:19:46 +0100
commitf6c7948c12455c55f19ac27f328478b486f8098e (patch)
tree204e1d60e1486031a5818e7738b73d070ef853b6 /src/string.cc
parent8ff63198bca86e00d8572d27d04321a3aefa5f73 (diff)
Add format_to allowing formating to an existing buffer
Diffstat (limited to 'src/string.cc')
-rw-r--r--src/string.cc52
1 files changed, 40 insertions, 12 deletions
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<StringView> wrap_lines(StringView text, CharCount max_width)
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;
for (auto it = fmt.begin(), end = fmt.end(); it != end;)
{
auto opening = std::find(it, end, '{');
- res += StringView{it, opening};
if (opening == end)
+ {
+ append(StringView{it, opening});
break;
-
- if (opening != it && *(opening-1) == '\\')
+ }
+ else if (opening != it and *(opening-1) == '\\')
{
- res.back() = '{';
+ 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<const StringView> 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<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;
}