diff options
Diffstat (limited to 'libs/kstd')
43 files changed, 1053 insertions, 76 deletions
diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt index 002fb548..9c68feed 100644 --- a/libs/kstd/CMakeLists.txt +++ b/libs/kstd/CMakeLists.txt @@ -69,38 +69,12 @@ endif() if(BUILD_TESTING) find_package("Catch2") include("Catch") + include("BuildHostTests") - add_executable("kstd_tests") - add_executable("kstd::tests" ALIAS "kstd_tests") - - target_sources("kstd_tests" PRIVATE - "kstd/flat_map.test.cpp" - "kstd/format.test.cpp" - "kstd/vector.test.cpp" - "kstd/bits/observer_ptr.test.cpp" - "kstd/test_support/os_panic.test.cpp" - "kstd/string.test.cpp" - ) - - target_link_libraries("kstd_tests" PRIVATE - "Catch2::Catch2WithMain" - "kstd::lib" - ) - - set_target_properties("kstd_tests" PROPERTIES - EXCLUDE_FROM_ALL NO - ) + teachos_add_tests("kstd") if(COMMAND "enable_coverage") enable_coverage("kstd") enable_coverage("kstd_tests") endif() - - file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bht_results") - - catch_discover_tests("kstd::tests" - REPORTER junit - OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/bht_results" - OUTPUT_SUFFIX ".xml" - ) endif()
\ No newline at end of file diff --git a/libs/kstd/kstd/allocator b/libs/kstd/kstd/allocator.hpp index 0de0e10d..0de0e10d 100644 --- a/libs/kstd/kstd/allocator +++ b/libs/kstd/kstd/allocator.hpp diff --git a/libs/kstd/kstd/asm_ptr b/libs/kstd/kstd/asm_ptr.hpp index c06a8b52..c06a8b52 100644 --- a/libs/kstd/kstd/asm_ptr +++ b/libs/kstd/kstd/asm_ptr.hpp diff --git a/libs/kstd/kstd/bits/basic_string.hpp b/libs/kstd/kstd/bits/basic_string.hpp index 1675434c..a718bccc 100644 --- a/libs/kstd/kstd/bits/basic_string.hpp +++ b/libs/kstd/kstd/bits/basic_string.hpp @@ -1,10 +1,10 @@ #ifndef KSTD_BITS_BASIC_STRING_HPP #define KSTD_BITS_BASIC_STRING_HPP -#include <kstd/allocator> +#include <kstd/allocator.hpp> #include <kstd/bits/concepts.hpp> #include <kstd/os/error.hpp> -#include <kstd/ranges> +#include <kstd/ranges.hpp> #include <algorithm> #include <array> diff --git a/libs/kstd/kstd/bits/format/arg.hpp b/libs/kstd/kstd/bits/format/arg.hpp index e65b26fa..8271ca3d 100644 --- a/libs/kstd/kstd/bits/format/arg.hpp +++ b/libs/kstd/kstd/bits/format/arg.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_FORMAT_ARG_HPP #define KSTD_BITS_FORMAT_ARG_HPP -// IWYU pragma: private, include <kstd/format> +// IWYU pragma: private, include <kstd/format.hpp> #include <kstd/bits/format/error.hpp> #include <kstd/bits/format/fwd.hpp> diff --git a/libs/kstd/kstd/bits/format/args.hpp b/libs/kstd/kstd/bits/format/args.hpp index e8e31145..01735011 100644 --- a/libs/kstd/kstd/bits/format/args.hpp +++ b/libs/kstd/kstd/bits/format/args.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_FORMAT_ARGS_HPP #define KSTD_BITS_FORMAT_ARGS_HPP -// IWYU pragma: private, include <kstd/format> +// IWYU pragma: private, include <kstd/format.hpp> #include <kstd/bits/format/arg.hpp> #include <kstd/bits/format/context.hpp> diff --git a/libs/kstd/kstd/bits/format/context.hpp b/libs/kstd/kstd/bits/format/context.hpp index c166ba9c..d5f2f4d9 100644 --- a/libs/kstd/kstd/bits/format/context.hpp +++ b/libs/kstd/kstd/bits/format/context.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_FORMAT_CONTEXT_HPP #define KSTD_BITS_FORMAT_CONTEXT_HPP -// IWYU pragma: private, include <kstd/format> +// IWYU pragma: private, include <kstd/format.hpp> #include <kstd/bits/format/arg.hpp> #include <kstd/bits/format/output_buffer.hpp> diff --git a/libs/kstd/kstd/bits/format/formatter.hpp b/libs/kstd/kstd/bits/format/formatter.hpp index eb288294..c26907b2 100644 --- a/libs/kstd/kstd/bits/format/formatter.hpp +++ b/libs/kstd/kstd/bits/format/formatter.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_FORMATTER_HPP #define KSTD_BITS_FORMATTER_HPP -// IWYU pragma: private, include <kstd/format> +// IWYU pragma: private, include <kstd/format.hpp> #include <kstd/bits/format/context.hpp> #include <kstd/bits/format/error.hpp> diff --git a/libs/kstd/kstd/bits/format/formatter/cstring.hpp b/libs/kstd/kstd/bits/format/formatter/cstring.hpp index 553c8caf..12cb9c6f 100644 --- a/libs/kstd/kstd/bits/format/formatter/cstring.hpp +++ b/libs/kstd/kstd/bits/format/formatter/cstring.hpp @@ -5,6 +5,7 @@ #include <kstd/bits/format/formatter.hpp> #include <kstd/bits/format/formatter/string_view.hpp> +#include <cstddef> #include <string_view> namespace kstd @@ -24,6 +25,11 @@ namespace kstd { }; + template<std::size_t Size> + struct formatter<char[Size]> : formatter<char const *> // NOLINT + { + }; + } // namespace kstd #endif
\ No newline at end of file diff --git a/libs/kstd/kstd/bits/format/output_buffer.hpp b/libs/kstd/kstd/bits/format/output_buffer.hpp index fd7a2b4c..7e6f0575 100644 --- a/libs/kstd/kstd/bits/format/output_buffer.hpp +++ b/libs/kstd/kstd/bits/format/output_buffer.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_FORMAT_OUTPUT_BUFFER_HPP #define KSTD_BITS_FORMAT_OUTPUT_BUFFER_HPP -// IWYU pragma: private, include <kstd/format> +// IWYU pragma: private, include <kstd/format.hpp> #include <string_view> diff --git a/libs/kstd/kstd/bits/format/parse_context.hpp b/libs/kstd/kstd/bits/format/parse_context.hpp index cab8d726..81ed52cf 100644 --- a/libs/kstd/kstd/bits/format/parse_context.hpp +++ b/libs/kstd/kstd/bits/format/parse_context.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_FORMAT_PARSE_CONTEXT_HPP #define KSTD_BITS_FORMAT_PARSE_CONTEXT_HPP -// IWYU pragma: private, include <kstd/format> +// IWYU pragma: private, include <kstd/format.hpp> #include <kstd/bits/format/error.hpp> diff --git a/libs/kstd/kstd/bits/format/string.hpp b/libs/kstd/kstd/bits/format/string.hpp index a2b298d4..ab034e7c 100644 --- a/libs/kstd/kstd/bits/format/string.hpp +++ b/libs/kstd/kstd/bits/format/string.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_FORMAT_STRING_HPP #define KSTD_BITS_FORMAT_STRING_HPP -// IWYU pragma: private, include <kstd/format> +// IWYU pragma: private, include <kstd/format.hpp> #include <kstd/bits/format/context.hpp> #include <kstd/bits/format/error.hpp> diff --git a/libs/kstd/kstd/bits/format/vformat.cpp b/libs/kstd/kstd/bits/format/vformat.cpp index 1bf293a4..7210a0b6 100644 --- a/libs/kstd/kstd/bits/format/vformat.cpp +++ b/libs/kstd/kstd/bits/format/vformat.cpp @@ -1,6 +1,7 @@ -#include <kstd/format> -#include <kstd/string> +#include <kstd/format.hpp> +#include <kstd/string.hpp> +#include <algorithm> #include <cstddef> #include <iterator> #include <string_view> @@ -221,4 +222,23 @@ namespace kstd::bits::format return m_size; } + auto span_writer::push(std::string_view text) -> void + { + if (m_position < m_span.size() - 1) + { + auto space_left = m_span.size() - m_position; + auto to_copy = std::min(space_left, text.size()); + std::ranges::copy_n(text.begin(), to_copy, m_span.subspan(m_position).begin()); + m_position += to_copy; + } + } + + auto span_writer::push(char character) -> void + { + if (m_position < m_span.size() - 1) + { + m_span[m_position++] = character; + } + } + } // namespace kstd::bits::format
\ No newline at end of file diff --git a/libs/kstd/kstd/bits/format/vformat.hpp b/libs/kstd/kstd/bits/format/vformat.hpp index 2db56d17..63b41ab6 100644 --- a/libs/kstd/kstd/bits/format/vformat.hpp +++ b/libs/kstd/kstd/bits/format/vformat.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_FORMAT_VFORMAT_HPP #define KSTD_BITS_FORMAT_VFORMAT_HPP -// IWYU pragma: private, include <kstd/format> +// IWYU pragma: private, include <kstd/format.hpp> #include <kstd/bits/basic_string.hpp> #include <kstd/bits/format/args.hpp> @@ -11,8 +11,10 @@ #include <algorithm> #include <cstddef> #include <iterator> +#include <span> #include <string_view> #include <type_traits> +#include <utility> namespace kstd { @@ -28,7 +30,7 @@ namespace kstd //! @param args The arguments for the format string. auto vformat_to(output_buffer & buffer, std::string_view format, format_args args) -> void; - struct string_writer : output_buffer + struct string_writer final : output_buffer { auto push(std::string_view text) -> void final; auto push(char character) -> void final; @@ -40,7 +42,7 @@ namespace kstd }; //! A buffer that merely records the size of the output written to it. - struct size_recorder : output_buffer + struct size_recorder final : output_buffer { auto push(std::string_view text) -> void final; auto push(char character) -> void final; @@ -52,9 +54,9 @@ namespace kstd }; template<std::output_iterator<char> Output> - struct iterator_writer : output_buffer + struct iterator_writer final : output_buffer { - explicit iterator_writer(Output iterator) + constexpr explicit iterator_writer(Output iterator) : m_output{iterator} {} @@ -77,6 +79,25 @@ namespace kstd Output m_output{}; }; + struct span_writer final : output_buffer + { + constexpr explicit span_writer(std::span<char> span) + : m_span{span} + {} + + auto push(std::string_view text) -> void override; + auto push(char character) -> void override; + + [[nodiscard]] constexpr auto position() const noexcept -> std::size_t + { + return m_position; + } + + private: + std::size_t m_position{}; + std::span<char> m_span{}; + }; + } // namespace bits::format //! Format a given string with the provided arguments. @@ -108,6 +129,21 @@ namespace kstd return buffer.iterator(); } + //! Format a given string with the provided arguments. + //! + //! @param span The span to write to. + //! @param format The format string. + //! @param args The arguments for the format string. + //! @return A pair of the span written to and the next position to write to. + template<typename... ArgumentTypes> + auto format_to(std::span<char> span, format_string<std::type_identity_t<ArgumentTypes>...> format, + ArgumentTypes &&... args) -> std::pair<std::span<char>, std::size_t> + { + auto buffer = bits::format::span_writer{span}; + bits::format::vformat_to(buffer, format.str_view, make_format_args(std::forward<ArgumentTypes>(args)...).args); + return {span, buffer.position()}; + } + //! Determine the number of characters required to format the format string with the given arguments. //! //! @param format The format string. diff --git a/libs/kstd/kstd/bits/observer_ptr.hpp b/libs/kstd/kstd/bits/observer_ptr.hpp index 2593d7a4..e63e5d77 100644 --- a/libs/kstd/kstd/bits/observer_ptr.hpp +++ b/libs/kstd/kstd/bits/observer_ptr.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_OBSERVER_PTR_HPP #define KSTD_OBSERVER_PTR_HPP -// IWYU pragma: private, include <kstd/memory> +// IWYU pragma: private, include <kstd/memory.hpp> #include <kstd/os/error.hpp> diff --git a/libs/kstd/kstd/bits/observer_ptr.test.cpp b/libs/kstd/kstd/bits/observer_ptr.tests.cpp index f26fc09a..eca14ccd 100644 --- a/libs/kstd/kstd/bits/observer_ptr.test.cpp +++ b/libs/kstd/kstd/bits/observer_ptr.tests.cpp @@ -1,4 +1,4 @@ -#include <kstd/memory> +#include <kstd/memory.hpp> #include <kstd/test_support/os_panic.hpp> #include <catch2/catch_test_macros.hpp> diff --git a/libs/kstd/kstd/bits/print_sink.hpp b/libs/kstd/kstd/bits/print_sink.hpp index af765e06..a1e9b0d4 100644 --- a/libs/kstd/kstd/bits/print_sink.hpp +++ b/libs/kstd/kstd/bits/print_sink.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_BITS_PRINT_SINK_HPP #define KSTD_BITS_PRINT_SINK_HPP -// IWYU pragma: private, include <kstd/print> +// IWYU pragma: private, include <kstd/print.hpp> namespace kstd { diff --git a/libs/kstd/kstd/bits/shared_ptr.hpp b/libs/kstd/kstd/bits/shared_ptr.hpp index 57a89c0d..ce4bfb7f 100644 --- a/libs/kstd/kstd/bits/shared_ptr.hpp +++ b/libs/kstd/kstd/bits/shared_ptr.hpp @@ -6,7 +6,7 @@ #include <type_traits> #include <utility> -// IWYU pragma: private, include <kstd/memory> +// IWYU pragma: private, include <kstd/memory.hpp> namespace kstd { diff --git a/libs/kstd/kstd/bits/unique_ptr.hpp b/libs/kstd/kstd/bits/unique_ptr.hpp index 3d803b4a..1df18cf2 100644 --- a/libs/kstd/kstd/bits/unique_ptr.hpp +++ b/libs/kstd/kstd/bits/unique_ptr.hpp @@ -3,7 +3,7 @@ #include <utility> -// IWYU pragma: private, include <kstd/memory> +// IWYU pragma: private, include <kstd/memory.hpp> namespace kstd { diff --git a/libs/kstd/kstd/cstring b/libs/kstd/kstd/cstring.hpp index bd8b28d8..bd8b28d8 100644 --- a/libs/kstd/kstd/cstring +++ b/libs/kstd/kstd/cstring.hpp diff --git a/libs/kstd/kstd/ext/bitfield_enum b/libs/kstd/kstd/ext/bitfield_enum.hpp index 80fe9d29..80fe9d29 100644 --- a/libs/kstd/kstd/ext/bitfield_enum +++ b/libs/kstd/kstd/ext/bitfield_enum.hpp diff --git a/libs/kstd/kstd/flat_map b/libs/kstd/kstd/flat_map.hpp index e51eb918..31557760 100644 --- a/libs/kstd/kstd/flat_map +++ b/libs/kstd/kstd/flat_map.hpp @@ -3,7 +3,7 @@ #include <kstd/bits/flat_map.hpp> #include <kstd/os/error.hpp> -#include <kstd/vector> +#include <kstd/vector.hpp> #include <algorithm> #include <concepts> diff --git a/libs/kstd/kstd/flat_map.test.cpp b/libs/kstd/kstd/flat_map.tests.cpp index 9df03bb4..bfd02303 100644 --- a/libs/kstd/kstd/flat_map.test.cpp +++ b/libs/kstd/kstd/flat_map.tests.cpp @@ -1,4 +1,4 @@ -#include <kstd/flat_map> +#include <kstd/flat_map.hpp> #include <kstd/test_support/os_panic.hpp> diff --git a/libs/kstd/kstd/format b/libs/kstd/kstd/format.hpp index 5ed798db..5d7f4ae6 100644 --- a/libs/kstd/kstd/format +++ b/libs/kstd/kstd/format.hpp @@ -5,6 +5,7 @@ #include <kstd/bits/format/arg.hpp> #include <kstd/bits/format/args.hpp> #include <kstd/bits/format/context.hpp> +#include <kstd/bits/format/error.hpp> #include <kstd/bits/format/formatter.hpp> #include <kstd/bits/format/formatter/bool.hpp> #include <kstd/bits/format/formatter/byte.hpp> diff --git a/libs/kstd/kstd/format.test.cpp b/libs/kstd/kstd/format.tests.cpp index 6126605f..a34cf063 100644 --- a/libs/kstd/kstd/format.test.cpp +++ b/libs/kstd/kstd/format.tests.cpp @@ -1,7 +1,8 @@ -#include <kstd/format> +#include <kstd/format.hpp> #include <catch2/catch_test_macros.hpp> +#include <array> #include <iterator> #include <sstream> #include <string_view> @@ -116,6 +117,95 @@ SCENARIO("Formatting to an output iterator", "[format]") } } +SCENARIO("Formatting to a span", "[format]") +{ + GIVEN("a format string without any placeholders") + { + constexpr auto fmt = "This is a test"sv; + + WHEN("calling format without any arguments.") + { + auto buffer = std::array<char, 100>{}; + auto [span, length] = kstd::format_to(buffer, fmt); + + THEN("the unmodified string is written to the span") + { + REQUIRE(std::string_view{span.data(), length} == "This is a test"); + } + } + + WHEN("calling format with additional arguments") + { + auto buffer = std::array<char, 100>{}; + auto [span, length] = kstd::format_to(buffer, fmt, 1, 2, 3); + + THEN("the unmodified string is written to the span") + { + REQUIRE(std::string_view(span.data(), length) == "This is a test"); + } + } + + WHEN("the span is too small") + { + auto buffer = std::array<char, 4>{}; + auto [span, length] = kstd::format_to(buffer, fmt, 1, 2, 3); + + THEN("the written length is equal to the span size") + { + REQUIRE(length == span.size()); + } + + THEN("only part of the unmodified string is written to the span") + { + REQUIRE(std::string_view(span.data(), length) == "This"); + } + } + } + + GIVEN("a format string with placeholders") + { + constexpr auto fmt = "Here are some placeholders: {} {} {}"sv; + + WHEN("calling format with the same number of arguments as there are placeholders") + { + auto buffer = std::array<char, 100>{}; + auto [span, length] = kstd::format_to(buffer, fmt, 1, true, -100); + + THEN("the formatted string is written to the span") + { + REQUIRE(std::string_view{span.data(), length} == "Here are some placeholders: 1 true -100"); + } + } + + WHEN("calling format with too many arguments") + { + auto buffer = std::array<char, 100>{}; + auto [span, length] = kstd::format_to(buffer, fmt, 2, false, -200, 4, 5, 6); + + THEN("the formatted string is written to the span") + { + REQUIRE(std::string_view{span.data(), length} == "Here are some placeholders: 2 false -200"); + } + } + + WHEN("the span is too small") + { + auto buffer = std::array<char, 4>{}; + auto [span, length] = kstd::format_to(buffer, fmt, 2, false, -200, 4, 5, 6); + + THEN("the written length is equal to the span size") + { + REQUIRE(length == span.size()); + } + + THEN("only part of the unmodified string is written to the span") + { + REQUIRE(std::string_view(span.data(), length) == "Here"); + } + } + } +} + SCENARIO("Determining formatted size") { GIVEN("a format string without any placeholders") diff --git a/libs/kstd/kstd/libc/string.cpp b/libs/kstd/kstd/libc/string.cpp index b7cdb82e..15ecc70f 100644 --- a/libs/kstd/kstd/libc/string.cpp +++ b/libs/kstd/kstd/libc/string.cpp @@ -1,4 +1,4 @@ -#include <kstd/cstring> +#include <kstd/cstring.hpp> #include <algorithm> #include <bit> diff --git a/libs/kstd/kstd/memory b/libs/kstd/kstd/memory.hpp index f108c6d6..f108c6d6 100644 --- a/libs/kstd/kstd/memory +++ b/libs/kstd/kstd/memory.hpp diff --git a/libs/kstd/kstd/mutex.cpp b/libs/kstd/kstd/mutex.cpp index 73876572..c1c5b190 100644 --- a/libs/kstd/kstd/mutex.cpp +++ b/libs/kstd/kstd/mutex.cpp @@ -1,4 +1,4 @@ -#include <kstd/mutex> +#include <kstd/mutex.hpp> #include <kstd/os/error.hpp> diff --git a/libs/kstd/kstd/mutex b/libs/kstd/kstd/mutex.hpp index b2a31aa9..b2a31aa9 100644 --- a/libs/kstd/kstd/mutex +++ b/libs/kstd/kstd/mutex.hpp diff --git a/libs/kstd/kstd/posix.hpp b/libs/kstd/kstd/posix.hpp new file mode 100644 index 00000000..12bd5ec0 --- /dev/null +++ b/libs/kstd/kstd/posix.hpp @@ -0,0 +1,85 @@ +#ifndef KSTD_CERRNO_HPP +#define KSTD_CERRNO_HPP + +namespace kstd::posix +{ + + constexpr auto static inline eafnosupport = 1; + constexpr auto static inline eaddrinuse = 2; + constexpr auto static inline eaddrnotavail = 3; + constexpr auto static inline eisconn = 4; + constexpr auto static inline e2big = 5; + constexpr auto static inline edom = 6; + constexpr auto static inline efault = 7; + constexpr auto static inline ebadf = 8; + constexpr auto static inline ebadmsg = 9; + constexpr auto static inline epipe = 10; + constexpr auto static inline econnaborted = 11; + constexpr auto static inline ealready = 12; + constexpr auto static inline econnrefused = 13; + constexpr auto static inline econnreset = 14; + constexpr auto static inline exdev = 15; + constexpr auto static inline edestaddrreq = 16; + constexpr auto static inline ebusy = 17; + constexpr auto static inline enotempty = 18; + constexpr auto static inline enoexec = 19; + constexpr auto static inline eexist = 20; + constexpr auto static inline efbig = 21; + constexpr auto static inline enametoolong = 22; + constexpr auto static inline enosys = 23; + constexpr auto static inline ehostunreach = 24; + constexpr auto static inline eidrm = 25; + constexpr auto static inline eilseq = 26; + constexpr auto static inline enotty = 27; + constexpr auto static inline eintr = 28; + constexpr auto static inline einval = 29; + constexpr auto static inline espipe = 30; + constexpr auto static inline eio = 31; + constexpr auto static inline eisdir = 32; + constexpr auto static inline emsgsize = 33; + constexpr auto static inline enetdown = 34; + constexpr auto static inline enetreset = 35; + constexpr auto static inline enetunreach = 36; + constexpr auto static inline enobufs = 37; + constexpr auto static inline echild = 38; + constexpr auto static inline enolink = 39; + constexpr auto static inline enolck = 40; + constexpr auto static inline enomsg = 41; + constexpr auto static inline enoprotoopt = 42; + constexpr auto static inline enospc = 43; + constexpr auto static inline enodev = 44; + constexpr auto static inline enxio = 45; + constexpr auto static inline enoent = 46; + constexpr auto static inline esrch = 47; + constexpr auto static inline enotdir = 48; + constexpr auto static inline enotsock = 49; + constexpr auto static inline enotconn = 50; + constexpr auto static inline enomem = 51; + constexpr auto static inline enotsup = 52; + constexpr auto static inline ecanceled = 53; + constexpr auto static inline einprogress = 54; + constexpr auto static inline eperm = 55; + constexpr auto static inline eopnotsupp = 56; + constexpr auto static inline ewouldblock = 57; + constexpr auto static inline eownerdead = 58; + constexpr auto static inline eacces = 59; + constexpr auto static inline eproto = 60; + constexpr auto static inline eprotonosupport = 61; + constexpr auto static inline erofs = 62; + constexpr auto static inline edeadlk = 63; + constexpr auto static inline eagain = 64; + constexpr auto static inline erange = 65; + constexpr auto static inline esocktnosupport = 66; + constexpr auto static inline enotrecoverable = 67; + constexpr auto static inline etxtbsy = 68; + constexpr auto static inline etimedout = 69; + constexpr auto static inline emfile = 70; + constexpr auto static inline enfile = 71; + constexpr auto static inline emlink = 72; + constexpr auto static inline eloop = 73; + constexpr auto static inline eoverflow = 74; + constexpr auto static inline eprototype = 75; + +} // namespace kstd::posix + +#endif
\ No newline at end of file diff --git a/libs/kstd/kstd/print b/libs/kstd/kstd/print.hpp index 1033f722..0d37efbe 100644 --- a/libs/kstd/kstd/print +++ b/libs/kstd/kstd/print.hpp @@ -2,7 +2,7 @@ #define KSTD_PRINT #include <kstd/bits/print_sink.hpp> // IWYU pragma: export -#include <kstd/format> +#include <kstd/format.hpp> #include <kstd/os/print.hpp> #include <type_traits> @@ -26,6 +26,7 @@ namespace kstd //! @qualifier kernel-defined //! Format the given error string using the given arguments and print it to the currently active output device. //! + //! @param sink The output sink to print to. //! @param format The format string //! @param args The arguments to use to place in the format string's placeholders. template<typename... Args> @@ -54,6 +55,7 @@ namespace kstd //! Format the given error string using the given arguments and print it, including a newline, to the currently active //! output device. //! + //! @param sink The output sink to print to. //! @param format The format string //! @param args The arguments template<typename... Args> diff --git a/libs/kstd/kstd/ranges b/libs/kstd/kstd/ranges.hpp index 78c3adbf..78c3adbf 100644 --- a/libs/kstd/kstd/ranges +++ b/libs/kstd/kstd/ranges.hpp diff --git a/libs/kstd/kstd/result.hpp b/libs/kstd/kstd/result.hpp new file mode 100644 index 00000000..7b027a8d --- /dev/null +++ b/libs/kstd/kstd/result.hpp @@ -0,0 +1,35 @@ +#ifndef KSTD_RESULT_HPP +#define KSTD_RESULT_HPP + +#include <kstd/system_error.hpp> + +#include <expected> +#include <type_traits> +#include <utility> + +namespace kstd +{ + + template<typename SuccessType> + using result = std::expected<SuccessType, error_code>; + + template<typename SuccessType> + requires(!std::is_void_v<SuccessType>) + constexpr auto inline success(SuccessType && value) -> result<std::remove_cvref_t<SuccessType>> + { + return result<std::remove_cvref_t<SuccessType>>{std::in_place, std::forward<SuccessType>(value)}; + } + + constexpr auto inline success() -> result<void> + { + return result<void>{std::in_place}; + } + + constexpr auto inline failure(error_code error) -> std::unexpected<error_code> + { + return std::unexpected(error); + } + +} // namespace kstd + +#endif
\ No newline at end of file diff --git a/libs/kstd/kstd/stack b/libs/kstd/kstd/stack.hpp index 02e44ea4..27e693f2 100644 --- a/libs/kstd/kstd/stack +++ b/libs/kstd/kstd/stack.hpp @@ -1,7 +1,7 @@ #ifndef KSTD_STACK_HPP #define KSTD_STACK_HPP -#include <kstd/vector> +#include <kstd/vector.hpp> #include <initializer_list> #include <utility> diff --git a/libs/kstd/kstd/string b/libs/kstd/kstd/string.hpp index 4a67a3a4..9978affc 100644 --- a/libs/kstd/kstd/string +++ b/libs/kstd/kstd/string.hpp @@ -7,9 +7,9 @@ #include <kstd/bits/format/formatter/cstring.hpp> #include <kstd/bits/format/formatter/integral.hpp> #include <kstd/bits/format/vformat.hpp> -#include <kstd/cstring> +#include <kstd/cstring.hpp> #include <kstd/os/error.hpp> -#include <kstd/vector> +#include <kstd/vector.hpp> #include <concepts> #include <cstddef> diff --git a/libs/kstd/kstd/string.test.cpp b/libs/kstd/kstd/string.tests.cpp index e11877e5..b8fa1139 100644 --- a/libs/kstd/kstd/string.test.cpp +++ b/libs/kstd/kstd/string.tests.cpp @@ -1,6 +1,6 @@ -#include <kstd/string> +#include <kstd/string.hpp> -#include <kstd/allocator> +#include <kstd/allocator.hpp> #include <kstd/test_support/os_panic.hpp> #include <catch2/catch_test_macros.hpp> diff --git a/libs/kstd/kstd/system_error.hpp b/libs/kstd/kstd/system_error.hpp new file mode 100644 index 00000000..09efb097 --- /dev/null +++ b/libs/kstd/kstd/system_error.hpp @@ -0,0 +1,636 @@ +#ifndef KSTD_SYSTEM_ERROR_HPP +#define KSTD_SYSTEM_ERROR_HPP + +#include <kstd/format.hpp> +#include <kstd/posix.hpp> // IWYU pragma: export + +#include <compare> +#include <cstdint> +#include <functional> +#include <string_view> +#include <type_traits> + +namespace kstd +{ + + struct error_condition; + struct error_code; + + //! Determine if a given enumeration type is an error condition enumeration. + //! + //! An enumeration type is an error condition enumeration if it defines generic, system-level error conditions. + //! Specific subsystem error enumerations on the other hand are not generic enough to be considered error conditions + //! and are thus called error codes. + //! + //! @note Types may opt in to being an error condition enumeration by specializing this class template. + //! + //! @tparam CandidateType The type to check. + template<typename CandidateType> + requires(std::is_enum_v<CandidateType>) + struct is_error_condition_enum : std::false_type + { + }; + + //! Determine if a given enumeration type is an error condition enumeration. + //! + //! @see is_error_condition_enum + //! + //! @tparam CandidateType The type to check. + template<typename CandidateType> + constexpr auto inline is_error_condition_enum_v = is_error_condition_enum<CandidateType>::value; + + //! Determine if a given enumeration type is an error condition enumeration. + //! + //! @see is_error_condition_enum + //! @tparam CandidateType The type to check. + template<typename CandidateType> + concept error_condition_enum = std::is_enum_v<CandidateType> && is_error_condition_enum_v<CandidateType>; + + //! Determine if a given enumeration type is an error code enumeration. + //! + //! An enumeration type is an error code enumeration if it defines specific, subsystem-level error codes. + //! Generic error conditions are not specific enough to be considered error codes and are thus called error + //! conditions. + //! + //! @note Types may opt in to being an error code enumeration by specializing this class template. + //! + //! @tparam CandidateType The type to check. + template<typename CandidateType> + requires(std::is_enum_v<CandidateType>) + struct is_error_code_enum : std::false_type + { + }; + + //! Determine if a given enumeration type is an error code enumeration. + //! + //! @see is_error_code_enum + //! + //! @tparam CandidateType The type to check. + template<typename CandidateType> + constexpr auto inline is_error_code_enum_v = is_error_code_enum<CandidateType>::value; + + //! Determine if a given enumeration type is an error code enumeration. + //! + //! @see is_error_code_enum + //! + //! @tparam CandidateType The type to check. + template<typename CandidateType> + concept error_code_enum = std::is_enum_v<CandidateType> && is_error_code_enum_v<CandidateType>; + + //! A category of error codes or conditions. + //! + //! An error category is a group of related error codes or conditions. Each error code or condition belongs to exactly + //! one error category. Error categories are used to provide additional context and information about the error codes + //! or conditions they contain. They can also be used to compare error codes or conditions from different categories. + //! + //! Subsystems shall defined their own error categories for their error codes, by inheriting from this class. + struct error_category + { + constexpr error_category() noexcept = default; + + error_category(error_category const &) = delete; + + constexpr virtual ~error_category() = default; + + auto operator=(error_category const &) -> error_category & = delete; + + //! Get the name of this error category. + [[nodiscard]] constexpr auto virtual name() const noexcept -> std::string_view = 0; + + //! Get the default error condition for a given error code value in this category. + //! + //! @param value The error code value to get the default error condition for. + //! @return The default error condition for the given error code value in this category. + [[nodiscard]] constexpr auto virtual default_error_condition(int value) const noexcept -> error_condition; + + //! Check if a given error code value is equivalent to a given error condition in this category. + //! + //! @param value The error code value to check. + //! @param other The error condition to compare against. + //! @return True if the error code value is equivalent to the error condition in this category, false otherwise. + [[nodiscard]] constexpr auto virtual equivalent(int value, error_condition const & other) const noexcept -> bool; + + //! Check if a given error code is equivalent to a given error condition in this category. + //! + //! @param code The error code to check. + //! @param condition The error condition to compare against. + //! @return True if the error code is equivalent to the error condition in this category, false otherwise. + [[nodiscard]] constexpr auto virtual equivalent(error_code const & code, int condition) const noexcept -> bool; + + //! Get the message for a given error code value in this category. + //! + //! @param value The error code value to get the message for. + //! @return The message for the given error code value in this category. + [[nodiscard]] constexpr auto virtual message(int value) const noexcept -> std::string_view = 0; + + //! Check if this error category is equal to another one. + [[nodiscard]] constexpr auto operator==(error_category const & other) const noexcept -> bool + { + return this == &other; + } + + //! Lexicographically compare this error category to a different one. + [[nodiscard]] constexpr auto operator<=>(error_category const & other) const noexcept -> std::strong_ordering + { + return std::compare_three_way{}(this, &other); + } + }; + + //! An error condition represents a generic, system-level error. + //! + //! Error conditions are used to represent errors to be tested for. + struct error_condition + { + //! Construct an error condition with a default value and category. + constexpr error_condition() noexcept; + + //! Construct an error condition with a specific value and category. + //! + //! @param value The error code value. + //! @param category The error category. + constexpr error_condition(int value, error_category const & category) noexcept + : m_value{value} + , m_category{&category} + {} + + //! Construct an error condition from an error condition enumeration value. + //! + //! @tparam Enum The error condition enumeration type. + //! @param value The error condition enumeration value. + template<error_condition_enum Enum> + constexpr error_condition(Enum value) noexcept + : error_condition{make_error_condition(value)} + {} + + //! Assign an error condition enumeration value to this error condition. + //! + //! @tparam Enum The error condition enumeration type. + //! @param value The error condition enumeration value. + template<error_condition_enum Enum> + constexpr auto operator=(Enum value) noexcept -> error_condition & + { + *this = make_error_condition(value); + } + + //! Assign a new value and category to this error condition. + //! + //! @param value The new error code value. + //! @param category The new error category. + constexpr auto assign(int value, error_category const & category) noexcept -> void + { + m_value = value; + m_category = &category; + } + + //! Clear this error condition. + //! + //! This sets the value to 0 and the category to the generic error category. + constexpr auto clear() noexcept -> void; + + //! Get the raw error code value of this error condition. + [[nodiscard]] constexpr auto value() const noexcept -> int + { + return m_value; + } + + //! Get the error category of this error condition. + [[nodiscard]] constexpr auto category() const noexcept -> error_category const & + { + return *m_category; + } + + //! Get the message associated with this error condition based on its value and category. + [[nodiscard]] constexpr auto message() const noexcept -> std::string_view + { + return m_category->message(m_value); + } + + //! Check if this error condition holds an error. + //! + //! @return @p true iff. this error condition holds a non-zero value, @p false otherwise. + [[nodiscard]] constexpr explicit operator bool() const noexcept + { + return m_value != 0; + } + + //! Check if two error conditions are equal. + //! + //! Error conditions are considered equal if they hold the same value and reference the same category. + [[nodiscard]] constexpr auto friend operator==(error_condition const & lhs, error_condition const & rhs) noexcept + -> bool + { + return lhs.category() == rhs.category() && lhs.value() == rhs.value(); + } + + //! Lexicographically compare two error conditions. + [[nodiscard]] constexpr auto friend operator<=>(error_condition const & lhs, error_condition const & rhs) noexcept + -> std::strong_ordering + { + if (auto result = lhs.category() <=> rhs.category(); result != std::strong_ordering::equal) + { + return result; + } + + return lhs.value() <=> rhs.value(); + } + + private: + int m_value{}; + error_category const * m_category{}; + }; + + //! An error code represents a specific, subsystem-level error. + //! + //! Error codes are used to represent errors that are specific to a subsystem. Equivalence between error codes and + //! error conditions can be defined per each error enumeration type. + struct error_code + { + //! Construct an error code with a default value and category. + constexpr error_code() noexcept; + + //! Construct an error code with a specific value and category. + constexpr error_code(int value, error_category const & category) noexcept + : m_value{value} + , m_category{&category} + {} + + //! Construct an error code from an error code enumeration value. + //! + //! @tparam Enum The error code enumeration type. + //! @param value The error code enumeration value. + template<error_code_enum Enum> + constexpr error_code(Enum value) noexcept + : error_code{make_error_code(value)} + {} + + //! Assign an error code enumeration value to this error code. + //! + //! The category is chosen based on the enumeration type of the value. + //! @tparam Enum The error code enumeration type. + //! @param value The error code enumeration value. + template<error_code_enum Enum> + constexpr auto operator=(Enum value) noexcept -> error_code & + { + return *this = make_error_code(value); + } + + //! Assign a new value and category to this error code. + //! + //! @param value The new error code value. + //! @param category The new error code category. + constexpr auto assign(int value, error_category const & category) noexcept -> void + { + m_value = value; + m_category = &category; + } + + //! Clear this error code. + constexpr auto clear() noexcept -> void; + + //! Get the raw error code value of this error code. + [[nodiscard]] constexpr auto value() const noexcept -> int + { + return m_value; + } + + //! Get the error category of this error code. + [[nodiscard]] constexpr auto category() const noexcept -> error_category const & + { + return *m_category; + } + + //! Get and error condition that is equivalent to this error code. + [[nodiscard]] constexpr auto default_error_condition() const noexcept -> error_condition + { + return m_category->default_error_condition(m_value); + } + + //! Get the message associated with this error code based on its value and category. + [[nodiscard]] constexpr auto message() const noexcept -> std::string_view + { + return m_category->message(m_value); + } + + //! Check if this error code holds an error. + //! + //! @return @p true iff. this error code holds a non-zero value, @p false otherwise. + [[nodiscard]] constexpr explicit operator bool() const noexcept + { + return m_value != 0; + } + + //! Check if two error codes are equal. + //! + //! Error codes are considered equal if they hold the same value and reference the same category. + [[nodiscard]] constexpr auto friend operator==(error_code const & lhs, error_code const & rhs) noexcept -> bool + { + return lhs.category() == rhs.category() && lhs.value() == rhs.value(); + } + + //! Lexicographically compare two error codes. + [[nodiscard]] constexpr auto friend operator<=>(error_code const & lhs, error_code const & rhs) noexcept + -> std::strong_ordering + { + if (auto result = lhs.category() <=> rhs.category(); result != std::strong_ordering::equal) + { + return result; + } + + return lhs.value() <=> rhs.value(); + } + + private: + int m_value{}; + error_category const * m_category{}; + }; + + enum struct errc : std::uint32_t + { + address_family_not_supported = posix::eafnosupport, + address_in_use = posix::eaddrinuse, + address_not_available = posix::eaddrnotavail, + already_connected = posix::eisconn, + argument_list_too_long = posix::e2big, + argument_out_of_domain = posix::edom, + bad_address = posix::efault, + bad_file_descriptor = posix::ebadf, + bad_message = posix::ebadmsg, + broken_pipe = posix::epipe, + connection_aborted = posix::econnaborted, + connection_already_in_progress = posix::ealready, + connection_refused = posix::econnrefused, + connection_reset = posix::econnreset, + cross_device_link = posix::exdev, + destination_address_required = posix::edestaddrreq, + device_or_resource_busy = posix::ebusy, + directory_not_empty = posix::enotempty, + executable_format_error = posix::enoexec, + file_exists = posix::eexist, + file_too_large = posix::efbig, + filename_too_long = posix::enametoolong, + function_not_supported = posix::enosys, + host_unreachable = posix::ehostunreach, + identifier_removed = posix::eidrm, + illegal_byte_sequence = posix::eilseq, + inappropriate_io_control_operation = posix::enotty, + interrupted = posix::eintr, + invalid_argument = posix::einval, + invalid_seek = posix::espipe, + io_error = posix::eio, + is_a_directory = posix::eisdir, + message_size = posix::emsgsize, + network_down = posix::enetdown, + network_reset = posix::enetreset, + network_unreachable = posix::enetunreach, + no_buffer_space = posix::enobufs, + no_child_process = posix::echild, + no_link = posix::enolink, + no_lock_available = posix::enolck, + no_message = posix::enomsg, + no_protocol_option = posix::enoprotoopt, + no_space_on_device = posix::enospc, + no_such_device_or_address = posix::enxio, + no_such_device = posix::enodev, + no_such_file_or_directory = posix::enoent, + no_such_process = posix::esrch, + not_a_directory = posix::enotdir, + not_a_socket = posix::enotsock, + not_connected = posix::enotconn, + not_enough_memory = posix::enomem, + not_supported = posix::enotsup, + operation_canceled = posix::ecanceled, + operation_in_progress = posix::einprogress, + operation_not_permitted = posix::eperm, + operation_not_supported = posix::eopnotsupp, + operation_would_block = posix::ewouldblock, + owner_dead = posix::eownerdead, + permission_denied = posix::eacces, + protocol_error = posix::eproto, + protocol_not_supported = posix::eprotonosupport, + read_only_file_system = posix::erofs, + resource_deadlock_would_occur = posix::edeadlk, + resource_unavailable_try_again = posix::eagain, + result_out_of_range = posix::erange, + state_not_recoverable = posix::enotrecoverable, + text_file_busy = posix::etxtbsy, + timed_out = posix::etimedout, + too_many_files_open_in_system = posix::enfile, + too_many_files_open = posix::emfile, + too_many_links = posix::emlink, + too_many_symbolic_link_levels = posix::eloop, + value_too_large = posix::eoverflow, + wrong_protocol_type = posix::eprototype, + }; + + //! Mark the kstd::errc enumeration as an error condition enumeration. + template<> + struct is_error_condition_enum<errc> : std::true_type + { + }; + + namespace bits + { + constexpr auto to_message(errc error) -> std::string_view + { + switch (error) + { + // clang-format off + case errc::address_family_not_supported: return "address family not supported"; + case errc::address_in_use: return "address in use"; + case errc::address_not_available: return "address not available"; + case errc::already_connected: return "already connected"; + case errc::argument_list_too_long: return "argument list too long"; + case errc::argument_out_of_domain: return "argument out of domain"; + case errc::bad_address: return "bad address"; + case errc::bad_file_descriptor: return "bad file descriptor"; + case errc::bad_message: return "bad message"; + case errc::broken_pipe: return "broken pipe"; + case errc::connection_aborted: return "connection aborted"; + case errc::connection_already_in_progress: return "connection already in progress"; + case errc::connection_refused: return "connection refused"; + case errc::connection_reset: return "connection reset"; + case errc::cross_device_link: return "cross device link"; + case errc::destination_address_required: return "destination address required"; + case errc::device_or_resource_busy: return "device or resource busy"; + case errc::directory_not_empty: return "directory not empty"; + case errc::executable_format_error: return "invalid executable format"; + case errc::file_exists: return "file exists"; + case errc::file_too_large: return "file too large"; + case errc::filename_too_long: return "filename too long"; + case errc::function_not_supported: return "function not supported"; + case errc::host_unreachable: return "host unreachable"; + case errc::identifier_removed: return "identifier removed"; + case errc::illegal_byte_sequence: return "illegal byte sequence"; + case errc::inappropriate_io_control_operation: return "inappropriate io control operation"; + case errc::interrupted: return "system call interrupted"; + case errc::invalid_argument: return "invalid argument"; + case errc::invalid_seek: return "invalid seek"; + case errc::io_error: return "input/output error"; + case errc::is_a_directory: return "is a directory"; + case errc::message_size: return "message size"; + case errc::network_down: return "network down"; + case errc::network_reset: return "network reset"; + case errc::network_unreachable: return "network unreachable"; + case errc::no_buffer_space: return "no buffer space"; + case errc::no_child_process: return "no child process"; + case errc::no_link: return "no link"; + case errc::no_lock_available: return "no lock available"; + case errc::no_message: return "no message"; + case errc::no_protocol_option: return "no protocol option"; + case errc::no_space_on_device: return "no space on device"; + case errc::no_such_device: return "no such device"; + case errc::no_such_device_or_address: return "no such device or address"; + case errc::no_such_file_or_directory: return "no such file or directory"; + case errc::no_such_process: return "no such process"; + case errc::not_a_directory: return "not a directory"; + case errc::not_a_socket: return "not a socket"; + case errc::not_connected: return "not connected"; + case errc::not_enough_memory: return "not enough memory"; + case errc::not_supported: return "not supported"; + case errc::operation_canceled: return "operation canceled"; + case errc::operation_in_progress: return "operation in progress"; + case errc::operation_not_permitted: return "operation not permitted"; + case errc::operation_not_supported: return "operation not supported"; + case errc::operation_would_block: return "operation would block"; + case errc::owner_dead: return "owner dead"; + case errc::permission_denied: return "permission denied"; + case errc::protocol_error: return "protocol error"; + case errc::protocol_not_supported: return "protocol not supported"; + case errc::read_only_file_system: return "read only file system"; + case errc::resource_deadlock_would_occur: return "resource deadlock would occur"; + case errc::resource_unavailable_try_again: return "resource unavailable, try again"; + case errc::result_out_of_range: return "result out of range"; + case errc::state_not_recoverable: return "state not recoverable"; + case errc::text_file_busy: return "text file busy"; + case errc::timed_out: return "timed out"; + case errc::too_many_files_open: return "too many files open"; + case errc::too_many_files_open_in_system: return "too many files open in system"; + case errc::too_many_links: return "too many links"; + case errc::too_many_symbolic_link_levels: return "too many symbolic link levels"; + case errc::value_too_large: return "value too large"; + case errc::wrong_protocol_type: return "wrong protocol type"; + default: return "unknown error"; + // clang-format on + } + } + + struct generic_category_t final : error_category + { + [[nodiscard]] constexpr auto name() const noexcept -> std::string_view override + { + return "generic"; + } + + [[nodiscard]] constexpr auto message(int value) const noexcept -> std::string_view override + { + return to_message(static_cast<errc>(value)); + } + } constexpr inline generic_category_instance{}; + + struct system_category_t final : error_category + { + [[nodiscard]] constexpr auto name() const noexcept -> std::string_view override + { + return "system"; + } + + [[nodiscard]] constexpr auto message(int value) const noexcept -> std::string_view override + { + return to_message(static_cast<errc>(value)); + } + } constexpr inline system_category_instance{}; + } // namespace bits + + //! Get a reference to the generic error category. + constexpr auto inline generic_category() noexcept -> error_category const & + { + return bits::generic_category_instance; + } + + //! Get a reference to the system error category. + constexpr auto inline system_category() noexcept -> error_category const & + { + return bits::system_category_instance; + } + + constexpr auto inline error_category::default_error_condition(int value) const noexcept -> error_condition + { + return error_condition{value, *this}; + } + + constexpr auto inline error_category::equivalent(int value, error_condition const & other) const noexcept -> bool + { + return default_error_condition(value) == other; + } + + constexpr auto error_category::equivalent(error_code const & code, int condition) const noexcept -> bool + { + return *this == code.category() && code.value() == condition; + } + + constexpr error_condition::error_condition() noexcept + : error_condition{0, generic_category()} + {} + + constexpr auto error_condition::clear() noexcept -> void + { + m_value = 0; + m_category = &generic_category(); + } + + constexpr auto operator==(error_code const & code, error_condition const & condition) noexcept -> bool + { + return code.category().equivalent(code.value(), condition) || + condition.category().equivalent(code, condition.value()); + } + + constexpr error_code::error_code() noexcept + : error_code{0, system_category()} {}; + + constexpr auto error_code::clear() noexcept -> void + { + m_value = 0; + m_category = &system_category(); + } + + //! Create an error code from an kstd::errc enumeration value. + [[nodiscard]] constexpr auto inline make_error_code(errc const value) noexcept -> error_code + { + return {static_cast<int>(value), generic_category()}; + } + + //! Create an error condition from an kstd::errc enumeration value. + [[nodiscard]] constexpr auto inline make_error_condition(errc const value) noexcept -> error_condition + { + return {static_cast<int>(value), generic_category()}; + } + + //! Enable formatting of kstd::error_code + //! + //! There are currently no valid format specifiers for error codes. + template<> + struct formatter<error_code> + { + constexpr auto parse(format_parse_context & context) -> format_parse_context::iterator + { + auto it = context.begin(); + if (it != context.end() && *it != '}') + { + bits::format::error("Invalid specifier for string_view."); + } + return it; + } + + auto format(error_code const & error, format_context & context) const -> void + { + context.push(error.category().name()); + context.push(':'); + formatter<int>{}.format(error.value(), context); + context.push(':'); + context.push(error.message()); + } + }; + +} // namespace kstd + +#endif diff --git a/libs/kstd/kstd/system_error.tests.cpp b/libs/kstd/kstd/system_error.tests.cpp new file mode 100644 index 00000000..59e11926 --- /dev/null +++ b/libs/kstd/kstd/system_error.tests.cpp @@ -0,0 +1,100 @@ +#include <kstd/system_error.hpp> + +#include <catch2/catch_test_macros.hpp> +#include <catch2/generators/catch_generators.hpp> + +SCENARIO("Error condition initialization and construction", "[kstd][system_error]") +{ + GIVEN("An empty context") + { + WHEN("constructing by default") + { + auto error = kstd::error_condition{}; + + THEN("the category is equal to generic_category") + { + REQUIRE(error.category() == kstd::generic_category()); + } + + THEN("the value is 0") + { + REQUIRE(error.value() == 0); + } + + THEN("conversion to bool yields false") + { + REQUIRE_FALSE(error); + } + } + } +} + +SCENARIO("Error code initialization and construction", "[kstd][system_error]") +{ + GIVEN("An empty context") + { + WHEN("constructing by default") + { + auto error = kstd::error_code{}; + + THEN("the category is equal to system_category") + { + REQUIRE(error.category() == kstd::system_category()); + } + + THEN("the value is 0") + { + REQUIRE(error.value() == 0); + } + + THEN("conversion to bool yields false") + { + REQUIRE_FALSE(error); + } + } + } +} + +SCENARIO("Error code messages", "[kstd][system_error]") +{ + GIVEN("An error code") + { + auto enumerator = GENERATE( + kstd::errc::address_family_not_supported, kstd::errc::address_in_use, kstd::errc::address_not_available, + kstd::errc::already_connected, kstd::errc::argument_list_too_long, kstd::errc::argument_out_of_domain, + kstd::errc::bad_address, kstd::errc::bad_file_descriptor, kstd::errc::bad_message, kstd::errc::broken_pipe, + kstd::errc::connection_aborted, kstd::errc::connection_already_in_progress, kstd::errc::connection_refused, + kstd::errc::connection_reset, kstd::errc::cross_device_link, kstd::errc::destination_address_required, + kstd::errc::device_or_resource_busy, kstd::errc::directory_not_empty, kstd::errc::executable_format_error, + kstd::errc::file_exists, kstd::errc::file_too_large, kstd::errc::filename_too_long, + kstd::errc::function_not_supported, kstd::errc::host_unreachable, kstd::errc::identifier_removed, + kstd::errc::illegal_byte_sequence, kstd::errc::inappropriate_io_control_operation, kstd::errc::interrupted, + kstd::errc::invalid_argument, kstd::errc::invalid_seek, kstd::errc::io_error, kstd::errc::is_a_directory, + kstd::errc::message_size, kstd::errc::network_down, kstd::errc::network_reset, kstd::errc::network_unreachable, + kstd::errc::no_buffer_space, kstd::errc::no_child_process, kstd::errc::no_link, kstd::errc::no_lock_available, + kstd::errc::no_message, kstd::errc::no_protocol_option, kstd::errc::no_space_on_device, + kstd::errc::no_such_device_or_address, kstd::errc::no_such_device, kstd::errc::no_such_file_or_directory, + kstd::errc::no_such_process, kstd::errc::not_a_directory, kstd::errc::not_a_socket, kstd::errc::not_connected, + kstd::errc::not_enough_memory, kstd::errc::not_supported, kstd::errc::operation_canceled, + kstd::errc::operation_in_progress, kstd::errc::operation_not_permitted, kstd::errc::operation_not_supported, + kstd::errc::operation_would_block, kstd::errc::owner_dead, kstd::errc::permission_denied, + kstd::errc::protocol_error, kstd::errc::protocol_not_supported, kstd::errc::read_only_file_system, + kstd::errc::resource_deadlock_would_occur, kstd::errc::resource_unavailable_try_again, + kstd::errc::result_out_of_range, kstd::errc::state_not_recoverable, kstd::errc::text_file_busy, + kstd::errc::timed_out, kstd::errc::too_many_files_open_in_system, kstd::errc::too_many_files_open, + kstd::errc::too_many_links, kstd::errc::too_many_symbolic_link_levels, kstd::errc::value_too_large, + kstd::errc::wrong_protocol_type); + + auto error = kstd::make_error_code(enumerator); + + WHEN("getting the message") + { + auto message = error.message(); + + THEN("the message is not 'unknown error'") + { + REQUIRE(message != "unknown error"); + } + } + } +} diff --git a/libs/kstd/kstd/test_support/os_panic.test.cpp b/libs/kstd/kstd/test_support/os_panic.tests.cpp index c30411aa..c30411aa 100644 --- a/libs/kstd/kstd/test_support/os_panic.test.cpp +++ b/libs/kstd/kstd/test_support/os_panic.tests.cpp diff --git a/libs/kstd/kstd/unikstd.h b/libs/kstd/kstd/unikstd.h deleted file mode 100644 index aa60be63..00000000 --- a/libs/kstd/kstd/unikstd.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef KSTD_UNIKSTD_HPP -#define KSTD_UNIKSTD_HPP - -#include <cstddef> -#include <type_traits> - -namespace kstd -{ - using ssize_t = std::make_signed_t<std::size_t>; -} // namespace kstd - -#endif
\ No newline at end of file diff --git a/libs/kstd/kstd/units b/libs/kstd/kstd/units.hpp index df5eb374..df5eb374 100644 --- a/libs/kstd/kstd/units +++ b/libs/kstd/kstd/units.hpp diff --git a/libs/kstd/kstd/vector b/libs/kstd/kstd/vector.hpp index 736b854d..d6ad232a 100644 --- a/libs/kstd/kstd/vector +++ b/libs/kstd/kstd/vector.hpp @@ -1,10 +1,10 @@ #ifndef KSTD_VECTOR_HPP #define KSTD_VECTOR_HPP -#include <kstd/allocator> +#include <kstd/allocator.hpp> #include <kstd/bits/concepts.hpp> #include <kstd/os/error.hpp> -#include <kstd/ranges> +#include <kstd/ranges.hpp> #include <algorithm> #include <concepts> @@ -107,6 +107,7 @@ namespace kstd //! @tparam ForwardIterator An iterator type used to describe the source range. //! @param first The start of the source range. //! @param last The end of the source range. + //! @param allocator The allocator to use in the vector. template<std::forward_iterator ForwardIterator> constexpr vector(ForwardIterator first, ForwardIterator last, allocator_type const & allocator = @@ -127,6 +128,7 @@ namespace kstd //! @tparam InputIterator An iterator type used to describe the source range. //! @param first The start of the source range. //! @param last The end of the source range. + //! @param allocator The allocator to use in the vector. template<std::input_iterator InputIterator> constexpr vector(InputIterator first, InputIterator last, allocator_type const & allocator = @@ -228,6 +230,7 @@ namespace kstd //! Construct a new vector and initialize it's content by copying all elements in the given initializer list. //! //! @param list The initializer list containing the source objects. + //! @param allocator The allocator to use in the vector. vector(std::initializer_list<value_type> list, allocator_type const & allocator = allocator_type{}) : vector{std::ranges::begin(list), std::ranges::end(list), allocator} {} @@ -639,6 +642,7 @@ namespace kstd //! Insert the element of a given range into the vector at a given position. //! + //! @param position The position where to insert the elements. //! @param range The source range to insert elements from. //! @tparam SourceRange A container compatible range type. template<typename SourceRange> diff --git a/libs/kstd/kstd/vector.test.cpp b/libs/kstd/kstd/vector.tests.cpp index 8bf8f79d..72c1127a 100644 --- a/libs/kstd/kstd/vector.test.cpp +++ b/libs/kstd/kstd/vector.tests.cpp @@ -1,6 +1,6 @@ -#include <kstd/vector> +#include <kstd/vector.hpp> -#include <kstd/ranges> +#include <kstd/ranges.hpp> #include <kstd/test_support/os_panic.hpp> #include <kstd/test_support/test_types.hpp> |
