summaryrefslogtreecommitdiff
path: root/asl
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-11-13 23:58:18 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-12-20 15:35:58 +0100
commit75e956eac30050bb10d131b8f14ecbc396abcf17 (patch)
tree116bef4e8208506cbb17dcf40006ed379cc6f0c1 /asl
parentae9d36675a21b5a81bc87279dc9ee1224cdcb963 (diff)
Use string_view for formatting
Diffstat (limited to 'asl')
-rw-r--r--asl/format.cpp88
-rw-r--r--asl/format.hpp11
-rw-r--r--asl/print.cpp8
-rw-r--r--asl/print.hpp6
-rw-r--r--asl/string_view.hpp32
-rw-r--r--asl/tests/format_tests.cpp35
-rw-r--r--asl/tests/string_view_tests.cpp35
7 files changed, 142 insertions, 73 deletions
diff --git a/asl/format.cpp b/asl/format.cpp
index a86ce69..5c22026 100644
--- a/asl/format.cpp
+++ b/asl/format.cpp
@@ -4,7 +4,7 @@
void asl::format_internals::format(
writer* writer,
- const char* fmt,
+ string_view fmt,
span<const type_erased_arg> args)
{
formatter f(writer);
@@ -12,87 +12,91 @@ void asl::format_internals::format(
const auto* arg_it = args.begin();
const auto* arg_end = args.end();
- const char* begin = fmt;
- while (*fmt != '\0')
+ isize_t i = 0;
+ while (i < fmt.size())
{
- if (fmt[0] == '{')
+ if (fmt[i] == '{')
{
- if (fmt[1] == '}')
+ if (i + 1 < fmt.size())
{
- if (arg_it < arg_end)
+ if (fmt[i + 1] == '}')
{
- f.write(begin, fmt - begin);
- fmt += 2;
- begin = fmt;
+ if (arg_it >= arg_end)
+ {
+ f.write(fmt.substr(0, i));
+ fmt = fmt.substr(i + 2);
+ i = 0;
+
+ f.write("<ERROR>");
+
+ continue;
+ }
+
+ f.write(fmt.substr(0, i));
+ fmt = fmt.substr(i + 2);
+ i = 0;
arg_it->fn(f, arg_it->data);
arg_it++; // NOLINT(*-pointer-arithmetic)
+
+ continue;
}
- else
+
+ if (fmt[i + 1] == '{')
{
- f.write(begin, fmt - begin);
- fmt += 2;
- begin = fmt;
+ f.write(fmt.substr(0, i + 1));
+ fmt = fmt.substr(i + 2);
+ i = 0;
- f.write("<ERROR>", 7);
+ continue;
}
}
- else if (fmt[1] == '{')
- {
- fmt += 1;
- f.write(begin, fmt - begin);
- fmt += 1;
- begin = fmt;
- }
- else
- {
- f.write(begin, fmt - begin);
- fmt += 1;
- begin = fmt;
+
+ f.write(fmt.substr(0, i));
+ fmt = fmt.substr(i + 1);
+ i = 0;
- f.write("<ERROR>", 7);
- }
+ f.write("<ERROR>");
}
- else if (fmt[0] == '}' && fmt[1] == '}')
+ else if (i + 1 < fmt.size() && fmt[i] == '}' && fmt[i + 1] == '}')
{
- fmt += 1;
- f.write(begin, fmt - begin);
- fmt += 1;
- begin = fmt;
+ f.write(fmt.substr(0, i + 1));
+ fmt = fmt.substr(i + 2);
+ i = 0;
}
else
{
- fmt += 1;
+ i += 1;
}
}
- f.write(begin, fmt - begin);
+ f.write(fmt);
}
void asl::AslFormat(formatter& f, const char* str)
{
- f.write(str, static_cast<isize_t>(__builtin_strlen(str)));
+ f.write({str, static_cast<isize_t>(__builtin_strlen(str))});
}
void asl::AslFormat(formatter& f, float)
{
- f.write("<FLOAT>", 7); // @Todo Float formatting
+ f.write("<FLOAT>"); // @Todo Float formatting
}
void asl::AslFormat(formatter& f, double)
{
- f.write("<DOUBLE>", 8); // @Todo Float formatting
+ f.write("<DOUBLE>"); // @Todo Float formatting
}
void asl::AslFormat(formatter& f, bool v)
{
if (v)
{
- f.write("true", 4);
+ f.write("true");
}
else
{
- f.write("false", 5);
+ f.write("false");
}
}
@@ -170,7 +174,7 @@ void asl::AslFormat(formatter& f, uint64_t v)
write_one('0' + static_cast<char>(v));
}
- f.write(buffer + cursor, kMaxDigits - cursor);
+ f.write({buffer + cursor, kMaxDigits - cursor});
}
void asl::AslFormat(formatter& f, int8_t v)
@@ -192,7 +196,7 @@ void asl::AslFormat(formatter& f, int64_t v)
{
if (v < 0)
{
- f.write("-", 1);
+ f.write("-");
uint64_t absolute_value = ~(bit_cast<uint64_t>(v) - 1);
AslFormat(f, absolute_value);
}
diff --git a/asl/format.hpp b/asl/format.hpp
index 666e325..57be45d 100644
--- a/asl/format.hpp
+++ b/asl/format.hpp
@@ -4,6 +4,7 @@
#include "asl/meta.hpp"
#include "asl/io.hpp"
#include "asl/span.hpp"
+#include "asl/string_view.hpp"
namespace asl
{
@@ -37,7 +38,7 @@ struct type_erased_arg
{}
};
-void format(writer*, const char* fmt, span<const type_erased_arg> args);
+void format(writer*, string_view fmt, span<const type_erased_arg> args);
} // namespace internals
@@ -50,16 +51,14 @@ public:
: m_writer{writer}
{}
- // @Todo Use string_view
- constexpr void write(const char* s, isize_t len)
+ constexpr void write(string_view s)
{
- m_writer->write(as_bytes(span<const char>(s, len)));
+ m_writer->write(as_bytes(s.as_span()));
}
};
-// @Todo Use string_view
template<formattable... Args>
-void format(writer* w, const char* fmt, const Args&... args)
+void format(writer* w, string_view fmt, const Args&... args)
{
if constexpr (types_count<Args...> > 0)
{
diff --git a/asl/print.cpp b/asl/print.cpp
index 8180c04..6f81f19 100644
--- a/asl/print.cpp
+++ b/asl/print.cpp
@@ -20,12 +20,12 @@ public:
asl::writer* asl::print_internals::get_stdout_writer()
{
- static ConsoleWriter writer{stdout};
- return &writer;
+ static ConsoleWriter s_writer{stdout};
+ return &s_writer;
}
asl::writer* asl::print_internals::get_stderr_writer()
{
- static ConsoleWriter writer{stderr};
- return &writer;
+ static ConsoleWriter s_writer{stderr};
+ return &s_writer;
}
diff --git a/asl/print.hpp b/asl/print.hpp
index d82d52b..4e7d07a 100644
--- a/asl/print.hpp
+++ b/asl/print.hpp
@@ -14,16 +14,14 @@ writer* get_stderr_writer();
} // namespace print_internals
-// @Todo Use string_view
template<formattable... Args>
-void print(const char* fmt, const Args&... args)
+void print(string_view fmt, const Args&... args)
{
format(print_internals::get_stdout_writer(), fmt, args...);
}
-// @Todo Use string_view
template<formattable... Args>
-void eprint(const char* fmt, const Args&... args)
+void eprint(string_view fmt, const Args&... args)
{
format(print_internals::get_stderr_writer(), fmt, args...);
}
diff --git a/asl/string_view.hpp b/asl/string_view.hpp
index 9045eda..2e8efff 100644
--- a/asl/string_view.hpp
+++ b/asl/string_view.hpp
@@ -2,6 +2,7 @@
#include "asl/integers.hpp"
#include "asl/meta.hpp"
+#include "asl/span.hpp"
namespace asl
{
@@ -23,6 +24,15 @@ public:
, m_size{size}
{}
+ template<isize_t kSize>
+ constexpr string_view(const char (&str)[kSize]) // NOLINT(*-explicit-conversions)
+ requires (kSize >= 1)
+ : m_data{str}
+ , m_size{kSize - 1}
+ {
+ ASL_ASSERT(m_data[kSize - 1] == '\0'); // NOLINT(*-pointer-arithmetic)
+ }
+
constexpr string_view(const string_view&) = default;
constexpr string_view(string_view&&) = default;
@@ -40,6 +50,26 @@ public:
constexpr const char* begin() const { return m_data; }
constexpr const char* end() const { return m_data + m_size; } // NOLINT(*-pointer-arithmetic)
+
+ constexpr span<const char> as_span() const { return span<const char>(m_data, m_size); }
+
+ constexpr char operator[](isize_t i) const
+ {
+ ASL_ASSERT(i >= 0 && i < m_size);
+ return m_data[i]; // NOLINT(*-pointer-arithmetic)
+ }
+
+ constexpr string_view substr(isize_t offset, isize_t size) const
+ {
+ ASL_ASSERT(offset >= 0 && size >= 0 && offset + size <= m_size);
+ return string_view{m_data + offset, size}; // NOLINT(*-pointer-arithmetic)
+ }
+
+ constexpr string_view substr(isize_t offset) const
+ {
+ ASL_ASSERT(offset >= 0 && offset <= m_size);
+ return string_view{m_data + offset, m_size - offset}; // NOLINT(*-pointer-arithmetic)
+ }
};
} // namespace asl
@@ -48,3 +78,5 @@ constexpr asl::string_view operator ""_sv(const char* s, size_t len)
{
return asl::string_view(s, static_cast<isize_t>(len));
}
+
+// @Todo Make comparison operator, replace in format and string_view tests
diff --git a/asl/tests/format_tests.cpp b/asl/tests/format_tests.cpp
index f051034..dd31efc 100644
--- a/asl/tests/format_tests.cpp
+++ b/asl/tests/format_tests.cpp
@@ -1,5 +1,6 @@
#include "asl/format.hpp"
#include "asl/testing/testing.hpp"
+#include "asl/print.hpp"
#include <cstdlib>
#include <cstring>
@@ -38,47 +39,47 @@ ASL_TEST(format_args)
{
StringSink sink;
- // @Todo Introduce ASL_TEST_ASSERT_EQ, or ASL_TEST_ASSERT_STREQ
+ // @Todo Introduce ASL_TEST_EXPECT_EQ, or ASL_TEST_EXPECT_STREQ
// @Todo Don't use strcmp for string comparison
asl::format(&sink, "Hello, world!");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "Hello, world!") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "Hello, world!") == 0);
sink.reset();
asl::format(&sink, "");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "") == 0);
sink.reset();
asl::format(&sink, "Hello, {}!", "world");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "Hello, world!") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "Hello, world!") == 0);
sink.reset();
asl::format(&sink, "Hello, {}! {}", "world");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "Hello, world! <ERROR>") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "Hello, world! <ERROR>") == 0);
sink.reset();
asl::format(&sink, "Hello, pup!", "world");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "Hello, pup!") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "Hello, pup!") == 0);
sink.reset();
asl::format(&sink, "{}", "CHEESE");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "CHEESE") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "CHEESE") == 0);
sink.reset();
asl::format(&sink, "{ ", "CHEESE");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "<ERROR> ") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "<ERROR> ") == 0);
sink.reset();
asl::format(&sink, "{", "CHEESE");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "<ERROR>") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "<ERROR>") == 0);
sink.reset();
asl::format(&sink, "a{{b");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "a{b") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "a{b") == 0);
sink.reset();
asl::format(&sink, "{{{}}} }", "CHEESE");
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "{CHEESE} }") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "{CHEESE} }") == 0);
}
ASL_TEST(format_integers)
@@ -87,23 +88,23 @@ ASL_TEST(format_integers)
sink.reset();
asl::format(&sink, "{} {} {}", 0, 1, 2);
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "0 1 2") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "0 1 2") == 0);
sink.reset();
asl::format(&sink, "{} {} {}", 10, 11, 12);
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "10 11 12") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "10 11 12") == 0);
sink.reset();
asl::format(&sink, "{} {} {}", 100, 101, 102);
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "100 101 102") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "100 101 102") == 0);
sink.reset();
asl::format(&sink, "{} {} {}", 1000, 1001, 1002);
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "1000 1001 1002") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "1000 1001 1002") == 0);
sink.reset();
asl::format(&sink, "{} {} {} {}", -1, -23, -456, -7890);
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "-1 -23 -456 -7890") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "-1 -23 -456 -7890") == 0);
}
ASL_TEST(format_boolean)
@@ -112,5 +113,5 @@ ASL_TEST(format_boolean)
sink.reset();
asl::format(&sink, "{} {}", true, false);
- ASL_TEST_ASSERT(strcmp(sink.cstr(), "true false") == 0);
+ ASL_TEST_EXPECT(strcmp(sink.cstr(), "true false") == 0);
}
diff --git a/asl/tests/string_view_tests.cpp b/asl/tests/string_view_tests.cpp
index dafb91c..1c12603 100644
--- a/asl/tests/string_view_tests.cpp
+++ b/asl/tests/string_view_tests.cpp
@@ -25,3 +25,38 @@ ASL_TEST(from_literal)
asl::string_view s2 = ""_sv;
ASL_TEST_EXPECT(s2.is_empty());
}
+
+ASL_TEST(substr1)
+{
+ asl::string_view s1 = "abcd";
+
+ asl::string_view s2 = s1.substr(0);
+ ASL_TEST_ASSERT(s2.size() == 4);
+ ASL_TEST_EXPECT(memcmp(s2.data(), "abcd", 4) == 0);
+
+ s2 = s1.substr(2);
+ ASL_TEST_ASSERT(s2.size() == 2);
+ ASL_TEST_EXPECT(memcmp(s2.data(), "cd", 2) == 0);
+
+ s2 = s1.substr(4);
+ ASL_TEST_ASSERT(s2.size() == 0);
+}
+
+ASL_TEST(substr2)
+{
+ asl::string_view s1 = "abcd";
+
+ asl::string_view s2 = s1.substr(0, 4);
+ ASL_TEST_ASSERT(s2.size() == 4);
+ ASL_TEST_EXPECT(memcmp(s2.data(), "abcd", 4) == 0);
+
+ s2 = s1.substr(1, 2);
+ ASL_TEST_ASSERT(s2.size() == 2);
+ ASL_TEST_EXPECT(memcmp(s2.data(), "bc", 2) == 0);
+
+ s2 = s1.substr(4, 0);
+ ASL_TEST_ASSERT(s2.size() == 0);
+
+ s2 = s1.substr(1, 0);
+ ASL_TEST_ASSERT(s2.size() == 0);
+}