summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2024-08-09 18:16:51 +1000
committerMaxime Coste <mawww@kakoune.org>2024-08-12 20:02:11 +1000
commit1a52006c3d215196997a2cd12450795d4ae4a1ca (patch)
tree9cae5c08d6fa0a0ec4017b6a0156e64924eeb898 /src
parent2d9886afe76adde9f33fc0c0454146176857a6f2 (diff)
Extract format implementation to its own file
Split it to avoid pulling all string_utils dependencies for just format.
Diffstat (limited to 'src')
-rw-r--r--src/backtrace.cc2
-rw-r--r--src/color.cc2
-rw-r--r--src/face_registry.cc2
-rw-r--r--src/format.cc180
-rw-r--r--src/format.hh81
-rw-r--r--src/highlighter_group.cc2
-rw-r--r--src/keymap_manager.cc2
-rw-r--r--src/parameters_parser.hh2
-rw-r--r--src/regex_impl.cc2
-rw-r--r--src/register_manager.cc2
-rw-r--r--src/string_utils.cc168
-rw-r--r--src/string_utils.hh72
-rw-r--r--src/terminal_ui.cc2
13 files changed, 272 insertions, 247 deletions
diff --git a/src/backtrace.cc b/src/backtrace.cc
index 1b3c6d09..04b772ad 100644
--- a/src/backtrace.cc
+++ b/src/backtrace.cc
@@ -1,7 +1,7 @@
#include "backtrace.hh"
#include "string.hh"
-#include "string_utils.hh"
+#include "format.hh"
#if defined(__GLIBC__) || defined(__APPLE__)
# include <execinfo.h>
diff --git a/src/color.cc b/src/color.cc
index 145a5381..71ef46b6 100644
--- a/src/color.cc
+++ b/src/color.cc
@@ -2,7 +2,7 @@
#include "exception.hh"
#include "ranges.hh"
-#include "string_utils.hh"
+#include "format.hh"
#include <cstdio>
diff --git a/src/face_registry.cc b/src/face_registry.cc
index d6c5cd53..e4a0cf86 100644
--- a/src/face_registry.cc
+++ b/src/face_registry.cc
@@ -2,7 +2,7 @@
#include "exception.hh"
#include "ranges.hh"
-#include "string_utils.hh"
+#include "format.hh"
namespace Kakoune
{
diff --git a/src/format.cc b/src/format.cc
new file mode 100644
index 00000000..685fa651
--- /dev/null
+++ b/src/format.cc
@@ -0,0 +1,180 @@
+#include "format.hh"
+
+#include "exception.hh"
+#include "string_utils.hh"
+
+#include <charconv>
+
+namespace Kakoune
+{
+
+
+template<size_t N>
+InplaceString<N> to_string_impl(auto val, auto format)
+{
+ InplaceString<N> res;
+ auto [end, errc] = std::to_chars(res.m_data, res.m_data + N, val, format);
+ if (errc != std::errc{})
+ throw runtime_error("to_string error");
+ res.m_length = end - res.m_data;
+ *end = '\0';
+ return res;
+}
+
+template<size_t N>
+InplaceString<N> to_string_impl(auto val)
+{
+ return to_string_impl<N>(val, 10);
+}
+
+InplaceString<15> to_string(int val)
+{
+ return to_string_impl<15>(val);
+}
+
+InplaceString<15> to_string(unsigned val)
+{
+ return to_string_impl<15>(val);
+}
+
+InplaceString<23> to_string(long int val)
+{
+ return to_string_impl<23>(val);
+}
+
+InplaceString<23> to_string(long long int val)
+{
+ return to_string_impl<23>(val);
+}
+
+InplaceString<23> to_string(unsigned long val)
+{
+ return to_string_impl<23>(val);
+}
+
+InplaceString<23> to_string(Hex val)
+{
+ return to_string_impl<23>(val.val, 16);
+}
+
+InplaceString<23> to_string(Grouped val)
+{
+ auto ungrouped = to_string_impl<23>(val.val);
+
+ InplaceString<23> res;
+ for (int pos = 0, len = ungrouped.m_length; pos != len; ++pos)
+ {
+ if (res.m_length and ((len - pos) % 3) == 0)
+ res.m_data[res.m_length++] = ',';
+ res.m_data[res.m_length++] = ungrouped.m_data[pos];
+ }
+ return res;
+}
+
+InplaceString<23> to_string(float val)
+{
+#if defined(__cpp_lib_to_chars)
+ return to_string_impl<23>(val, std::chars_format::general);
+#else
+ InplaceString<23> res;
+ res.m_length = snprintf(res.m_data, 23, "%f", val);
+ return res;
+#endif
+}
+
+InplaceString<7> to_string(Codepoint c)
+{
+ InplaceString<7> res;
+ char* ptr = res.m_data;
+ utf8::dump(ptr, c);
+ res.m_length = (int)(ptr - res.m_data);
+ return res;
+}
+
+template<typename AppendFunc>
+void format_impl(StringView fmt, ArrayView<const StringView> params, AppendFunc append)
+{
+ int implicitIndex = 0;
+ for (auto it = fmt.begin(), end = fmt.end(); it != end;)
+ {
+ auto opening = std::find(it, end, '{');
+ if (opening == end)
+ {
+ append(StringView{it, opening});
+ break;
+ }
+ else if (opening != it and *(opening-1) == '\\')
+ {
+ append(StringView{it, opening-1});
+ append('{');
+ it = opening + 1;
+ }
+ else
+ {
+ append(StringView{it, opening});
+ auto closing = std::find(opening, end, '}');
+ if (closing == end)
+ throw runtime_error("format string error, unclosed '{'");
+
+ auto format = std::find(opening+1, closing, ':');
+ const int index = opening+1 == format ? implicitIndex : str_to_int({opening+1, format});
+
+ if (index >= params.size())
+ throw runtime_error("format string parameter index too big");
+
+ if (format != closing)
+ {
+ char padding = ' ';
+ if (*(++format) == '0')
+ {
+ padding = '0';
+ ++format;
+ }
+ for (ColumnCount width = str_to_int({format, closing}), len = params[index].column_length();
+ width > len; --width)
+ append(padding);
+ }
+
+ 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 };
+}
+
+void format_with(FunctionRef<void (StringView)> append, StringView fmt, ArrayView<const StringView> params)
+{
+ format_impl(fmt, params, append);
+}
+
+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;
+}
+
+}
diff --git a/src/format.hh b/src/format.hh
new file mode 100644
index 00000000..652bc477
--- /dev/null
+++ b/src/format.hh
@@ -0,0 +1,81 @@
+#ifndef format_hh_INCLUDED
+#define format_hh_INCLUDED
+
+#include "string.hh"
+#include "utils.hh"
+
+namespace Kakoune
+{
+
+template<size_t N>
+struct InplaceString
+{
+ static_assert(N < 256, "InplaceString cannot handle sizes >= 256");
+
+ constexpr operator StringView() const { return {m_data, ByteCount{m_length}}; }
+ operator String() const { return {m_data, ByteCount{m_length}}; }
+
+ unsigned char m_length{};
+ char m_data[N];
+};
+
+struct Hex { size_t val; };
+constexpr Hex hex(size_t val) { return {val}; }
+
+struct Grouped { size_t val; };
+constexpr Grouped grouped(size_t val) { return {val}; }
+
+InplaceString<15> to_string(int val);
+InplaceString<15> to_string(unsigned val);
+InplaceString<23> to_string(long int val);
+InplaceString<23> to_string(unsigned long val);
+InplaceString<23> to_string(long long int val);
+InplaceString<23> to_string(Hex val);
+InplaceString<23> to_string(Grouped val);
+InplaceString<23> to_string(float val);
+InplaceString<7> to_string(Codepoint c);
+
+template<typename RealType, typename ValueType>
+decltype(auto) to_string(const StronglyTypedNumber<RealType, ValueType>& val)
+{
+ return to_string((ValueType)val);
+}
+
+namespace detail
+{
+
+template<typename T> requires std::is_convertible_v<T, StringView>
+StringView format_param(const T& val) { return val; }
+
+template<typename T> requires (not std::is_convertible_v<T, StringView>)
+decltype(auto) format_param(const T& val) { return to_string(val); }
+
+}
+
+String format(StringView fmt, ArrayView<const StringView> params);
+
+template<typename... Types>
+String format(StringView fmt, Types&&... params)
+{
+ return format(fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(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(std::forward<Types>(params))...});
+}
+
+void format_with(FunctionRef<void (StringView)> append, StringView fmt, ArrayView<const StringView> params);
+
+template<typename... Types>
+void format_with(FunctionRef<void (StringView)> append, StringView fmt, Types&&... params)
+{
+ return format_with(append, fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(params))...});
+}
+
+}
+
+#endif // format_hh_INCLUDED
diff --git a/src/highlighter_group.cc b/src/highlighter_group.cc
index 813262c0..7802df94 100644
--- a/src/highlighter_group.cc
+++ b/src/highlighter_group.cc
@@ -1,7 +1,7 @@
#include "highlighter_group.hh"
#include "ranges.hh"
-#include "string_utils.hh"
+#include "format.hh"
namespace Kakoune
{
diff --git a/src/keymap_manager.cc b/src/keymap_manager.cc
index 582a271d..583fb2e7 100644
--- a/src/keymap_manager.cc
+++ b/src/keymap_manager.cc
@@ -3,7 +3,7 @@
#include "array_view.hh"
#include "assert.hh"
#include "exception.hh"
-#include "string_utils.hh"
+#include "format.hh"
#include <algorithm>
diff --git a/src/parameters_parser.hh b/src/parameters_parser.hh
index c11dc501..7d26c3bb 100644
--- a/src/parameters_parser.hh
+++ b/src/parameters_parser.hh
@@ -8,7 +8,7 @@
#include "optional.hh"
#include "flags.hh"
#include "string.hh"
-#include "string_utils.hh"
+#include "format.hh"
#include <functional>
diff --git a/src/regex_impl.cc b/src/regex_impl.cc
index c32917eb..2cebf964 100644
--- a/src/regex_impl.cc
+++ b/src/regex_impl.cc
@@ -6,7 +6,7 @@
#include "unit_tests.hh"
#include "utf8.hh"
#include "utf8_iterator.hh"
-#include "string_utils.hh"
+#include "format.hh"
#include "vector.hh"
#include "utils.hh"
diff --git a/src/register_manager.cc b/src/register_manager.cc
index a189c5b6..bb198dc6 100644
--- a/src/register_manager.cc
+++ b/src/register_manager.cc
@@ -3,7 +3,7 @@
#include "assert.hh"
#include "context.hh"
#include "hash_map.hh"
-#include "string_utils.hh"
+#include "format.hh"
namespace Kakoune
{
diff --git a/src/string_utils.cc b/src/string_utils.cc
index c614d485..42b299f9 100644
--- a/src/string_utils.cc
+++ b/src/string_utils.cc
@@ -147,88 +147,6 @@ int str_to_int(StringView str)
throw runtime_error{str + " is not a number"};
}
-template<size_t N>
-InplaceString<N> to_string_impl(auto val, auto format)
-{
- InplaceString<N> res;
- auto [end, errc] = std::to_chars(res.m_data, res.m_data + N, val, format);
- if (errc != std::errc{})
- throw runtime_error("to_string error");
- res.m_length = end - res.m_data;
- *end = '\0';
- return res;
-}
-
-template<size_t N>
-InplaceString<N> to_string_impl(auto val)
-{
- return to_string_impl<N>(val, 10);
-}
-
-InplaceString<15> to_string(int val)
-{
- return to_string_impl<15>(val);
-}
-
-InplaceString<15> to_string(unsigned val)
-{
- return to_string_impl<15>(val);
-}
-
-InplaceString<23> to_string(long int val)
-{
- return to_string_impl<23>(val);
-}
-
-InplaceString<23> to_string(long long int val)
-{
- return to_string_impl<23>(val);
-}
-
-InplaceString<23> to_string(unsigned long val)
-{
- return to_string_impl<23>(val);
-}
-
-InplaceString<23> to_string(Hex val)
-{
- return to_string_impl<23>(val.val, 16);
-}
-
-InplaceString<23> to_string(Grouped val)
-{
- auto ungrouped = to_string_impl<23>(val.val);
-
- InplaceString<23> res;
- for (int pos = 0, len = ungrouped.m_length; pos != len; ++pos)
- {
- if (res.m_length and ((len - pos) % 3) == 0)
- res.m_data[res.m_length++] = ',';
- res.m_data[res.m_length++] = ungrouped.m_data[pos];
- }
- return res;
-}
-
-InplaceString<23> to_string(float val)
-{
-#if defined(__cpp_lib_to_chars)
- return to_string_impl<23>(val, std::chars_format::general);
-#else
- InplaceString<23> res;
- res.m_length = snprintf(res.m_data, 23, "%f", val);
- return res;
-#endif
-}
-
-InplaceString<7> to_string(Codepoint c)
-{
- InplaceString<7> res;
- char* ptr = res.m_data;
- utf8::dump(ptr, c);
- res.m_length = (int)(ptr - res.m_data);
- return res;
-}
-
bool subsequence_match(StringView str, StringView subseq)
{
auto it = str.begin();
@@ -327,92 +245,6 @@ WrapView::Iterator& WrapView::Iterator::operator++()
return *this;
}
-template<typename AppendFunc>
-void format_impl(StringView fmt, ArrayView<const StringView> params, AppendFunc append)
-{
- int implicitIndex = 0;
- for (auto it = fmt.begin(), end = fmt.end(); it != end;)
- {
- auto opening = std::find(it, end, '{');
- if (opening == end)
- {
- append(StringView{it, opening});
- break;
- }
- else if (opening != it and *(opening-1) == '\\')
- {
- append(StringView{it, opening-1});
- append('{');
- it = opening + 1;
- }
- else
- {
- append(StringView{it, opening});
- auto closing = std::find(opening, end, '}');
- if (closing == end)
- throw runtime_error("format string error, unclosed '{'");
-
- auto format = std::find(opening+1, closing, ':');
- const int index = opening+1 == format ? implicitIndex : str_to_int({opening+1, format});
-
- if (index >= params.size())
- throw runtime_error("format string parameter index too big");
-
- if (format != closing)
- {
- char padding = ' ';
- if (*(++format) == '0')
- {
- padding = '0';
- ++format;
- }
- for (ColumnCount width = str_to_int({format, closing}), len = params[index].column_length();
- width > len; --width)
- append(padding);
- }
-
- 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 };
-}
-
-void format_with(FunctionRef<void (StringView)> append, StringView fmt, ArrayView<const StringView> params)
-{
- format_impl(fmt, params, append);
-}
-
-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;
-}
-
String double_up(StringView s, StringView characters)
{
String res;
diff --git a/src/string_utils.hh b/src/string_utils.hh
index 3034dfd5..24da0111 100644
--- a/src/string_utils.hh
+++ b/src/string_utils.hh
@@ -4,9 +4,10 @@
#include "string.hh"
#include "enum.hh"
#include "vector.hh"
-#include "ranges.hh"
#include "optional.hh"
#include "utils.hh"
+#include "format.hh"
+#include "ranges.hh"
namespace Kakoune
{
@@ -107,75 +108,6 @@ inline auto wrap_at(ColumnCount max_width)
int str_to_int(StringView str); // throws on error
Optional<int> str_to_int_ifp(StringView str);
-template<size_t N>
-struct InplaceString
-{
- static_assert(N < 256, "InplaceString cannot handle sizes >= 256");
-
- constexpr operator StringView() const { return {m_data, ByteCount{m_length}}; }
- operator String() const { return {m_data, ByteCount{m_length}}; }
-
- unsigned char m_length{};
- char m_data[N];
-};
-
-struct Hex { size_t val; };
-constexpr Hex hex(size_t val) { return {val}; }
-
-struct Grouped { size_t val; };
-constexpr Grouped grouped(size_t val) { return {val}; }
-
-InplaceString<15> to_string(int val);
-InplaceString<15> to_string(unsigned val);
-InplaceString<23> to_string(long int val);
-InplaceString<23> to_string(unsigned long val);
-InplaceString<23> to_string(long long int val);
-InplaceString<23> to_string(Hex val);
-InplaceString<23> to_string(Grouped val);
-InplaceString<23> to_string(float val);
-InplaceString<7> to_string(Codepoint c);
-
-template<typename RealType, typename ValueType>
-decltype(auto) to_string(const StronglyTypedNumber<RealType, ValueType>& val)
-{
- return to_string((ValueType)val);
-}
-
-namespace detail
-{
-
-template<typename T> requires std::is_convertible_v<T, StringView>
-StringView format_param(const T& val) { return val; }
-
-template<typename T> requires (not std::is_convertible_v<T, StringView>)
-decltype(auto) format_param(const T& val) { return to_string(val); }
-
-}
-
-String format(StringView fmt, ArrayView<const StringView> params);
-
-template<typename... Types>
-String format(StringView fmt, Types&&... params)
-{
- return format(fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(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(std::forward<Types>(params))...});
-}
-
-void format_with(FunctionRef<void (StringView)> append, StringView fmt, ArrayView<const StringView> params);
-
-template<typename... Types>
-void format_with(FunctionRef<void (StringView)> append, StringView fmt, Types&&... params)
-{
- return format_with(append, fmt, ArrayView<const StringView>{detail::format_param(std::forward<Types>(params))...});
-}
-
String double_up(StringView s, StringView characters);
inline String quote(StringView s)
diff --git a/src/terminal_ui.cc b/src/terminal_ui.cc
index 33574e90..991cdecf 100644
--- a/src/terminal_ui.cc
+++ b/src/terminal_ui.cc
@@ -7,7 +7,7 @@
#include "file.hh"
#include "keys.hh"
#include "ranges.hh"
-#include "string_utils.hh"
+#include "format.hh"
#include "diff.hh"
#include <algorithm>