From 6e8f369a814061fab9d59611736cf0d7947a2ff6 Mon Sep 17 00:00:00 2001 From: dekrain Date: Sun, 6 Dec 2020 23:45:51 +0100 Subject: [PATCH 1/3] Added current implementation WiP --- Tests/Io/PrintfTest.cpp | 19 +++++++++ cpp/Printf.cpp | 49 ++++++++++++++++++++++ cpp/Printf.hpp | 12 ++++++ cpp/Tuparg.hpp | 93 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 Tests/Io/PrintfTest.cpp create mode 100644 cpp/Printf.cpp create mode 100644 cpp/Printf.hpp create mode 100644 cpp/Tuparg.hpp diff --git a/Tests/Io/PrintfTest.cpp b/Tests/Io/PrintfTest.cpp new file mode 100644 index 0000000..b7c0f47 --- /dev/null +++ b/Tests/Io/PrintfTest.cpp @@ -0,0 +1,19 @@ +#include "../../cpp/Printf.hpp" + +#include + +int main() { + std::random_device drng; + std::uniform_int_distribution dist(1, 999); + int num = dist(drng); + + static char const* const days[] = { + "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday", "Hiddenday", "Nullday" + }; + + int di = num % 9; + char const* day = days[di]; + + return xprintf("Hello, User%d!\nYour random day is %s\n", num, day); +} diff --git a/cpp/Printf.cpp b/cpp/Printf.cpp new file mode 100644 index 0000000..173c37a --- /dev/null +++ b/cpp/Printf.cpp @@ -0,0 +1,49 @@ +#include "Printf.hpp" + +#include +#include + +int xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend) { + while (*fmt) { + char ch = *fmt++; + if (ch != '%') + std::putchar(ch); + else { + char fch = *fmt++; + if (!fch) { + std::fputs("\nError: Invalid format string", stderr); + return 123; + } + if (tbegin == tend) { + std::fputs("\nError: Passed to few arguments", stderr); + return 1234; + } + switch (fch) { + case 'd': { + int value = tbegin.getnext(); + std::printf("%d", value); + break; + } + case 's': { + auto value = tbegin.getnext(); + std::fwrite(value, 1, std::strlen(value), stdout); + break; + } + case 'c': { + char value = tbegin.getnext(); + std::putchar(value); + break; + } + default: { + std::fputs("\nError: Invalid format specifier", stderr); + return 12345; + } + } + } + } + if (tbegin != tend) { + std::fputs("\nError: Not all arguments parsed", stderr); + return -666; + } + return 0; +} diff --git a/cpp/Printf.hpp b/cpp/Printf.hpp new file mode 100644 index 0000000..6c1c3ef --- /dev/null +++ b/cpp/Printf.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "Tuparg.hpp" + +int xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend); + +template +int xprintf(const char* fmt, Args&&... args) { + auto targs = make_xtuple(std::forward(args)...); + auto const& layout = xtuple_layout::get_layout(); + return xvprintf(fmt, layout.begin(targs), layout.end()); +} \ No newline at end of file diff --git a/cpp/Tuparg.hpp b/cpp/Tuparg.hpp new file mode 100644 index 0000000..5438a06 --- /dev/null +++ b/cpp/Tuparg.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include +#include +#include +#include + +struct xtuple_iterator { + size_t const* layout; + void* addr; + + template + X& getnext() { + assert(addr); + + X* p = reinterpret_cast(addr); + addr = reinterpret_cast( + reinterpret_cast(addr) + + *layout + ); + if (* ++layout == 0) + addr = nullptr; + return *p; + } + + bool operator==(const xtuple_iterator& o) const { + return addr == o.addr; + } + + bool operator!=(const xtuple_iterator& o) const { + return addr != o.addr; + } +}; + +template +struct xtuple { + Tfirst _first; + xtuple _rest; + + xtuple(Tfirst f, Trest... r) + : _first(std::move(f)), _rest(std::move(r)...) + {} + + consteval static size_t get_offset() { + return offsetof(xtuple, _rest); + } +}; + +template +struct xtuple { + Tfirst _first; + + xtuple(Tfirst f) : _first(std::move(f)) {} + + consteval static size_t get_offset() { + return sizeof(xtuple); + } +}; + +template +struct xtuple_layout; + +template +struct xtuple_layout> { + using tuple_type = xtuple; + constexpr static size_t count = 1 + sizeof...(Trest); + + size_t data[count + 1]; + + consteval xtuple_layout() { + assign_layout(data, 0); + data[count] = 0; + } + + consteval static void assign_layout(size_t* p, size_t idx) { + p[idx] = tuple_type::get_offset(); + if constexpr (sizeof...(Trest)) + xtuple_layout>::assign_layout(p, idx+1); + } + + static inline xtuple_layout const& get_layout() { + static constinit const xtuple_layout _layout; + return _layout; + } + + auto begin(tuple_type& tup) const { return xtuple_iterator{data, &tup._first}; } + auto end() const { return xtuple_iterator{data + count, nullptr}; } +}; + +template +auto make_xtuple(Args&&... args) { + return xtuple...>(std::forward(args)...); +} From f9eaa310df3895017b0811e26126ad284a3aa41f Mon Sep 17 00:00:00 2001 From: dekrain Date: Wed, 6 Jan 2021 00:09:47 +0100 Subject: [PATCH 2/3] Symbiotize tuparg with hsd --- Tests/Io/PrintfTest.cpp | 8 +- cpp/Printf.cpp | 19 ++--- cpp/Printf.hpp | 17 ++-- cpp/Result.hpp | 6 +- cpp/Tuparg.hpp | 175 ++++++++++++++++++++-------------------- cpp/Types.hpp | 7 +- 6 files changed, 121 insertions(+), 111 deletions(-) diff --git a/Tests/Io/PrintfTest.cpp b/Tests/Io/PrintfTest.cpp index b7c0f47..b7b160d 100644 --- a/Tests/Io/PrintfTest.cpp +++ b/Tests/Io/PrintfTest.cpp @@ -1,4 +1,4 @@ -#include "../../cpp/Printf.hpp" +#include #include @@ -7,13 +7,13 @@ int main() { std::uniform_int_distribution dist(1, 999); int num = dist(drng); - static char const* const days[] = { + static const char* const days[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Hiddenday", "Nullday" }; int di = num % 9; - char const* day = days[di]; + const char* day = days[di]; - return xprintf("Hello, User%d!\nYour random day is %s\n", num, day); + hsd::xprintf("Hello, User%d!\nYour random day is %s\n", num, day).unwrap(); } diff --git a/cpp/Printf.cpp b/cpp/Printf.cpp index 173c37a..8aa8ffa 100644 --- a/cpp/Printf.cpp +++ b/cpp/Printf.cpp @@ -3,7 +3,8 @@ #include #include -int xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend) { +using namespace hsd; +Result hsd::xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend) noexcept { while (*fmt) { char ch = *fmt++; if (ch != '%') @@ -11,12 +12,10 @@ int xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend) { else { char fch = *fmt++; if (!fch) { - std::fputs("\nError: Invalid format string", stderr); - return 123; + return runtime_error("\nError: Invalid format string"); } if (tbegin == tend) { - std::fputs("\nError: Passed to few arguments", stderr); - return 1234; + return runtime_error("\nError: Passed to few arguments"); } switch (fch) { case 'd': { @@ -25,7 +24,7 @@ int xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend) { break; } case 's': { - auto value = tbegin.getnext(); + auto value = tbegin.getnext(); std::fwrite(value, 1, std::strlen(value), stdout); break; } @@ -35,15 +34,13 @@ int xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend) { break; } default: { - std::fputs("\nError: Invalid format specifier", stderr); - return 12345; + return runtime_error("\nError: Invalid format specifier"); } } } } if (tbegin != tend) { - std::fputs("\nError: Not all arguments parsed", stderr); - return -666; + return runtime_error("\nError: Not all arguments parsed"); } - return 0; + return {}; } diff --git a/cpp/Printf.hpp b/cpp/Printf.hpp index 6c1c3ef..78ec161 100644 --- a/cpp/Printf.hpp +++ b/cpp/Printf.hpp @@ -1,12 +1,15 @@ #pragma once #include "Tuparg.hpp" +#include "Result.hpp" -int xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend); +namespace hsd { + Result xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend) noexcept; -template -int xprintf(const char* fmt, Args&&... args) { - auto targs = make_xtuple(std::forward(args)...); - auto const& layout = xtuple_layout::get_layout(); - return xvprintf(fmt, layout.begin(targs), layout.end()); -} \ No newline at end of file + template + Result xprintf(const char* fmt, Args&&... args) noexcept { + auto targs = make_xtuple(forward(args)...); + const auto& layout = xtuple_layout::get_layout(); + return xvprintf(fmt, layout.begin(targs), layout.end()); + } +} diff --git a/cpp/Result.hpp b/cpp/Result.hpp index 12387b7..2746739 100644 --- a/cpp/Result.hpp +++ b/cpp/Result.hpp @@ -69,9 +69,13 @@ namespace hsd const char* _err = nullptr; public: - runtime_error(const char* error) + constexpr runtime_error(const char* error) : _err{error} {} + + constexpr const char* operator()() const { + return _err; + } }; template < typename Ok, typename Err > diff --git a/cpp/Tuparg.hpp b/cpp/Tuparg.hpp index 5438a06..6842069 100644 --- a/cpp/Tuparg.hpp +++ b/cpp/Tuparg.hpp @@ -1,93 +1,94 @@ #pragma once -#include -#include -#include +#include "Types.hpp" +#include "Utility.hpp" #include -struct xtuple_iterator { - size_t const* layout; - void* addr; - - template - X& getnext() { - assert(addr); - - X* p = reinterpret_cast(addr); - addr = reinterpret_cast( - reinterpret_cast(addr) - + *layout - ); - if (* ++layout == 0) - addr = nullptr; - return *p; +namespace hsd { + struct xtuple_iterator { + const usize* layout; + void* addr; + + template + X& getnext() { + assert(addr); + + X* p = reinterpret_cast(addr); + addr = reinterpret_cast( + reinterpret_cast(addr) + + *layout + ); + if (* ++layout == 0) + addr = nullptr; + return *p; + } + + bool operator==(const xtuple_iterator& o) const { + return addr == o.addr; + } + + bool operator!=(const xtuple_iterator& o) const { + return addr != o.addr; + } + }; + + template + struct xtuple { + Tfirst _first; + xtuple _rest; + + xtuple(Tfirst f, Trest... r) + : _first(move(f)), _rest(move(r)...) + {} + + consteval static usize get_offset() { + return offsetof(xtuple, _rest); + } + }; + + template + struct xtuple { + Tfirst _first; + + xtuple(Tfirst f) : _first(move(f)) {} + + consteval static usize get_offset() { + return sizeof(xtuple); + } + }; + + template + struct xtuple_layout; + + template + struct xtuple_layout> { + using tuple_type = xtuple; + constexpr static usize count = 1 + sizeof...(Trest); + + usize data[count + 1]; + + consteval xtuple_layout() { + assign_layout(data, 0); + data[count] = 0; + } + + consteval static void assign_layout(usize* p, usize idx) { + p[idx] = tuple_type::get_offset(); + if constexpr (sizeof...(Trest)) + xtuple_layout>::assign_layout(p, idx+1); + } + + static inline xtuple_layout const& get_layout() { + static constinit const xtuple_layout _layout; + return _layout; + } + + auto begin(tuple_type& tup) const { return xtuple_iterator{data, &tup._first}; } + auto end() const { return xtuple_iterator{data + count, nullptr}; } + }; + + template + auto make_xtuple(Args&&... args) { + return xtuple...>(forward(args)...); } - - bool operator==(const xtuple_iterator& o) const { - return addr == o.addr; - } - - bool operator!=(const xtuple_iterator& o) const { - return addr != o.addr; - } -}; - -template -struct xtuple { - Tfirst _first; - xtuple _rest; - - xtuple(Tfirst f, Trest... r) - : _first(std::move(f)), _rest(std::move(r)...) - {} - - consteval static size_t get_offset() { - return offsetof(xtuple, _rest); - } -}; - -template -struct xtuple { - Tfirst _first; - - xtuple(Tfirst f) : _first(std::move(f)) {} - - consteval static size_t get_offset() { - return sizeof(xtuple); - } -}; - -template -struct xtuple_layout; - -template -struct xtuple_layout> { - using tuple_type = xtuple; - constexpr static size_t count = 1 + sizeof...(Trest); - - size_t data[count + 1]; - - consteval xtuple_layout() { - assign_layout(data, 0); - data[count] = 0; - } - - consteval static void assign_layout(size_t* p, size_t idx) { - p[idx] = tuple_type::get_offset(); - if constexpr (sizeof...(Trest)) - xtuple_layout>::assign_layout(p, idx+1); - } - - static inline xtuple_layout const& get_layout() { - static constinit const xtuple_layout _layout; - return _layout; - } - - auto begin(tuple_type& tup) const { return xtuple_iterator{data, &tup._first}; } - auto end() const { return xtuple_iterator{data + count, nullptr}; } -}; - -template -auto make_xtuple(Args&&... args) { - return xtuple...>(std::forward(args)...); } diff --git a/cpp/Types.hpp b/cpp/Types.hpp index 7ef9e91..1fb4886 100644 --- a/cpp/Types.hpp +++ b/cpp/Types.hpp @@ -12,7 +12,7 @@ namespace hsd template <> struct remove_unsigned { - using type = char; + using type = signed char; }; template <> @@ -43,6 +43,10 @@ namespace hsd using usize = decltype(sizeof(int)); using isize = detail::remove_unsigned::type; + using uptr = usize; + using iptr = isize; + using ptrdiff = isize; + #ifdef HSD_COMPILER_GCC using u128 = __uint128_t; using i128 = __int128_t; @@ -54,6 +58,7 @@ namespace hsd using u16 = unsigned short; using u8 = unsigned char; + using ilong = long; using i64 = long long; using i32 = int; using i16 = short; From 7def831ddff72df672f7c5de14e081cda1d2f7e8 Mon Sep 17 00:00:00 2001 From: dekrain Date: Wed, 6 Jan 2021 01:52:55 +0100 Subject: [PATCH 3/3] Update to work with Result --- cpp/Printf.cpp | 15 +++++++++------ cpp/Result.hpp | 14 +++++++++----- cpp/Tuparg.hpp | 11 +++++++++-- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/cpp/Printf.cpp b/cpp/Printf.cpp index 8aa8ffa..7e07421 100644 --- a/cpp/Printf.cpp +++ b/cpp/Printf.cpp @@ -1,7 +1,9 @@ #include "Printf.hpp" #include -#include + +#include "String.hpp" +#include "Io.hpp" using namespace hsd; Result hsd::xvprintf(const char* fmt, xtuple_iterator tbegin, xtuple_iterator tend) noexcept { @@ -19,17 +21,18 @@ Result hsd::xvprintf(const char* fmt, xtuple_iterator tbegi } switch (fch) { case 'd': { - int value = tbegin.getnext(); - std::printf("%d", value); + int value = tbegin.getnext().unwrap(); + auto s = string::to_string(value); + std::fwrite(s.data(), 1, s.size(), stdout); break; } case 's': { - auto value = tbegin.getnext(); - std::fwrite(value, 1, std::strlen(value), stdout); + auto value = tbegin.getnext().unwrap(); + std::fwrite(value, 1, cstring::length(value), stdout); break; } case 'c': { - char value = tbegin.getnext(); + char value = tbegin.getnext().unwrap(); std::putchar(value); break; } diff --git a/cpp/Result.hpp b/cpp/Result.hpp index 2746739..8352d6e 100644 --- a/cpp/Result.hpp +++ b/cpp/Result.hpp @@ -78,6 +78,10 @@ namespace hsd } }; + // Tags for result construction + struct ok_tag_t {}; + struct err_tag_t {}; + template < typename Ok, typename Err > class Result { @@ -94,17 +98,17 @@ namespace hsd HSD_CONSTEXPR Result& operator=(const Result&) = delete; HSD_CONSTEXPR Result& operator=(Result&&) = delete; - HSD_CONSTEXPR Result(const Ok& value) + HSD_CONSTEXPR Result(const Ok& value, ok_tag_t = {}) : _ok_data{value}, _initialized{true} {} - HSD_CONSTEXPR Result(Ok&& value) + HSD_CONSTEXPR Result(Ok&& value, ok_tag_t = {}) : _ok_data{move(value)}, _initialized{true} {} template requires (std::is_convertible_v) - HSD_CONSTEXPR Result(T&& value) + HSD_CONSTEXPR Result(T&& value, err_tag_t = {}) : _err_data{forward(value)}, _initialized{false} {} @@ -395,13 +399,13 @@ namespace hsd constexpr void unwrap_or_default() = delete; constexpr void unwrap_or() = delete; - HSD_CONSTEXPR Result() + HSD_CONSTEXPR Result(ok_tag_t = {}) : _initialized{true} {} template requires (std::is_convertible_v) - HSD_CONSTEXPR Result(T&& value) + HSD_CONSTEXPR Result(T&& value, err_tag_t = {}) : _err_data{forward(value)}, _initialized{false} {} diff --git a/cpp/Tuparg.hpp b/cpp/Tuparg.hpp index 6842069..be52167 100644 --- a/cpp/Tuparg.hpp +++ b/cpp/Tuparg.hpp @@ -1,7 +1,7 @@ #pragma once #include "Types.hpp" -#include "Utility.hpp" +#include "Result.hpp" #include namespace hsd { @@ -10,7 +10,7 @@ namespace hsd { void* addr; template - X& getnext() { + X& getnext_unsafe() { assert(addr); X* p = reinterpret_cast(addr); @@ -23,6 +23,13 @@ namespace hsd { return *p; } + template + Result, runtime_error> getnext() { + if (!addr) + return runtime_error("Extracting value past end of the container"); + return Result, runtime_error>(getnext_unsafe(), ok_tag_t{}); + } + bool operator==(const xtuple_iterator& o) const { return addr == o.addr; }