diff --git a/.clang-format b/.clang-format index ecd945af7..f6b8d98ec 100644 --- a/.clang-format +++ b/.clang-format @@ -84,7 +84,7 @@ KeepEmptyLines: AtEndOfFile: false AtStartOfBlock: false AtStartOfFile: false -LineEnding: LF +LineEnding: CRLF MacroBlockBegin: "" MacroBlockEnd: "" MaxEmptyLinesToKeep: 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 35ceffabc..e6d3df310 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,7 +160,7 @@ else() -Wno-nullability-extension) else() if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - add_compile_options(/W3 /Zc:preprocessor) + add_compile_options(/W3 /Zc:preprocessor /permissive) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif() endif() diff --git a/ashura/editor/editor.cc b/ashura/editor/editor.cc index 422b19480..39bf5317c 100644 --- a/ashura/editor/editor.cc +++ b/ashura/editor/editor.cc @@ -29,7 +29,7 @@ int main() sw[0].on(); -scalar.frame(250, 100); + scalar.frame(250, 100); slider.range(0, 100).interp(0).axis(Axis::Y); @@ -76,7 +76,7 @@ scalar.frame(250, 100); .axis(Axis::X) .cross_align(0) .main_align(MainAlign::SpaceBetween) - .frame(1920, 1080); + .frame(1'920, 1'080); engine->run(flex); -} \ No newline at end of file +} diff --git a/ashura/engine/canvas.cc b/ashura/engine/canvas.cc index 6855072d2..9905aa49e 100644 --- a/ashura/engine/canvas.cc +++ b/ashura/engine/canvas.cc @@ -430,7 +430,7 @@ static inline void flush_batch(Canvas & c) .params_ssbo = ctx.ngons.descriptor, .textures = ctx.gpu.texture_views, .index_counts = - ctx.canvas.ngon_index_counts.span().slice(batch.objects)}; + ctx.canvas.ngon_index_counts.view().slice(batch.objects)}; ctx.passes.ngon->encode(ctx.gpu, ctx.enc, params); }); return; @@ -638,12 +638,12 @@ Canvas & Canvas::text(ShapeInfo const & info, TextBlock const & block, f32 const block_width = max(layout.extent.x, style.align_width); Vec2 const block_extent{block_width, layout.extent.y}; - constexpr u8 PASS_BACKGROUND = 0; - constexpr u8 PASS_GLYPH_SHADOWS = 1; - constexpr u8 PASS_GLYPHS = 2; - constexpr u8 PASS_UNDERLINE = 3; - constexpr u8 PASS_STRIKETHROUGH = 4; - constexpr u8 NUM_PASSES = 5; + static constexpr u8 PASS_BACKGROUND = 0; + static constexpr u8 PASS_GLYPH_SHADOWS = 1; + static constexpr u8 PASS_GLYPHS = 2; + static constexpr u8 PASS_UNDERLINE = 3; + static constexpr u8 PASS_STRIKETHROUGH = 4; + static constexpr u8 NUM_PASSES = 5; for (u8 pass = 0; pass < NUM_PASSES; pass++) { @@ -667,7 +667,7 @@ Canvas & Canvas::text(ShapeInfo const & info, TextBlock const & block, f32 cursor = space_align(block_width, ln.metrics.width, alignment) - ln.metrics.width * 0.5F; for (TextRun const & run : - layout.runs.span().slice(ln.first_run, ln.num_runs)) + layout.runs.view().slice(ln.first_run, ln.num_runs)) { FontStyle const & font_style = block.fonts[run.style]; TextStyle const & run_style = style.runs[run.style]; @@ -823,7 +823,7 @@ Canvas & Canvas::triangles(ShapeInfo const & info, Span points, ngon_vertices.extend(points).unwrap(); ngon_indices.extend(idx).unwrap(); - for (u32 & v : ngon_indices.span().slice(first_index)) + for (u32 & v : ngon_indices.view().slice(first_index)) { v += first_vertex; } diff --git a/ashura/engine/color.h b/ashura/engine/color.h index c026ff591..71392a937 100644 --- a/ashura/engine/color.h +++ b/ashura/engine/color.h @@ -8,97 +8,97 @@ namespace ash namespace colors { -constexpr Vec4U8 WHITE = Vec4U8{0xFF, 0xFF, 0xFF, 0xFF}; -constexpr Vec4U8 BLACK = Vec4U8{0x00, 0x00, 0x00, 0xFF}; -constexpr Vec4U8 RED = Vec4U8{0xFF, 0x00, 0x00, 0xFF}; -constexpr Vec4U8 BLUE = Vec4U8{0x00, 0x00, 0xFF, 0xFF}; -constexpr Vec4U8 GREEN = Vec4U8{0x00, 0xFF, 0x00, 0xFF}; -constexpr Vec4U8 CYAN = Vec4U8{0x00, 0xFF, 0xFF, 0xFF}; -constexpr Vec4U8 MAGENTA = Vec4U8{0xFF, 0x00, 0xFF, 0xFF}; -constexpr Vec4U8 YELLOW = Vec4U8{0xFF, 0xFF, 0x00, 0xFF}; +inline constexpr Vec4U8 WHITE = Vec4U8{0xFF, 0xFF, 0xFF, 0xFF}; +inline constexpr Vec4U8 BLACK = Vec4U8{0x00, 0x00, 0x00, 0xFF}; +inline constexpr Vec4U8 RED = Vec4U8{0xFF, 0x00, 0x00, 0xFF}; +inline constexpr Vec4U8 BLUE = Vec4U8{0x00, 0x00, 0xFF, 0xFF}; +inline constexpr Vec4U8 GREEN = Vec4U8{0x00, 0xFF, 0x00, 0xFF}; +inline constexpr Vec4U8 CYAN = Vec4U8{0x00, 0xFF, 0xFF, 0xFF}; +inline constexpr Vec4U8 MAGENTA = Vec4U8{0xFF, 0x00, 0xFF, 0xFF}; +inline constexpr Vec4U8 YELLOW = Vec4U8{0xFF, 0xFF, 0x00, 0xFF}; } // namespace colors // ios default system colors namespace ios { -constexpr Vec4U8 LIGHT_BLUE = Vec4U8{0, 122, 0xFF, 0xFF}; -constexpr Vec4U8 DARK_BLUE = Vec4U8{10, 132, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_BROWN = Vec4U8{162, 132, 94, 0xFF}; -constexpr Vec4U8 DARK_BROWN = Vec4U8{172, 142, 104, 0xFF}; -constexpr Vec4U8 LIGHT_CYAN = Vec4U8{50, 173, 230, 0xFF}; -constexpr Vec4U8 DARK_CYAN = Vec4U8{100, 210, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN = Vec4U8{52, 199, 89, 0xFF}; -constexpr Vec4U8 DARK_GREEN = Vec4U8{48, 209, 88, 0xFF}; -constexpr Vec4U8 LIGHT_INDIGO = Vec4U8{88, 86, 214, 0xFF}; -constexpr Vec4U8 DARK_INDIGO = Vec4U8{94, 92, 230, 0xFF}; -constexpr Vec4U8 LIGHT_MINT = Vec4U8{0, 199, 190, 0xFF}; -constexpr Vec4U8 DARK_MINT = Vec4U8{102, 212, 207, 0xFF}; -constexpr Vec4U8 LIGHT_ORANGE = Vec4U8{255, 149, 0, 0xFF}; -constexpr Vec4U8 DARK_ORANGE = Vec4U8{255, 159, 10, 0xFF}; -constexpr Vec4U8 LIGHT_PINK = Vec4U8{255, 45, 85, 0xFF}; -constexpr Vec4U8 DARK_PINK = Vec4U8{255, 55, 95, 0xFF}; -constexpr Vec4U8 LIGHT_PURPLE = Vec4U8{175, 82, 222, 0xFF}; -constexpr Vec4U8 DARK_PURPLE = Vec4U8{191, 90, 242, 0xFF}; -constexpr Vec4U8 LIGHT_RED = Vec4U8{255, 59, 48, 0xFF}; -constexpr Vec4U8 DARK_RED = Vec4U8{255, 69, 58, 0xFF}; -constexpr Vec4U8 LIGHT_TEAL = Vec4U8{48, 176, 199, 0xFF}; -constexpr Vec4U8 DARK_TEAL = Vec4U8{64, 200, 224, 0xFF}; -constexpr Vec4U8 LIGHT_YELLOW = Vec4U8{255, 204, 0, 0xFF}; -constexpr Vec4U8 DARK_YELLOW = Vec4U8{255, 214, 10, 0xFF}; - -constexpr Vec4U8 LIGHT_GRAY = Vec4U8{142, 142, 147, 0xFF}; -constexpr Vec4U8 DARK_GRAY = Vec4U8{142, 142, 147, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_2 = Vec4U8{174, 174, 178, 0xFF}; -constexpr Vec4U8 DARK_GRAY_2 = Vec4U8{99, 99, 102, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_3 = Vec4U8{199, 199, 204, 0xFF}; -constexpr Vec4U8 DARK_GRAY_3 = Vec4U8{72, 72, 74, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_4 = Vec4U8{209, 209, 214, 0xFF}; -constexpr Vec4U8 DARK_GRAY_4 = Vec4U8{58, 58, 60, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_5 = Vec4U8{229, 229, 234, 0xFF}; -constexpr Vec4U8 DARK_GRAY_5 = Vec4U8{44, 44, 46, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_6 = Vec4U8{242, 242, 247, 0xFF}; -constexpr Vec4U8 DARK_GRAY_6 = Vec4U8{28, 28, 30, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE = Vec4U8{0, 122, 0xFF, 0xFF}; +inline constexpr Vec4U8 DARK_BLUE = Vec4U8{10, 132, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_BROWN = Vec4U8{162, 132, 94, 0xFF}; +inline constexpr Vec4U8 DARK_BROWN = Vec4U8{172, 142, 104, 0xFF}; +inline constexpr Vec4U8 LIGHT_CYAN = Vec4U8{50, 173, 230, 0xFF}; +inline constexpr Vec4U8 DARK_CYAN = Vec4U8{100, 210, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN = Vec4U8{52, 199, 89, 0xFF}; +inline constexpr Vec4U8 DARK_GREEN = Vec4U8{48, 209, 88, 0xFF}; +inline constexpr Vec4U8 LIGHT_INDIGO = Vec4U8{88, 86, 214, 0xFF}; +inline constexpr Vec4U8 DARK_INDIGO = Vec4U8{94, 92, 230, 0xFF}; +inline constexpr Vec4U8 LIGHT_MINT = Vec4U8{0, 199, 190, 0xFF}; +inline constexpr Vec4U8 DARK_MINT = Vec4U8{102, 212, 207, 0xFF}; +inline constexpr Vec4U8 LIGHT_ORANGE = Vec4U8{255, 149, 0, 0xFF}; +inline constexpr Vec4U8 DARK_ORANGE = Vec4U8{255, 159, 10, 0xFF}; +inline constexpr Vec4U8 LIGHT_PINK = Vec4U8{255, 45, 85, 0xFF}; +inline constexpr Vec4U8 DARK_PINK = Vec4U8{255, 55, 95, 0xFF}; +inline constexpr Vec4U8 LIGHT_PURPLE = Vec4U8{175, 82, 222, 0xFF}; +inline constexpr Vec4U8 DARK_PURPLE = Vec4U8{191, 90, 242, 0xFF}; +inline constexpr Vec4U8 LIGHT_RED = Vec4U8{255, 59, 48, 0xFF}; +inline constexpr Vec4U8 DARK_RED = Vec4U8{255, 69, 58, 0xFF}; +inline constexpr Vec4U8 LIGHT_TEAL = Vec4U8{48, 176, 199, 0xFF}; +inline constexpr Vec4U8 DARK_TEAL = Vec4U8{64, 200, 224, 0xFF}; +inline constexpr Vec4U8 LIGHT_YELLOW = Vec4U8{255, 204, 0, 0xFF}; +inline constexpr Vec4U8 DARK_YELLOW = Vec4U8{255, 214, 10, 0xFF}; + +inline constexpr Vec4U8 LIGHT_GRAY = Vec4U8{142, 142, 147, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY = Vec4U8{142, 142, 147, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_2 = Vec4U8{174, 174, 178, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_2 = Vec4U8{99, 99, 102, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_3 = Vec4U8{199, 199, 204, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_3 = Vec4U8{72, 72, 74, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_4 = Vec4U8{209, 209, 214, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_4 = Vec4U8{58, 58, 60, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_5 = Vec4U8{229, 229, 234, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_5 = Vec4U8{44, 44, 46, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_6 = Vec4U8{242, 242, 247, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_6 = Vec4U8{28, 28, 30, 0xFF}; // ios accessible colors namespace accessible { -constexpr Vec4U8 LIGHT_BLUE = Vec4U8{0, 64, 221, 0xFF}; -constexpr Vec4U8 DARK_BLUE = Vec4U8{64, 156, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_BROWN = Vec4U8{127, 101, 69, 0xFF}; -constexpr Vec4U8 DARK_BROWN = Vec4U8{181, 148, 105, 0xFF}; -constexpr Vec4U8 LIGHT_CYAN = Vec4U8{0, 113, 164, 0xFF}; -constexpr Vec4U8 DARK_CYAN = Vec4U8{112, 215, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN = Vec4U8{36, 138, 61, 0xFF}; -constexpr Vec4U8 DARK_GREEN = Vec4U8{48, 219, 91, 0xFF}; -constexpr Vec4U8 LIGHT_INDIGO = Vec4U8{54, 52, 163, 0xFF}; -constexpr Vec4U8 DARK_INDIGO = Vec4U8{125, 122, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_MINT = Vec4U8{12, 129, 123, 0xFF}; -constexpr Vec4U8 DARK_MINT = Vec4U8{102, 212, 207, 0xFF}; -constexpr Vec4U8 LIGHT_ORANGE = Vec4U8{201, 52, 0, 0xFF}; -constexpr Vec4U8 DARK_ORANGE = Vec4U8{255, 179, 64, 0xFF}; -constexpr Vec4U8 LIGHT_PINK = Vec4U8{211, 15, 69, 0xFF}; -constexpr Vec4U8 DARK_PINK = Vec4U8{255, 100, 130, 0xFF}; -constexpr Vec4U8 LIGHT_PURPLE = Vec4U8{137, 68, 171, 0xFF}; -constexpr Vec4U8 DARK_PURPLE = Vec4U8{218, 143, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_RED = Vec4U8{215, 0, 21, 0xFF}; -constexpr Vec4U8 DARK_RED = Vec4U8{255, 105, 97, 0xFF}; -constexpr Vec4U8 LIGHT_TEAL = Vec4U8{0, 130, 153, 0xFF}; -constexpr Vec4U8 DARK_TEAL = Vec4U8{93, 230, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_YELLOW = Vec4U8{178, 80, 0, 0xFF}; -constexpr Vec4U8 DARK_YELLOW = Vec4U8{255, 212, 38, 0xFF}; - -constexpr Vec4U8 LIGHT_GRAY = Vec4U8{108, 108, 112, 0xFF}; -constexpr Vec4U8 DARK_GRAY = Vec4U8{174, 174, 178, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_2 = Vec4U8{142, 142, 147, 0xFF}; -constexpr Vec4U8 DARK_GRAY_2 = Vec4U8{124, 124, 128, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_3 = Vec4U8{174, 174, 178, 0xFF}; -constexpr Vec4U8 DARK_GRAY_3 = Vec4U8{84, 84, 86, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_4 = Vec4U8{188, 188, 192, 0xFF}; -constexpr Vec4U8 DARK_GRAY_4 = Vec4U8{68, 68, 70, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_5 = Vec4U8{216, 216, 220, 0xFF}; -constexpr Vec4U8 DARK_GRAY_5 = Vec4U8{54, 54, 56, 0xFF}; -constexpr Vec4U8 LIGHT_GRAY_6 = Vec4U8{235, 235, 240, 0xFF}; -constexpr Vec4U8 DARK_GRAY_6 = Vec4U8{36, 36, 36, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE = Vec4U8{0, 64, 221, 0xFF}; +inline constexpr Vec4U8 DARK_BLUE = Vec4U8{64, 156, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_BROWN = Vec4U8{127, 101, 69, 0xFF}; +inline constexpr Vec4U8 DARK_BROWN = Vec4U8{181, 148, 105, 0xFF}; +inline constexpr Vec4U8 LIGHT_CYAN = Vec4U8{0, 113, 164, 0xFF}; +inline constexpr Vec4U8 DARK_CYAN = Vec4U8{112, 215, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN = Vec4U8{36, 138, 61, 0xFF}; +inline constexpr Vec4U8 DARK_GREEN = Vec4U8{48, 219, 91, 0xFF}; +inline constexpr Vec4U8 LIGHT_INDIGO = Vec4U8{54, 52, 163, 0xFF}; +inline constexpr Vec4U8 DARK_INDIGO = Vec4U8{125, 122, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_MINT = Vec4U8{12, 129, 123, 0xFF}; +inline constexpr Vec4U8 DARK_MINT = Vec4U8{102, 212, 207, 0xFF}; +inline constexpr Vec4U8 LIGHT_ORANGE = Vec4U8{201, 52, 0, 0xFF}; +inline constexpr Vec4U8 DARK_ORANGE = Vec4U8{255, 179, 64, 0xFF}; +inline constexpr Vec4U8 LIGHT_PINK = Vec4U8{211, 15, 69, 0xFF}; +inline constexpr Vec4U8 DARK_PINK = Vec4U8{255, 100, 130, 0xFF}; +inline constexpr Vec4U8 LIGHT_PURPLE = Vec4U8{137, 68, 171, 0xFF}; +inline constexpr Vec4U8 DARK_PURPLE = Vec4U8{218, 143, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_RED = Vec4U8{215, 0, 21, 0xFF}; +inline constexpr Vec4U8 DARK_RED = Vec4U8{255, 105, 97, 0xFF}; +inline constexpr Vec4U8 LIGHT_TEAL = Vec4U8{0, 130, 153, 0xFF}; +inline constexpr Vec4U8 DARK_TEAL = Vec4U8{93, 230, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_YELLOW = Vec4U8{178, 80, 0, 0xFF}; +inline constexpr Vec4U8 DARK_YELLOW = Vec4U8{255, 212, 38, 0xFF}; + +inline constexpr Vec4U8 LIGHT_GRAY = Vec4U8{108, 108, 112, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY = Vec4U8{174, 174, 178, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_2 = Vec4U8{142, 142, 147, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_2 = Vec4U8{124, 124, 128, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_3 = Vec4U8{174, 174, 178, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_3 = Vec4U8{84, 84, 86, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_4 = Vec4U8{188, 188, 192, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_4 = Vec4U8{68, 68, 70, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_5 = Vec4U8{216, 216, 220, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_5 = Vec4U8{54, 54, 56, 0xFF}; +inline constexpr Vec4U8 LIGHT_GRAY_6 = Vec4U8{235, 235, 240, 0xFF}; +inline constexpr Vec4U8 DARK_GRAY_6 = Vec4U8{36, 36, 36, 0xFF}; } // namespace accessible } // namespace ios @@ -106,281 +106,281 @@ constexpr Vec4U8 DARK_GRAY_6 = Vec4U8{36, 36, 36, 0xFF}; /// @brief Material Design Colors namespace mdc { -constexpr Vec4U8 RED_50 = Vec4U8{0xFF, 0xEB, 0xEE, 0xFF}; -constexpr Vec4U8 RED_100 = Vec4U8{0xFF, 0xCD, 0xD2, 0xFF}; -constexpr Vec4U8 RED_200 = Vec4U8{0xEF, 0x9A, 0x9A, 0xFF}; -constexpr Vec4U8 RED_300 = Vec4U8{0xE5, 0x73, 0x73, 0xFF}; -constexpr Vec4U8 RED_400 = Vec4U8{0xEF, 0x53, 0x50, 0xFF}; -constexpr Vec4U8 RED_500 = Vec4U8{0xF4, 0x43, 0x36, 0xFF}; -constexpr Vec4U8 RED_600 = Vec4U8{0xE5, 0x39, 0x35, 0xFF}; -constexpr Vec4U8 RED_700 = Vec4U8{0xD3, 0x2F, 0x2F, 0xFF}; -constexpr Vec4U8 RED_800 = Vec4U8{0xC6, 0x28, 0x28, 0xFF}; -constexpr Vec4U8 RED_900 = Vec4U8{0xB7, 0x1C, 0x1C, 0xFF}; -constexpr Vec4U8 RED_A100 = Vec4U8{0xFF, 0x8A, 0x80, 0xFF}; -constexpr Vec4U8 RED_A200 = Vec4U8{0xFF, 0x52, 0x52, 0xFF}; -constexpr Vec4U8 RED_A400 = Vec4U8{0xFF, 0x17, 0x44, 0xFF}; -constexpr Vec4U8 RED_A700 = Vec4U8{0xD5, 0x00, 0x00, 0xFF}; - -constexpr Vec4U8 PINK_50 = Vec4U8{0xFC, 0xE4, 0xEC, 0xFF}; -constexpr Vec4U8 PINK_100 = Vec4U8{0xF8, 0xBB, 0xD0, 0xFF}; -constexpr Vec4U8 PINK_200 = Vec4U8{0xF4, 0x8F, 0xB1, 0xFF}; -constexpr Vec4U8 PINK_300 = Vec4U8{0xF0, 0x62, 0x92, 0xFF}; -constexpr Vec4U8 PINK_400 = Vec4U8{0xEC, 0x40, 0x7A, 0xFF}; -constexpr Vec4U8 PINK_500 = Vec4U8{0xE9, 0x1E, 0x63, 0xFF}; -constexpr Vec4U8 PINK_600 = Vec4U8{0xD8, 0x1B, 0x60, 0xFF}; -constexpr Vec4U8 PINK_700 = Vec4U8{0xC2, 0x18, 0x5B, 0xFF}; -constexpr Vec4U8 PINK_800 = Vec4U8{0xAD, 0x14, 0x57, 0xFF}; -constexpr Vec4U8 PINK_900 = Vec4U8{0x88, 0x0E, 0x4F, 0xFF}; -constexpr Vec4U8 PINK_A100 = Vec4U8{0xFF, 0x80, 0xAB, 0xFF}; -constexpr Vec4U8 PINK_A200 = Vec4U8{0xFF, 0x40, 0x81, 0xFF}; -constexpr Vec4U8 PINK_A400 = Vec4U8{0xF5, 0x00, 0x57, 0xFF}; -constexpr Vec4U8 PINK_A700 = Vec4U8{0xC5, 0x11, 0x62, 0xFF}; - -constexpr Vec4U8 PURPLE_50 = Vec4U8{0xF3, 0xE5, 0xF5, 0xFF}; -constexpr Vec4U8 PURPLE_100 = Vec4U8{0xE1, 0xBE, 0xE7, 0xFF}; -constexpr Vec4U8 PURPLE_200 = Vec4U8{0xCE, 0x93, 0xD8, 0xFF}; -constexpr Vec4U8 PURPLE_300 = Vec4U8{0xBA, 0x68, 0xC8, 0xFF}; -constexpr Vec4U8 PURPLE_400 = Vec4U8{0xAB, 0x47, 0xBC, 0xFF}; -constexpr Vec4U8 PURPLE_500 = Vec4U8{0x9C, 0x27, 0xB0, 0xFF}; -constexpr Vec4U8 PURPLE_600 = Vec4U8{0x8E, 0x24, 0xAA, 0xFF}; -constexpr Vec4U8 PURPLE_700 = Vec4U8{0x7B, 0x1F, 0xA2, 0xFF}; -constexpr Vec4U8 PURPLE_800 = Vec4U8{0x6A, 0x1B, 0x9A, 0xFF}; -constexpr Vec4U8 PURPLE_900 = Vec4U8{0x4A, 0x14, 0x8C, 0xFF}; -constexpr Vec4U8 PURPLE_A100 = Vec4U8{0xEA, 0x80, 0xFC, 0xFF}; -constexpr Vec4U8 PURPLE_A200 = Vec4U8{0xE0, 0x40, 0xFB, 0xFF}; -constexpr Vec4U8 PURPLE_A400 = Vec4U8{0xD5, 0x00, 0xF9, 0xFF}; -constexpr Vec4U8 PURPLE_A700 = Vec4U8{0xAA, 0x00, 0xFF, 0xFF}; - -constexpr Vec4U8 DEEP_PURPLE_50 = Vec4U8{0xED, 0xE7, 0xF6, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_100 = Vec4U8{0xD1, 0xC4, 0xE9, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_200 = Vec4U8{0xB3, 0x9D, 0xDB, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_300 = Vec4U8{0x95, 0x75, 0xCD, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_400 = Vec4U8{0x7E, 0x57, 0xC2, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_500 = Vec4U8{0x67, 0x3A, 0xB7, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_600 = Vec4U8{0x5E, 0x35, 0xB1, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_700 = Vec4U8{0x51, 0x2D, 0xA8, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_800 = Vec4U8{0x45, 0x27, 0xA0, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_900 = Vec4U8{0x31, 0x1B, 0x92, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_A100 = Vec4U8{0xB3, 0x88, 0xFF, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_A200 = Vec4U8{0x7C, 0x4D, 0xFF, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_A400 = Vec4U8{0x65, 0x1F, 0xFF, 0xFF}; -constexpr Vec4U8 DEEP_PURPLE_A700 = Vec4U8{0x62, 0x00, 0xEA, 0xFF}; - -constexpr Vec4U8 INDIGO_50 = Vec4U8{0xE8, 0xEA, 0xF6, 0xFF}; -constexpr Vec4U8 INDIGO_100 = Vec4U8{0xC5, 0xCA, 0xE9, 0xFF}; -constexpr Vec4U8 INDIGO_200 = Vec4U8{0x9F, 0xA8, 0xDA, 0xFF}; -constexpr Vec4U8 INDIGO_300 = Vec4U8{0x79, 0x86, 0xCB, 0xFF}; -constexpr Vec4U8 INDIGO_400 = Vec4U8{0x5C, 0x6B, 0xC0, 0xFF}; -constexpr Vec4U8 INDIGO_500 = Vec4U8{0x3F, 0x51, 0xB5, 0xFF}; -constexpr Vec4U8 INDIGO_600 = Vec4U8{0x39, 0x49, 0xAB, 0xFF}; -constexpr Vec4U8 INDIGO_700 = Vec4U8{0x30, 0x3F, 0x9F, 0xFF}; -constexpr Vec4U8 INDIGO_800 = Vec4U8{0x28, 0x35, 0x93, 0xFF}; -constexpr Vec4U8 INDIGO_900 = Vec4U8{0x1A, 0x23, 0x7E, 0xFF}; -constexpr Vec4U8 INDIGO_A100 = Vec4U8{0x8C, 0x9E, 0xFF, 0xFF}; -constexpr Vec4U8 INDIGO_A200 = Vec4U8{0x53, 0x6D, 0xFE, 0xFF}; -constexpr Vec4U8 INDIGO_A400 = Vec4U8{0x3D, 0x5A, 0xFE, 0xFF}; -constexpr Vec4U8 INDIGO_A700 = Vec4U8{0x30, 0x4F, 0xFE, 0xFF}; - -constexpr Vec4U8 BLUE_50 = Vec4U8{0xE3, 0xF2, 0xFD, 0xFF}; -constexpr Vec4U8 BLUE_100 = Vec4U8{0xBB, 0xDE, 0xFB, 0xFF}; -constexpr Vec4U8 BLUE_200 = Vec4U8{0x90, 0xCA, 0xF9, 0xFF}; -constexpr Vec4U8 BLUE_300 = Vec4U8{0x64, 0xB5, 0xF6, 0xFF}; -constexpr Vec4U8 BLUE_400 = Vec4U8{0x42, 0xA5, 0xF5, 0xFF}; -constexpr Vec4U8 BLUE_500 = Vec4U8{0x21, 0x96, 0xF3, 0xFF}; -constexpr Vec4U8 BLUE_600 = Vec4U8{0x1E, 0x88, 0xE5, 0xFF}; -constexpr Vec4U8 BLUE_700 = Vec4U8{0x19, 0x76, 0xD2, 0xFF}; -constexpr Vec4U8 BLUE_800 = Vec4U8{0x15, 0x65, 0xC0, 0xFF}; -constexpr Vec4U8 BLUE_900 = Vec4U8{0x0D, 0x47, 0xA1, 0xFF}; -constexpr Vec4U8 BLUE_A100 = Vec4U8{0x82, 0xB1, 0xFF, 0xFF}; -constexpr Vec4U8 BLUE_A200 = Vec4U8{0x44, 0x8A, 0xFF, 0xFF}; -constexpr Vec4U8 BLUE_A400 = Vec4U8{0x29, 0x79, 0xFF, 0xFF}; -constexpr Vec4U8 BLUE_A700 = Vec4U8{0x29, 0x62, 0xFF, 0xFF}; - -constexpr Vec4U8 LIGHT_BLUE_50 = Vec4U8{0xE1, 0xF5, 0xFE, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_100 = Vec4U8{0xB3, 0xE5, 0xFC, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_200 = Vec4U8{0x81, 0xD4, 0xFA, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_300 = Vec4U8{0x4F, 0xC3, 0xF7, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_400 = Vec4U8{0x29, 0xB6, 0xF6, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_500 = Vec4U8{0x03, 0xA9, 0xF4, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_600 = Vec4U8{0x03, 0x9B, 0xE5, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_700 = Vec4U8{0x02, 0x88, 0xD1, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_800 = Vec4U8{0x02, 0x77, 0xBD, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_900 = Vec4U8{0x01, 0x57, 0x9B, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_A100 = Vec4U8{0x80, 0xD8, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_A200 = Vec4U8{0x40, 0xC4, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_A400 = Vec4U8{0x00, 0xB0, 0xFF, 0xFF}; -constexpr Vec4U8 LIGHT_BLUE_A700 = Vec4U8{0x00, 0x91, 0xEA, 0xFF}; - -constexpr Vec4U8 CYAN_50 = Vec4U8{0xE0, 0xF7, 0xFA, 0xFF}; -constexpr Vec4U8 CYAN_100 = Vec4U8{0xB2, 0xEB, 0xF2, 0xFF}; -constexpr Vec4U8 CYAN_200 = Vec4U8{0x80, 0xDE, 0xEA, 0xFF}; -constexpr Vec4U8 CYAN_300 = Vec4U8{0x4D, 0xD0, 0xE1, 0xFF}; -constexpr Vec4U8 CYAN_400 = Vec4U8{0x26, 0xC6, 0xDA, 0xFF}; -constexpr Vec4U8 CYAN_500 = Vec4U8{0x00, 0xBC, 0xD4, 0xFF}; -constexpr Vec4U8 CYAN_600 = Vec4U8{0x00, 0xAC, 0xC1, 0xFF}; -constexpr Vec4U8 CYAN_700 = Vec4U8{0x00, 0x97, 0xA7, 0xFF}; -constexpr Vec4U8 CYAN_800 = Vec4U8{0x00, 0x83, 0x8F, 0xFF}; -constexpr Vec4U8 CYAN_900 = Vec4U8{0x00, 0x60, 0x64, 0xFF}; -constexpr Vec4U8 CYAN_A100 = Vec4U8{0x84, 0xFF, 0xFF, 0xFF}; -constexpr Vec4U8 CYAN_A200 = Vec4U8{0x18, 0xFF, 0xFF, 0xFF}; -constexpr Vec4U8 CYAN_A400 = Vec4U8{0x00, 0xE5, 0xFF, 0xFF}; -constexpr Vec4U8 CYAN_A700 = Vec4U8{0x00, 0xB8, 0xD4, 0xFF}; - -constexpr Vec4U8 TEAL_50 = Vec4U8{0xE0, 0xF2, 0xF1, 0xFF}; -constexpr Vec4U8 TEAL_100 = Vec4U8{0xB2, 0xDF, 0xDB, 0xFF}; -constexpr Vec4U8 TEAL_200 = Vec4U8{0x80, 0xCB, 0xC4, 0xFF}; -constexpr Vec4U8 TEAL_300 = Vec4U8{0x4D, 0xB6, 0xAC, 0xFF}; -constexpr Vec4U8 TEAL_400 = Vec4U8{0x26, 0xA6, 0x9A, 0xFF}; -constexpr Vec4U8 TEAL_500 = Vec4U8{0x00, 0x96, 0x88, 0xFF}; -constexpr Vec4U8 TEAL_600 = Vec4U8{0x00, 0x89, 0x7B, 0xFF}; -constexpr Vec4U8 TEAL_700 = Vec4U8{0x00, 0x79, 0x6B, 0xFF}; -constexpr Vec4U8 TEAL_800 = Vec4U8{0x00, 0x69, 0x5C, 0xFF}; -constexpr Vec4U8 TEAL_900 = Vec4U8{0x00, 0x4D, 0x40, 0xFF}; -constexpr Vec4U8 TEAL_A100 = Vec4U8{0xA7, 0xFF, 0xEB, 0xFF}; -constexpr Vec4U8 TEAL_A200 = Vec4U8{0x64, 0xFF, 0xDA, 0xFF}; -constexpr Vec4U8 TEAL_A400 = Vec4U8{0x1D, 0xE9, 0xB6, 0xFF}; -constexpr Vec4U8 TEAL_A700 = Vec4U8{0x00, 0xBF, 0xA5, 0xFF}; - -constexpr Vec4U8 GREEN_50 = Vec4U8{0xE8, 0xF5, 0xE9, 0xFF}; -constexpr Vec4U8 GREEN_100 = Vec4U8{0xC8, 0xE6, 0xC9, 0xFF}; -constexpr Vec4U8 GREEN_200 = Vec4U8{0xA5, 0xD6, 0xA7, 0xFF}; -constexpr Vec4U8 GREEN_300 = Vec4U8{0x81, 0xC7, 0x84, 0xFF}; -constexpr Vec4U8 GREEN_400 = Vec4U8{0x66, 0xBB, 0x6A, 0xFF}; -constexpr Vec4U8 GREEN_500 = Vec4U8{0x4C, 0xAF, 0x50, 0xFF}; -constexpr Vec4U8 GREEN_600 = Vec4U8{0x43, 0xA0, 0x47, 0xFF}; -constexpr Vec4U8 GREEN_700 = Vec4U8{0x38, 0x8E, 0x3C, 0xFF}; -constexpr Vec4U8 GREEN_800 = Vec4U8{0x2E, 0x7D, 0x32, 0xFF}; -constexpr Vec4U8 GREEN_900 = Vec4U8{0x1B, 0x5E, 0x20, 0xFF}; -constexpr Vec4U8 GREEN_A100 = Vec4U8{0xB9, 0xF6, 0xCA, 0xFF}; -constexpr Vec4U8 GREEN_A200 = Vec4U8{0x69, 0xF0, 0xAE, 0xFF}; -constexpr Vec4U8 GREEN_A400 = Vec4U8{0x00, 0xE6, 0x76, 0xFF}; -constexpr Vec4U8 GREEN_A700 = Vec4U8{0x00, 0xC8, 0x53, 0xFF}; - -constexpr Vec4U8 LIGHT_GREEN_50 = Vec4U8{0xF1, 0xF8, 0xE9, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_100 = Vec4U8{0xDC, 0xED, 0xC8, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_200 = Vec4U8{0xC5, 0xE1, 0xA5, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_300 = Vec4U8{0xAE, 0xD5, 0x81, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_400 = Vec4U8{0x9C, 0xCC, 0x65, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_500 = Vec4U8{0x8B, 0xC3, 0x4A, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_600 = Vec4U8{0x7C, 0xB3, 0x42, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_700 = Vec4U8{0x68, 0x9F, 0x38, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_800 = Vec4U8{0x55, 0x8B, 0x2F, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_900 = Vec4U8{0x33, 0x69, 0x1E, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_A100 = Vec4U8{0xCC, 0xFF, 0x90, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_A200 = Vec4U8{0xB2, 0xFF, 0x59, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_A400 = Vec4U8{0x76, 0xFF, 0x03, 0xFF}; -constexpr Vec4U8 LIGHT_GREEN_A700 = Vec4U8{0x64, 0xDD, 0x17, 0xFF}; - -constexpr Vec4U8 LIME_50 = Vec4U8{0xF9, 0xFB, 0xE7, 0xFF}; -constexpr Vec4U8 LIME_100 = Vec4U8{0xF0, 0xF4, 0xC3, 0xFF}; -constexpr Vec4U8 LIME_200 = Vec4U8{0xE6, 0xEE, 0x9C, 0xFF}; -constexpr Vec4U8 LIME_300 = Vec4U8{0xDC, 0xE7, 0x75, 0xFF}; -constexpr Vec4U8 LIME_400 = Vec4U8{0xD4, 0xE1, 0x57, 0xFF}; -constexpr Vec4U8 LIME_500 = Vec4U8{0xCD, 0xDC, 0x39, 0xFF}; -constexpr Vec4U8 LIME_600 = Vec4U8{0xC0, 0xCA, 0x33, 0xFF}; -constexpr Vec4U8 LIME_700 = Vec4U8{0xAF, 0xB4, 0x2B, 0xFF}; -constexpr Vec4U8 LIME_800 = Vec4U8{0x9E, 0x9D, 0x24, 0xFF}; -constexpr Vec4U8 LIME_900 = Vec4U8{0x82, 0x77, 0x17, 0xFF}; -constexpr Vec4U8 LIME_A100 = Vec4U8{0xF4, 0xFF, 0x81, 0xFF}; -constexpr Vec4U8 LIME_A200 = Vec4U8{0xEE, 0xFF, 0x41, 0xFF}; -constexpr Vec4U8 LIME_A400 = Vec4U8{0xC6, 0xFF, 0x00, 0xFF}; -constexpr Vec4U8 LIME_A700 = Vec4U8{0xAE, 0xEA, 0x00, 0xFF}; - -constexpr Vec4U8 YELLOW_50 = Vec4U8{0xFF, 0xFD, 0xE7, 0xFF}; -constexpr Vec4U8 YELLOW_100 = Vec4U8{0xFF, 0xF9, 0xC4, 0xFF}; -constexpr Vec4U8 YELLOW_200 = Vec4U8{0xFF, 0xF5, 0x9D, 0xFF}; -constexpr Vec4U8 YELLOW_300 = Vec4U8{0xFF, 0xF1, 0x76, 0xFF}; -constexpr Vec4U8 YELLOW_400 = Vec4U8{0xFF, 0xEE, 0x58, 0xFF}; -constexpr Vec4U8 YELLOW_500 = Vec4U8{0xFF, 0xEB, 0x3B, 0xFF}; -constexpr Vec4U8 YELLOW_600 = Vec4U8{0xFD, 0xD8, 0x35, 0xFF}; -constexpr Vec4U8 YELLOW_700 = Vec4U8{0xFB, 0xC0, 0x2D, 0xFF}; -constexpr Vec4U8 YELLOW_800 = Vec4U8{0xF9, 0xA8, 0x25, 0xFF}; -constexpr Vec4U8 YELLOW_900 = Vec4U8{0xF5, 0x7F, 0x17, 0xFF}; -constexpr Vec4U8 YELLOW_A100 = Vec4U8{0xFF, 0xFF, 0x8D, 0xFF}; -constexpr Vec4U8 YELLOW_A200 = Vec4U8{0xFF, 0xFF, 0x00, 0xFF}; -constexpr Vec4U8 YELLOW_A400 = Vec4U8{0xFF, 0xEA, 0x00, 0xFF}; -constexpr Vec4U8 YELLOW_A700 = Vec4U8{0xFF, 0xD6, 0x00, 0xFF}; - -constexpr Vec4U8 AMBER_50 = Vec4U8{0xFF, 0xF8, 0xE1, 0xFF}; -constexpr Vec4U8 AMBER_100 = Vec4U8{0xFF, 0xEC, 0xB3, 0xFF}; -constexpr Vec4U8 AMBER_200 = Vec4U8{0xFF, 0xE0, 0x82, 0xFF}; -constexpr Vec4U8 AMBER_300 = Vec4U8{0xFF, 0xD5, 0x4F, 0xFF}; -constexpr Vec4U8 AMBER_400 = Vec4U8{0xFF, 0xCA, 0x28, 0xFF}; -constexpr Vec4U8 AMBER_500 = Vec4U8{0xFF, 0xC1, 0x07, 0xFF}; -constexpr Vec4U8 AMBER_600 = Vec4U8{0xFF, 0xB3, 0x00, 0xFF}; -constexpr Vec4U8 AMBER_700 = Vec4U8{0xFF, 0xA0, 0x00, 0xFF}; -constexpr Vec4U8 AMBER_800 = Vec4U8{0xFF, 0x8F, 0x00, 0xFF}; -constexpr Vec4U8 AMBER_900 = Vec4U8{0xFF, 0x6F, 0x00, 0xFF}; -constexpr Vec4U8 AMBER_A100 = Vec4U8{0xFF, 0xE5, 0x7F, 0xFF}; -constexpr Vec4U8 AMBER_A200 = Vec4U8{0xFF, 0xD7, 0x40, 0xFF}; -constexpr Vec4U8 AMBER_A400 = Vec4U8{0xFF, 0xC4, 0x00, 0xFF}; -constexpr Vec4U8 AMBER_A700 = Vec4U8{0xFF, 0xAB, 0x00, 0xFF}; - -constexpr Vec4U8 ORANGE_50 = Vec4U8{0xFF, 0xF3, 0xE0, 0xFF}; -constexpr Vec4U8 ORANGE_100 = Vec4U8{0xFF, 0xE0, 0xB2, 0xFF}; -constexpr Vec4U8 ORANGE_200 = Vec4U8{0xFF, 0xCC, 0x80, 0xFF}; -constexpr Vec4U8 ORANGE_300 = Vec4U8{0xFF, 0xB7, 0x4D, 0xFF}; -constexpr Vec4U8 ORANGE_400 = Vec4U8{0xFF, 0xA7, 0x26, 0xFF}; -constexpr Vec4U8 ORANGE_500 = Vec4U8{0xFF, 0x98, 0x00, 0xFF}; -constexpr Vec4U8 ORANGE_600 = Vec4U8{0xFB, 0x8C, 0x00, 0xFF}; -constexpr Vec4U8 ORANGE_700 = Vec4U8{0xF5, 0x7C, 0x00, 0xFF}; -constexpr Vec4U8 ORANGE_800 = Vec4U8{0xEF, 0x6C, 0x00, 0xFF}; -constexpr Vec4U8 ORANGE_900 = Vec4U8{0xE6, 0x51, 0x00, 0xFF}; -constexpr Vec4U8 ORANGE_A100 = Vec4U8{0xFF, 0xD1, 0x80, 0xFF}; -constexpr Vec4U8 ORANGE_A200 = Vec4U8{0xFF, 0xAB, 0x40, 0xFF}; -constexpr Vec4U8 ORANGE_A400 = Vec4U8{0xFF, 0x91, 0x00, 0xFF}; -constexpr Vec4U8 ORANGE_A700 = Vec4U8{0xFF, 0x6D, 0x00, 0xFF}; - -constexpr Vec4U8 DEEP_ORANGE_50 = Vec4U8{0xFB, 0xE9, 0xE7, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_100 = Vec4U8{0xFF, 0xCC, 0xBC, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_200 = Vec4U8{0xFF, 0xAB, 0x91, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_300 = Vec4U8{0xFF, 0x8A, 0x65, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_400 = Vec4U8{0xFF, 0x70, 0x43, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_500 = Vec4U8{0xFF, 0x57, 0x22, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_600 = Vec4U8{0xF4, 0x51, 0x1E, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_700 = Vec4U8{0xE6, 0x4A, 0x19, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_800 = Vec4U8{0xD8, 0x43, 0x15, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_900 = Vec4U8{0xBF, 0x36, 0x0C, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_A100 = Vec4U8{0xFF, 0x9E, 0x80, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_A200 = Vec4U8{0xFF, 0x6E, 0x40, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_A400 = Vec4U8{0xFF, 0x3D, 0x00, 0xFF}; -constexpr Vec4U8 DEEP_ORANGE_A700 = Vec4U8{0xDD, 0x2C, 0x00, 0xFF}; - -constexpr Vec4U8 BROWN_50 = Vec4U8{0xEF, 0xEB, 0xE9, 0xFF}; -constexpr Vec4U8 BROWN_100 = Vec4U8{0xD7, 0xCC, 0xC8, 0xFF}; -constexpr Vec4U8 BROWN_200 = Vec4U8{0xBC, 0xAA, 0xA4, 0xFF}; -constexpr Vec4U8 BROWN_300 = Vec4U8{0xA1, 0x88, 0x7F, 0xFF}; -constexpr Vec4U8 BROWN_400 = Vec4U8{0x8D, 0x6E, 0x63, 0xFF}; -constexpr Vec4U8 BROWN_500 = Vec4U8{0x79, 0x55, 0x48, 0xFF}; -constexpr Vec4U8 BROWN_600 = Vec4U8{0x6D, 0x4C, 0x41, 0xFF}; -constexpr Vec4U8 BROWN_700 = Vec4U8{0x5D, 0x40, 0x37, 0xFF}; -constexpr Vec4U8 BROWN_800 = Vec4U8{0x4E, 0x34, 0x2E, 0xFF}; -constexpr Vec4U8 BROWN_900 = Vec4U8{0x3E, 0x27, 0x23, 0xFF}; - -constexpr Vec4U8 GRAY_50 = Vec4U8{0xFA, 0xFA, 0xFA, 0xFF}; -constexpr Vec4U8 GRAY_100 = Vec4U8{0xF5, 0xF5, 0xF5, 0xFF}; -constexpr Vec4U8 GRAY_200 = Vec4U8{0xEE, 0xEE, 0xEE, 0xFF}; -constexpr Vec4U8 GRAY_300 = Vec4U8{0xE0, 0xE0, 0xE0, 0xFF}; -constexpr Vec4U8 GRAY_400 = Vec4U8{0xBD, 0xBD, 0xBD, 0xFF}; -constexpr Vec4U8 GRAY_500 = Vec4U8{0x9E, 0x9E, 0x9E, 0xFF}; -constexpr Vec4U8 GRAY_600 = Vec4U8{0x75, 0x75, 0x75, 0xFF}; -constexpr Vec4U8 GRAY_700 = Vec4U8{0x61, 0x61, 0x61, 0xFF}; -constexpr Vec4U8 GRAY_800 = Vec4U8{0x42, 0x42, 0x42, 0xFF}; -constexpr Vec4U8 GRAY_900 = Vec4U8{0x21, 0x21, 0x21, 0xFF}; - -constexpr Vec4U8 BLUE_GRAY_50 = Vec4U8{0xEC, 0xEF, 0xF1, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_100 = Vec4U8{0xCF, 0xD8, 0xDC, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_200 = Vec4U8{0xB0, 0xBE, 0xC5, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_300 = Vec4U8{0x90, 0xA4, 0xAE, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_400 = Vec4U8{0x78, 0x90, 0x9C, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_500 = Vec4U8{0x60, 0x7D, 0x8B, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_600 = Vec4U8{0x54, 0x6E, 0x7A, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_700 = Vec4U8{0x45, 0x5A, 0x64, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_800 = Vec4U8{0x37, 0x47, 0x4F, 0xFF}; -constexpr Vec4U8 BLUE_GRAY_900 = Vec4U8{0x26, 0x32, 0x38, 0xFF}; - -constexpr Vec4U8 WHITE = Vec4U8{0xFF, 0xFF, 0xFF, 0xFF}; -constexpr Vec4U8 BLACK = Vec4U8{0x00, 0x00, 0x00, 0xFF}; +inline constexpr Vec4U8 RED_50 = Vec4U8{0xFF, 0xEB, 0xEE, 0xFF}; +inline constexpr Vec4U8 RED_100 = Vec4U8{0xFF, 0xCD, 0xD2, 0xFF}; +inline constexpr Vec4U8 RED_200 = Vec4U8{0xEF, 0x9A, 0x9A, 0xFF}; +inline constexpr Vec4U8 RED_300 = Vec4U8{0xE5, 0x73, 0x73, 0xFF}; +inline constexpr Vec4U8 RED_400 = Vec4U8{0xEF, 0x53, 0x50, 0xFF}; +inline constexpr Vec4U8 RED_500 = Vec4U8{0xF4, 0x43, 0x36, 0xFF}; +inline constexpr Vec4U8 RED_600 = Vec4U8{0xE5, 0x39, 0x35, 0xFF}; +inline constexpr Vec4U8 RED_700 = Vec4U8{0xD3, 0x2F, 0x2F, 0xFF}; +inline constexpr Vec4U8 RED_800 = Vec4U8{0xC6, 0x28, 0x28, 0xFF}; +inline constexpr Vec4U8 RED_900 = Vec4U8{0xB7, 0x1C, 0x1C, 0xFF}; +inline constexpr Vec4U8 RED_A100 = Vec4U8{0xFF, 0x8A, 0x80, 0xFF}; +inline constexpr Vec4U8 RED_A200 = Vec4U8{0xFF, 0x52, 0x52, 0xFF}; +inline constexpr Vec4U8 RED_A400 = Vec4U8{0xFF, 0x17, 0x44, 0xFF}; +inline constexpr Vec4U8 RED_A700 = Vec4U8{0xD5, 0x00, 0x00, 0xFF}; + +inline constexpr Vec4U8 PINK_50 = Vec4U8{0xFC, 0xE4, 0xEC, 0xFF}; +inline constexpr Vec4U8 PINK_100 = Vec4U8{0xF8, 0xBB, 0xD0, 0xFF}; +inline constexpr Vec4U8 PINK_200 = Vec4U8{0xF4, 0x8F, 0xB1, 0xFF}; +inline constexpr Vec4U8 PINK_300 = Vec4U8{0xF0, 0x62, 0x92, 0xFF}; +inline constexpr Vec4U8 PINK_400 = Vec4U8{0xEC, 0x40, 0x7A, 0xFF}; +inline constexpr Vec4U8 PINK_500 = Vec4U8{0xE9, 0x1E, 0x63, 0xFF}; +inline constexpr Vec4U8 PINK_600 = Vec4U8{0xD8, 0x1B, 0x60, 0xFF}; +inline constexpr Vec4U8 PINK_700 = Vec4U8{0xC2, 0x18, 0x5B, 0xFF}; +inline constexpr Vec4U8 PINK_800 = Vec4U8{0xAD, 0x14, 0x57, 0xFF}; +inline constexpr Vec4U8 PINK_900 = Vec4U8{0x88, 0x0E, 0x4F, 0xFF}; +inline constexpr Vec4U8 PINK_A100 = Vec4U8{0xFF, 0x80, 0xAB, 0xFF}; +inline constexpr Vec4U8 PINK_A200 = Vec4U8{0xFF, 0x40, 0x81, 0xFF}; +inline constexpr Vec4U8 PINK_A400 = Vec4U8{0xF5, 0x00, 0x57, 0xFF}; +inline constexpr Vec4U8 PINK_A700 = Vec4U8{0xC5, 0x11, 0x62, 0xFF}; + +inline constexpr Vec4U8 PURPLE_50 = Vec4U8{0xF3, 0xE5, 0xF5, 0xFF}; +inline constexpr Vec4U8 PURPLE_100 = Vec4U8{0xE1, 0xBE, 0xE7, 0xFF}; +inline constexpr Vec4U8 PURPLE_200 = Vec4U8{0xCE, 0x93, 0xD8, 0xFF}; +inline constexpr Vec4U8 PURPLE_300 = Vec4U8{0xBA, 0x68, 0xC8, 0xFF}; +inline constexpr Vec4U8 PURPLE_400 = Vec4U8{0xAB, 0x47, 0xBC, 0xFF}; +inline constexpr Vec4U8 PURPLE_500 = Vec4U8{0x9C, 0x27, 0xB0, 0xFF}; +inline constexpr Vec4U8 PURPLE_600 = Vec4U8{0x8E, 0x24, 0xAA, 0xFF}; +inline constexpr Vec4U8 PURPLE_700 = Vec4U8{0x7B, 0x1F, 0xA2, 0xFF}; +inline constexpr Vec4U8 PURPLE_800 = Vec4U8{0x6A, 0x1B, 0x9A, 0xFF}; +inline constexpr Vec4U8 PURPLE_900 = Vec4U8{0x4A, 0x14, 0x8C, 0xFF}; +inline constexpr Vec4U8 PURPLE_A100 = Vec4U8{0xEA, 0x80, 0xFC, 0xFF}; +inline constexpr Vec4U8 PURPLE_A200 = Vec4U8{0xE0, 0x40, 0xFB, 0xFF}; +inline constexpr Vec4U8 PURPLE_A400 = Vec4U8{0xD5, 0x00, 0xF9, 0xFF}; +inline constexpr Vec4U8 PURPLE_A700 = Vec4U8{0xAA, 0x00, 0xFF, 0xFF}; + +inline constexpr Vec4U8 DEEP_PURPLE_50 = Vec4U8{0xED, 0xE7, 0xF6, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_100 = Vec4U8{0xD1, 0xC4, 0xE9, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_200 = Vec4U8{0xB3, 0x9D, 0xDB, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_300 = Vec4U8{0x95, 0x75, 0xCD, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_400 = Vec4U8{0x7E, 0x57, 0xC2, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_500 = Vec4U8{0x67, 0x3A, 0xB7, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_600 = Vec4U8{0x5E, 0x35, 0xB1, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_700 = Vec4U8{0x51, 0x2D, 0xA8, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_800 = Vec4U8{0x45, 0x27, 0xA0, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_900 = Vec4U8{0x31, 0x1B, 0x92, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_A100 = Vec4U8{0xB3, 0x88, 0xFF, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_A200 = Vec4U8{0x7C, 0x4D, 0xFF, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_A400 = Vec4U8{0x65, 0x1F, 0xFF, 0xFF}; +inline constexpr Vec4U8 DEEP_PURPLE_A700 = Vec4U8{0x62, 0x00, 0xEA, 0xFF}; + +inline constexpr Vec4U8 INDIGO_50 = Vec4U8{0xE8, 0xEA, 0xF6, 0xFF}; +inline constexpr Vec4U8 INDIGO_100 = Vec4U8{0xC5, 0xCA, 0xE9, 0xFF}; +inline constexpr Vec4U8 INDIGO_200 = Vec4U8{0x9F, 0xA8, 0xDA, 0xFF}; +inline constexpr Vec4U8 INDIGO_300 = Vec4U8{0x79, 0x86, 0xCB, 0xFF}; +inline constexpr Vec4U8 INDIGO_400 = Vec4U8{0x5C, 0x6B, 0xC0, 0xFF}; +inline constexpr Vec4U8 INDIGO_500 = Vec4U8{0x3F, 0x51, 0xB5, 0xFF}; +inline constexpr Vec4U8 INDIGO_600 = Vec4U8{0x39, 0x49, 0xAB, 0xFF}; +inline constexpr Vec4U8 INDIGO_700 = Vec4U8{0x30, 0x3F, 0x9F, 0xFF}; +inline constexpr Vec4U8 INDIGO_800 = Vec4U8{0x28, 0x35, 0x93, 0xFF}; +inline constexpr Vec4U8 INDIGO_900 = Vec4U8{0x1A, 0x23, 0x7E, 0xFF}; +inline constexpr Vec4U8 INDIGO_A100 = Vec4U8{0x8C, 0x9E, 0xFF, 0xFF}; +inline constexpr Vec4U8 INDIGO_A200 = Vec4U8{0x53, 0x6D, 0xFE, 0xFF}; +inline constexpr Vec4U8 INDIGO_A400 = Vec4U8{0x3D, 0x5A, 0xFE, 0xFF}; +inline constexpr Vec4U8 INDIGO_A700 = Vec4U8{0x30, 0x4F, 0xFE, 0xFF}; + +inline constexpr Vec4U8 BLUE_50 = Vec4U8{0xE3, 0xF2, 0xFD, 0xFF}; +inline constexpr Vec4U8 BLUE_100 = Vec4U8{0xBB, 0xDE, 0xFB, 0xFF}; +inline constexpr Vec4U8 BLUE_200 = Vec4U8{0x90, 0xCA, 0xF9, 0xFF}; +inline constexpr Vec4U8 BLUE_300 = Vec4U8{0x64, 0xB5, 0xF6, 0xFF}; +inline constexpr Vec4U8 BLUE_400 = Vec4U8{0x42, 0xA5, 0xF5, 0xFF}; +inline constexpr Vec4U8 BLUE_500 = Vec4U8{0x21, 0x96, 0xF3, 0xFF}; +inline constexpr Vec4U8 BLUE_600 = Vec4U8{0x1E, 0x88, 0xE5, 0xFF}; +inline constexpr Vec4U8 BLUE_700 = Vec4U8{0x19, 0x76, 0xD2, 0xFF}; +inline constexpr Vec4U8 BLUE_800 = Vec4U8{0x15, 0x65, 0xC0, 0xFF}; +inline constexpr Vec4U8 BLUE_900 = Vec4U8{0x0D, 0x47, 0xA1, 0xFF}; +inline constexpr Vec4U8 BLUE_A100 = Vec4U8{0x82, 0xB1, 0xFF, 0xFF}; +inline constexpr Vec4U8 BLUE_A200 = Vec4U8{0x44, 0x8A, 0xFF, 0xFF}; +inline constexpr Vec4U8 BLUE_A400 = Vec4U8{0x29, 0x79, 0xFF, 0xFF}; +inline constexpr Vec4U8 BLUE_A700 = Vec4U8{0x29, 0x62, 0xFF, 0xFF}; + +inline constexpr Vec4U8 LIGHT_BLUE_50 = Vec4U8{0xE1, 0xF5, 0xFE, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_100 = Vec4U8{0xB3, 0xE5, 0xFC, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_200 = Vec4U8{0x81, 0xD4, 0xFA, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_300 = Vec4U8{0x4F, 0xC3, 0xF7, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_400 = Vec4U8{0x29, 0xB6, 0xF6, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_500 = Vec4U8{0x03, 0xA9, 0xF4, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_600 = Vec4U8{0x03, 0x9B, 0xE5, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_700 = Vec4U8{0x02, 0x88, 0xD1, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_800 = Vec4U8{0x02, 0x77, 0xBD, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_900 = Vec4U8{0x01, 0x57, 0x9B, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_A100 = Vec4U8{0x80, 0xD8, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_A200 = Vec4U8{0x40, 0xC4, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_A400 = Vec4U8{0x00, 0xB0, 0xFF, 0xFF}; +inline constexpr Vec4U8 LIGHT_BLUE_A700 = Vec4U8{0x00, 0x91, 0xEA, 0xFF}; + +inline constexpr Vec4U8 CYAN_50 = Vec4U8{0xE0, 0xF7, 0xFA, 0xFF}; +inline constexpr Vec4U8 CYAN_100 = Vec4U8{0xB2, 0xEB, 0xF2, 0xFF}; +inline constexpr Vec4U8 CYAN_200 = Vec4U8{0x80, 0xDE, 0xEA, 0xFF}; +inline constexpr Vec4U8 CYAN_300 = Vec4U8{0x4D, 0xD0, 0xE1, 0xFF}; +inline constexpr Vec4U8 CYAN_400 = Vec4U8{0x26, 0xC6, 0xDA, 0xFF}; +inline constexpr Vec4U8 CYAN_500 = Vec4U8{0x00, 0xBC, 0xD4, 0xFF}; +inline constexpr Vec4U8 CYAN_600 = Vec4U8{0x00, 0xAC, 0xC1, 0xFF}; +inline constexpr Vec4U8 CYAN_700 = Vec4U8{0x00, 0x97, 0xA7, 0xFF}; +inline constexpr Vec4U8 CYAN_800 = Vec4U8{0x00, 0x83, 0x8F, 0xFF}; +inline constexpr Vec4U8 CYAN_900 = Vec4U8{0x00, 0x60, 0x64, 0xFF}; +inline constexpr Vec4U8 CYAN_A100 = Vec4U8{0x84, 0xFF, 0xFF, 0xFF}; +inline constexpr Vec4U8 CYAN_A200 = Vec4U8{0x18, 0xFF, 0xFF, 0xFF}; +inline constexpr Vec4U8 CYAN_A400 = Vec4U8{0x00, 0xE5, 0xFF, 0xFF}; +inline constexpr Vec4U8 CYAN_A700 = Vec4U8{0x00, 0xB8, 0xD4, 0xFF}; + +inline constexpr Vec4U8 TEAL_50 = Vec4U8{0xE0, 0xF2, 0xF1, 0xFF}; +inline constexpr Vec4U8 TEAL_100 = Vec4U8{0xB2, 0xDF, 0xDB, 0xFF}; +inline constexpr Vec4U8 TEAL_200 = Vec4U8{0x80, 0xCB, 0xC4, 0xFF}; +inline constexpr Vec4U8 TEAL_300 = Vec4U8{0x4D, 0xB6, 0xAC, 0xFF}; +inline constexpr Vec4U8 TEAL_400 = Vec4U8{0x26, 0xA6, 0x9A, 0xFF}; +inline constexpr Vec4U8 TEAL_500 = Vec4U8{0x00, 0x96, 0x88, 0xFF}; +inline constexpr Vec4U8 TEAL_600 = Vec4U8{0x00, 0x89, 0x7B, 0xFF}; +inline constexpr Vec4U8 TEAL_700 = Vec4U8{0x00, 0x79, 0x6B, 0xFF}; +inline constexpr Vec4U8 TEAL_800 = Vec4U8{0x00, 0x69, 0x5C, 0xFF}; +inline constexpr Vec4U8 TEAL_900 = Vec4U8{0x00, 0x4D, 0x40, 0xFF}; +inline constexpr Vec4U8 TEAL_A100 = Vec4U8{0xA7, 0xFF, 0xEB, 0xFF}; +inline constexpr Vec4U8 TEAL_A200 = Vec4U8{0x64, 0xFF, 0xDA, 0xFF}; +inline constexpr Vec4U8 TEAL_A400 = Vec4U8{0x1D, 0xE9, 0xB6, 0xFF}; +inline constexpr Vec4U8 TEAL_A700 = Vec4U8{0x00, 0xBF, 0xA5, 0xFF}; + +inline constexpr Vec4U8 GREEN_50 = Vec4U8{0xE8, 0xF5, 0xE9, 0xFF}; +inline constexpr Vec4U8 GREEN_100 = Vec4U8{0xC8, 0xE6, 0xC9, 0xFF}; +inline constexpr Vec4U8 GREEN_200 = Vec4U8{0xA5, 0xD6, 0xA7, 0xFF}; +inline constexpr Vec4U8 GREEN_300 = Vec4U8{0x81, 0xC7, 0x84, 0xFF}; +inline constexpr Vec4U8 GREEN_400 = Vec4U8{0x66, 0xBB, 0x6A, 0xFF}; +inline constexpr Vec4U8 GREEN_500 = Vec4U8{0x4C, 0xAF, 0x50, 0xFF}; +inline constexpr Vec4U8 GREEN_600 = Vec4U8{0x43, 0xA0, 0x47, 0xFF}; +inline constexpr Vec4U8 GREEN_700 = Vec4U8{0x38, 0x8E, 0x3C, 0xFF}; +inline constexpr Vec4U8 GREEN_800 = Vec4U8{0x2E, 0x7D, 0x32, 0xFF}; +inline constexpr Vec4U8 GREEN_900 = Vec4U8{0x1B, 0x5E, 0x20, 0xFF}; +inline constexpr Vec4U8 GREEN_A100 = Vec4U8{0xB9, 0xF6, 0xCA, 0xFF}; +inline constexpr Vec4U8 GREEN_A200 = Vec4U8{0x69, 0xF0, 0xAE, 0xFF}; +inline constexpr Vec4U8 GREEN_A400 = Vec4U8{0x00, 0xE6, 0x76, 0xFF}; +inline constexpr Vec4U8 GREEN_A700 = Vec4U8{0x00, 0xC8, 0x53, 0xFF}; + +inline constexpr Vec4U8 LIGHT_GREEN_50 = Vec4U8{0xF1, 0xF8, 0xE9, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_100 = Vec4U8{0xDC, 0xED, 0xC8, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_200 = Vec4U8{0xC5, 0xE1, 0xA5, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_300 = Vec4U8{0xAE, 0xD5, 0x81, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_400 = Vec4U8{0x9C, 0xCC, 0x65, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_500 = Vec4U8{0x8B, 0xC3, 0x4A, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_600 = Vec4U8{0x7C, 0xB3, 0x42, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_700 = Vec4U8{0x68, 0x9F, 0x38, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_800 = Vec4U8{0x55, 0x8B, 0x2F, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_900 = Vec4U8{0x33, 0x69, 0x1E, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_A100 = Vec4U8{0xCC, 0xFF, 0x90, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_A200 = Vec4U8{0xB2, 0xFF, 0x59, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_A400 = Vec4U8{0x76, 0xFF, 0x03, 0xFF}; +inline constexpr Vec4U8 LIGHT_GREEN_A700 = Vec4U8{0x64, 0xDD, 0x17, 0xFF}; + +inline constexpr Vec4U8 LIME_50 = Vec4U8{0xF9, 0xFB, 0xE7, 0xFF}; +inline constexpr Vec4U8 LIME_100 = Vec4U8{0xF0, 0xF4, 0xC3, 0xFF}; +inline constexpr Vec4U8 LIME_200 = Vec4U8{0xE6, 0xEE, 0x9C, 0xFF}; +inline constexpr Vec4U8 LIME_300 = Vec4U8{0xDC, 0xE7, 0x75, 0xFF}; +inline constexpr Vec4U8 LIME_400 = Vec4U8{0xD4, 0xE1, 0x57, 0xFF}; +inline constexpr Vec4U8 LIME_500 = Vec4U8{0xCD, 0xDC, 0x39, 0xFF}; +inline constexpr Vec4U8 LIME_600 = Vec4U8{0xC0, 0xCA, 0x33, 0xFF}; +inline constexpr Vec4U8 LIME_700 = Vec4U8{0xAF, 0xB4, 0x2B, 0xFF}; +inline constexpr Vec4U8 LIME_800 = Vec4U8{0x9E, 0x9D, 0x24, 0xFF}; +inline constexpr Vec4U8 LIME_900 = Vec4U8{0x82, 0x77, 0x17, 0xFF}; +inline constexpr Vec4U8 LIME_A100 = Vec4U8{0xF4, 0xFF, 0x81, 0xFF}; +inline constexpr Vec4U8 LIME_A200 = Vec4U8{0xEE, 0xFF, 0x41, 0xFF}; +inline constexpr Vec4U8 LIME_A400 = Vec4U8{0xC6, 0xFF, 0x00, 0xFF}; +inline constexpr Vec4U8 LIME_A700 = Vec4U8{0xAE, 0xEA, 0x00, 0xFF}; + +inline constexpr Vec4U8 YELLOW_50 = Vec4U8{0xFF, 0xFD, 0xE7, 0xFF}; +inline constexpr Vec4U8 YELLOW_100 = Vec4U8{0xFF, 0xF9, 0xC4, 0xFF}; +inline constexpr Vec4U8 YELLOW_200 = Vec4U8{0xFF, 0xF5, 0x9D, 0xFF}; +inline constexpr Vec4U8 YELLOW_300 = Vec4U8{0xFF, 0xF1, 0x76, 0xFF}; +inline constexpr Vec4U8 YELLOW_400 = Vec4U8{0xFF, 0xEE, 0x58, 0xFF}; +inline constexpr Vec4U8 YELLOW_500 = Vec4U8{0xFF, 0xEB, 0x3B, 0xFF}; +inline constexpr Vec4U8 YELLOW_600 = Vec4U8{0xFD, 0xD8, 0x35, 0xFF}; +inline constexpr Vec4U8 YELLOW_700 = Vec4U8{0xFB, 0xC0, 0x2D, 0xFF}; +inline constexpr Vec4U8 YELLOW_800 = Vec4U8{0xF9, 0xA8, 0x25, 0xFF}; +inline constexpr Vec4U8 YELLOW_900 = Vec4U8{0xF5, 0x7F, 0x17, 0xFF}; +inline constexpr Vec4U8 YELLOW_A100 = Vec4U8{0xFF, 0xFF, 0x8D, 0xFF}; +inline constexpr Vec4U8 YELLOW_A200 = Vec4U8{0xFF, 0xFF, 0x00, 0xFF}; +inline constexpr Vec4U8 YELLOW_A400 = Vec4U8{0xFF, 0xEA, 0x00, 0xFF}; +inline constexpr Vec4U8 YELLOW_A700 = Vec4U8{0xFF, 0xD6, 0x00, 0xFF}; + +inline constexpr Vec4U8 AMBER_50 = Vec4U8{0xFF, 0xF8, 0xE1, 0xFF}; +inline constexpr Vec4U8 AMBER_100 = Vec4U8{0xFF, 0xEC, 0xB3, 0xFF}; +inline constexpr Vec4U8 AMBER_200 = Vec4U8{0xFF, 0xE0, 0x82, 0xFF}; +inline constexpr Vec4U8 AMBER_300 = Vec4U8{0xFF, 0xD5, 0x4F, 0xFF}; +inline constexpr Vec4U8 AMBER_400 = Vec4U8{0xFF, 0xCA, 0x28, 0xFF}; +inline constexpr Vec4U8 AMBER_500 = Vec4U8{0xFF, 0xC1, 0x07, 0xFF}; +inline constexpr Vec4U8 AMBER_600 = Vec4U8{0xFF, 0xB3, 0x00, 0xFF}; +inline constexpr Vec4U8 AMBER_700 = Vec4U8{0xFF, 0xA0, 0x00, 0xFF}; +inline constexpr Vec4U8 AMBER_800 = Vec4U8{0xFF, 0x8F, 0x00, 0xFF}; +inline constexpr Vec4U8 AMBER_900 = Vec4U8{0xFF, 0x6F, 0x00, 0xFF}; +inline constexpr Vec4U8 AMBER_A100 = Vec4U8{0xFF, 0xE5, 0x7F, 0xFF}; +inline constexpr Vec4U8 AMBER_A200 = Vec4U8{0xFF, 0xD7, 0x40, 0xFF}; +inline constexpr Vec4U8 AMBER_A400 = Vec4U8{0xFF, 0xC4, 0x00, 0xFF}; +inline constexpr Vec4U8 AMBER_A700 = Vec4U8{0xFF, 0xAB, 0x00, 0xFF}; + +inline constexpr Vec4U8 ORANGE_50 = Vec4U8{0xFF, 0xF3, 0xE0, 0xFF}; +inline constexpr Vec4U8 ORANGE_100 = Vec4U8{0xFF, 0xE0, 0xB2, 0xFF}; +inline constexpr Vec4U8 ORANGE_200 = Vec4U8{0xFF, 0xCC, 0x80, 0xFF}; +inline constexpr Vec4U8 ORANGE_300 = Vec4U8{0xFF, 0xB7, 0x4D, 0xFF}; +inline constexpr Vec4U8 ORANGE_400 = Vec4U8{0xFF, 0xA7, 0x26, 0xFF}; +inline constexpr Vec4U8 ORANGE_500 = Vec4U8{0xFF, 0x98, 0x00, 0xFF}; +inline constexpr Vec4U8 ORANGE_600 = Vec4U8{0xFB, 0x8C, 0x00, 0xFF}; +inline constexpr Vec4U8 ORANGE_700 = Vec4U8{0xF5, 0x7C, 0x00, 0xFF}; +inline constexpr Vec4U8 ORANGE_800 = Vec4U8{0xEF, 0x6C, 0x00, 0xFF}; +inline constexpr Vec4U8 ORANGE_900 = Vec4U8{0xE6, 0x51, 0x00, 0xFF}; +inline constexpr Vec4U8 ORANGE_A100 = Vec4U8{0xFF, 0xD1, 0x80, 0xFF}; +inline constexpr Vec4U8 ORANGE_A200 = Vec4U8{0xFF, 0xAB, 0x40, 0xFF}; +inline constexpr Vec4U8 ORANGE_A400 = Vec4U8{0xFF, 0x91, 0x00, 0xFF}; +inline constexpr Vec4U8 ORANGE_A700 = Vec4U8{0xFF, 0x6D, 0x00, 0xFF}; + +inline constexpr Vec4U8 DEEP_ORANGE_50 = Vec4U8{0xFB, 0xE9, 0xE7, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_100 = Vec4U8{0xFF, 0xCC, 0xBC, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_200 = Vec4U8{0xFF, 0xAB, 0x91, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_300 = Vec4U8{0xFF, 0x8A, 0x65, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_400 = Vec4U8{0xFF, 0x70, 0x43, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_500 = Vec4U8{0xFF, 0x57, 0x22, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_600 = Vec4U8{0xF4, 0x51, 0x1E, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_700 = Vec4U8{0xE6, 0x4A, 0x19, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_800 = Vec4U8{0xD8, 0x43, 0x15, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_900 = Vec4U8{0xBF, 0x36, 0x0C, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_A100 = Vec4U8{0xFF, 0x9E, 0x80, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_A200 = Vec4U8{0xFF, 0x6E, 0x40, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_A400 = Vec4U8{0xFF, 0x3D, 0x00, 0xFF}; +inline constexpr Vec4U8 DEEP_ORANGE_A700 = Vec4U8{0xDD, 0x2C, 0x00, 0xFF}; + +inline constexpr Vec4U8 BROWN_50 = Vec4U8{0xEF, 0xEB, 0xE9, 0xFF}; +inline constexpr Vec4U8 BROWN_100 = Vec4U8{0xD7, 0xCC, 0xC8, 0xFF}; +inline constexpr Vec4U8 BROWN_200 = Vec4U8{0xBC, 0xAA, 0xA4, 0xFF}; +inline constexpr Vec4U8 BROWN_300 = Vec4U8{0xA1, 0x88, 0x7F, 0xFF}; +inline constexpr Vec4U8 BROWN_400 = Vec4U8{0x8D, 0x6E, 0x63, 0xFF}; +inline constexpr Vec4U8 BROWN_500 = Vec4U8{0x79, 0x55, 0x48, 0xFF}; +inline constexpr Vec4U8 BROWN_600 = Vec4U8{0x6D, 0x4C, 0x41, 0xFF}; +inline constexpr Vec4U8 BROWN_700 = Vec4U8{0x5D, 0x40, 0x37, 0xFF}; +inline constexpr Vec4U8 BROWN_800 = Vec4U8{0x4E, 0x34, 0x2E, 0xFF}; +inline constexpr Vec4U8 BROWN_900 = Vec4U8{0x3E, 0x27, 0x23, 0xFF}; + +inline constexpr Vec4U8 GRAY_50 = Vec4U8{0xFA, 0xFA, 0xFA, 0xFF}; +inline constexpr Vec4U8 GRAY_100 = Vec4U8{0xF5, 0xF5, 0xF5, 0xFF}; +inline constexpr Vec4U8 GRAY_200 = Vec4U8{0xEE, 0xEE, 0xEE, 0xFF}; +inline constexpr Vec4U8 GRAY_300 = Vec4U8{0xE0, 0xE0, 0xE0, 0xFF}; +inline constexpr Vec4U8 GRAY_400 = Vec4U8{0xBD, 0xBD, 0xBD, 0xFF}; +inline constexpr Vec4U8 GRAY_500 = Vec4U8{0x9E, 0x9E, 0x9E, 0xFF}; +inline constexpr Vec4U8 GRAY_600 = Vec4U8{0x75, 0x75, 0x75, 0xFF}; +inline constexpr Vec4U8 GRAY_700 = Vec4U8{0x61, 0x61, 0x61, 0xFF}; +inline constexpr Vec4U8 GRAY_800 = Vec4U8{0x42, 0x42, 0x42, 0xFF}; +inline constexpr Vec4U8 GRAY_900 = Vec4U8{0x21, 0x21, 0x21, 0xFF}; + +inline constexpr Vec4U8 BLUE_GRAY_50 = Vec4U8{0xEC, 0xEF, 0xF1, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_100 = Vec4U8{0xCF, 0xD8, 0xDC, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_200 = Vec4U8{0xB0, 0xBE, 0xC5, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_300 = Vec4U8{0x90, 0xA4, 0xAE, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_400 = Vec4U8{0x78, 0x90, 0x9C, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_500 = Vec4U8{0x60, 0x7D, 0x8B, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_600 = Vec4U8{0x54, 0x6E, 0x7A, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_700 = Vec4U8{0x45, 0x5A, 0x64, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_800 = Vec4U8{0x37, 0x47, 0x4F, 0xFF}; +inline constexpr Vec4U8 BLUE_GRAY_900 = Vec4U8{0x26, 0x32, 0x38, 0xFF}; + +inline constexpr Vec4U8 WHITE = Vec4U8{0xFF, 0xFF, 0xFF, 0xFF}; +inline constexpr Vec4U8 BLACK = Vec4U8{0x00, 0x00, 0x00, 0xFF}; } // namespace mdc diff --git a/ashura/engine/engine.cc b/ashura/engine/engine.cc index 4f2f11690..b4265bcce 100644 --- a/ashura/engine/engine.cc +++ b/ashura/engine/engine.cc @@ -265,7 +265,7 @@ void Engine::init(AllocatorImpl allocator, void * app, data_u32.resize_uninit(data.size() >> 2).unwrap(); - mem::copy(data.span(), data_u32.span().as_u8()); + mem::copy(data.view(), data_u32.view().as_u8()); logger->trace("Loaded shader ", shader_id, " from file"); @@ -442,7 +442,7 @@ void Engine::recreate_swapchain_() for (gpu::ColorSpace cp : preferred_color_spaces) { - Span sel = find_if(formats.span(), [&](gpu::SurfaceFormat a) { + Span sel = find_if(formats.view(), [&](gpu::SurfaceFormat a) { return a.color_space == cp; }); if (!sel.is_empty()) @@ -460,7 +460,7 @@ void Engine::recreate_swapchain_() for (gpu::PresentMode pm : preferred_present_modes) { - if (!find(present_modes.span(), pm).is_empty()) + if (!find(present_modes.view(), pm).is_empty()) { found_present_mode = true; present_mode = pm; diff --git a/ashura/engine/font.h b/ashura/engine/font.h index a663c8d1c..993c9a684 100644 --- a/ashura/engine/font.h +++ b/ashura/engine/font.h @@ -11,7 +11,7 @@ namespace ash { // App Unit (AU) -constexpr i32 AU_UNIT = 128 * 64; +inline constexpr i32 AU_UNIT = 128 * 64; static_assert((AU_UNIT % 64) == 0, "App Unit needs to be in 26.6 Fractional Unit"); diff --git a/ashura/engine/font_impl.cc b/ashura/engine/font_impl.cc index a1fbc8aa0..dab737ba1 100644 --- a/ashura/engine/font_impl.cc +++ b/ashura/engine/font_impl.cc @@ -107,8 +107,7 @@ Result, FontErr> Font::decode(Span encoded, u32 face, if (ft_postscript_name != nullptr) { postscript_name_size = strlen(ft_postscript_name); - if (!postscript_name.extend( - Span{ft_postscript_name, postscript_name_size})) + if (!postscript_name.extend(Span{ft_postscript_name, postscript_name_size})) { return Err{FontErr::OutOfMemory}; } diff --git a/ashura/engine/font_impl.h b/ashura/engine/font_impl.h index 21787f4d3..6efc103ef 100644 --- a/ashura/engine/font_impl.h +++ b/ashura/engine/font_impl.h @@ -130,7 +130,7 @@ struct FontImpl : Font virtual Result<> rasterize(u32 font_height, AllocatorImpl allocator) override { - constexpr u32 MIN_ATLAS_EXTENT = 512; + static constexpr u32 MIN_ATLAS_EXTENT = 512; static_assert(MIN_ATLAS_EXTENT > 0, "Font atlas extent must be non-zero"); static_assert(MIN_ATLAS_EXTENT > 128, "Font atlas extent must be at least 128px"); @@ -147,7 +147,7 @@ struct FontImpl : Font CpuFontAtlas atlas; - if (!atlas.glyphs.resize_defaulted(glyphs.size32())) + if (!atlas.glyphs.resize(glyphs.size32())) { return Err{}; } @@ -234,14 +234,14 @@ struct FontImpl : Font rect_pack::pack_rects(pack_context, rects.data() + num_packed, num_rasterized_glyphs - num_packed); auto [just_packed, unpacked] = - partition(rects.span().slice(num_packed), + partition(rects.view().slice(num_packed), [](rect_pack::rect const & r) { return r.was_packed; }); - for (u32 i = num_packed; i < (num_packed + just_packed.span); i++) + CHECK(!just_packed.is_empty()); + for (auto & rect : rects.view().slice(num_packed, just_packed.size32())) { - rects[i].layer = num_layers; + rect.layer = num_layers; } - CHECK(just_packed.span != 0); - num_packed += (u32) just_packed.span; + num_packed += just_packed.size32(); num_layers++; } @@ -264,7 +264,7 @@ struct FontImpl : Font u64 const atlas_layer_size = atlas_area; u64 const atlas_size = atlas_layer_size * num_layers; - if (!atlas.channels.resize_defaulted(atlas_size)) + if (!atlas.channels.resize(atlas_size)) { return Err{}; } @@ -349,7 +349,7 @@ struct FontImpl : Font Vec views; - views.resize_defaulted(atlas.num_layers).unwrap(); + views.resize(atlas.num_layers).unwrap(); for (u32 i = 0; i < atlas.num_layers; i++) { @@ -427,7 +427,7 @@ struct FontImpl : Font Vec textures; Vec glyphs; - textures.resize_defaulted(atlas.num_layers).unwrap(); + textures.resize(atlas.num_layers).unwrap(); glyphs.extend(atlas.glyphs).unwrap(); for (u32 i = 0; i < atlas.num_layers; i++) diff --git a/ashura/engine/gpu_context.cc b/ashura/engine/gpu_context.cc index 36598b0bf..34df7f5c3 100644 --- a/ashura/engine/gpu_context.cc +++ b/ashura/engine/gpu_context.cc @@ -625,7 +625,7 @@ static void uninit_objects(gpu::Device * d, Span objects) d->uninit_descriptor_set_layout(obj.descriptor_set_layout); break; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } } } diff --git a/ashura/engine/gpu_context.h b/ashura/engine/gpu_context.h index c350508b1..f8426dcd1 100644 --- a/ashura/engine/gpu_context.h +++ b/ashura/engine/gpu_context.h @@ -11,19 +11,19 @@ namespace ash { -constexpr u32 TEXTURE_WHITE = 0; -constexpr u32 TEXTURE_BLACK = 1; -constexpr u32 TEXTURE_TRANSPARENT = 2; -constexpr u32 TEXTURE_RED = 3; -constexpr u32 TEXTURE_GREEN = 4; -constexpr u32 TEXTURE_BLUE = 5; -constexpr u32 NUM_DEFAULT_TEXTURES = TEXTURE_BLUE + 1; - -constexpr u32 SAMPLER_LINEAR = 0; -constexpr u32 SAMPLER_NEAREST = 1; -constexpr u32 SAMPLER_LINEAR_CLAMPED = 2; -constexpr u32 SAMPLER_NEAREST_CLAMPED = 3; -constexpr u32 NUM_DEFAULT_SAMPLERS = SAMPLER_NEAREST_CLAMPED + 1; +inline constexpr u32 TEXTURE_WHITE = 0; +inline constexpr u32 TEXTURE_BLACK = 1; +inline constexpr u32 TEXTURE_TRANSPARENT = 2; +inline constexpr u32 TEXTURE_RED = 3; +inline constexpr u32 TEXTURE_GREEN = 4; +inline constexpr u32 TEXTURE_BLUE = 5; +inline constexpr u32 NUM_DEFAULT_TEXTURES = TEXTURE_BLUE + 1; + +inline constexpr u32 SAMPLER_LINEAR = 0; +inline constexpr u32 SAMPLER_NEAREST = 1; +inline constexpr u32 SAMPLER_LINEAR_CLAMPED = 2; +inline constexpr u32 SAMPLER_NEAREST_CLAMPED = 3; +inline constexpr u32 NUM_DEFAULT_SAMPLERS = SAMPLER_NEAREST_CLAMPED + 1; struct FramebufferAttachment { diff --git a/ashura/engine/image_decoder.cc b/ashura/engine/image_decoder.cc index 730754282..e9e1bf833 100644 --- a/ashura/engine/image_decoder.cc +++ b/ashura/engine/image_decoder.cc @@ -8,7 +8,6 @@ extern "C" #include "jpeglib.h" #include "png.h" #include "webp/decode.h" -#include "webp/types.h" } namespace ash @@ -202,13 +201,12 @@ ImageDecodeError decode_jpg(Span bytes, DecodedImage & image) ImageDecodeError decode_image(Span bytes, DecodedImage & image) { - constexpr u8 JPG_MAGIC[] = {0xFF, 0xD8, 0xFF}; - - constexpr u8 PNG_MAGIC[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; - + static constexpr u8 JPG_MAGIC[] = {0xFF, 0xD8, 0xFF}; + static constexpr u8 PNG_MAGIC[] = {0x89, 0x50, 0x4E, 0x47, + 0x0D, 0x0A, 0x1A, 0x0A}; // RIFF-[file size: 4 bytes]-WEBP - constexpr u8 WEBP_MAGIC1[] = {'R', 'I', 'F', 'F'}; - constexpr u8 WEBP_MAGIC2[] = {'W', 'E', 'B', 'P'}; + static constexpr u8 WEBP_MAGIC1[] = {'R', 'I', 'F', 'F'}; + static constexpr u8 WEBP_MAGIC2[] = {'W', 'E', 'B', 'P'}; if (range_eq(bytes.slice(0, size(JPG_MAGIC)), JPG_MAGIC)) { diff --git a/ashura/engine/input.h b/ashura/engine/input.h index 7a9618148..f27872782 100644 --- a/ashura/engine/input.h +++ b/ashura/engine/input.h @@ -546,7 +546,7 @@ enum class KeyCode : u16 EndCall = 290 }; -constexpr u16 NUM_KEYS = 512; +inline constexpr u16 NUM_KEYS = 512; enum class MouseButtons : u8 { @@ -743,44 +743,44 @@ enum class Cursor }; /// @brief default charset is ASCII -constexpr char const MIME_TEXT_PLAIN[] = "text/plain"; -constexpr char const MIME_TEXT_UTF8[] = "text/plain;charset=UTF-8"; -constexpr char const MIME_TEXT_CSS[] = "text/css"; -constexpr char const MIME_TEXT_CSV[] = "text/csv"; -constexpr char const MIME_TEXT_HTML[] = "text/html"; -constexpr char const MIME_TEXT_JS[] = "text/javascript"; -constexpr char const MIME_TEXT_MARKDOWN[] = "text/markdown"; - -constexpr char const MIME_IMAGE_AVIF[] = "image/avif"; -constexpr char const MIME_IMAGE_BMP[] = "image/bmp"; -constexpr char const MIME_IMAGE_HEIF[] = "image/heif"; -constexpr char const MIME_IMAGE_JPEG[] = "image/jpeg"; -constexpr char const MIME_IMAGE_PNG[] = "image/png"; -constexpr char const MIME_IMAGE_SVG[] = "image/svg+xml"; -constexpr char const MIME_IMAGE_WEBP[] = "image/webp"; - -constexpr char const MIME_VIDEO_AV1[] = "video/AV1"; -constexpr char const MIME_VIDEO_H264[] = "video/H264"; -constexpr char const MIME_VIDEO_H265[] = "video/H265"; -constexpr char const MIME_VIDEO_H266[] = "video/H266"; -constexpr char const MIME_VIDEO_MATROSKA[] = "video/matroska"; -constexpr char const MIME_VIDEO_MP4[] = "video/mp4"; -constexpr char const MIME_VIDEO_RAW[] = "video/raw"; -constexpr char const MIME_VIDEO_VP8[] = "video/VP8"; -constexpr char const MIME_VIDEO_VP9[] = "video/VP9"; - -constexpr char const MIME_MODEL_GLTF_BINARY[] = "model/gltf+binary"; -constexpr char const MIME_MODEL_GLTF_JSON[] = "model/gltf+json"; -constexpr char const MIME_MODEL_MESH[] = "model/mesh"; -constexpr char const MIME_MODEL_MTL[] = "model/mtl"; -constexpr char const MIME_MODEL_OBJ[] = "model/obj"; -constexpr char const MIME_MODEL_STL[] = "model/stl"; - -constexpr char const MIME_FONT_OTF[] = "font/otf"; -constexpr char const MIME_FONT_SFNT[] = "font/sfnt"; -constexpr char const MIME_FONT_TTF[] = "font/ttf"; -constexpr char const MIME_FONT_WOFF[] = "font/woff"; -constexpr char const MIME_FONT_WOFF2[] = "font/woff2"; +inline constexpr char const MIME_TEXT_PLAIN[] = "text/plain"; +inline constexpr char const MIME_TEXT_UTF8[] = "text/plain;charset=UTF-8"; +inline constexpr char const MIME_TEXT_CSS[] = "text/css"; +inline constexpr char const MIME_TEXT_CSV[] = "text/csv"; +inline constexpr char const MIME_TEXT_HTML[] = "text/html"; +inline constexpr char const MIME_TEXT_JS[] = "text/javascript"; +inline constexpr char const MIME_TEXT_MARKDOWN[] = "text/markdown"; + +inline constexpr char const MIME_IMAGE_AVIF[] = "image/avif"; +inline constexpr char const MIME_IMAGE_BMP[] = "image/bmp"; +inline constexpr char const MIME_IMAGE_HEIF[] = "image/heif"; +inline constexpr char const MIME_IMAGE_JPEG[] = "image/jpeg"; +inline constexpr char const MIME_IMAGE_PNG[] = "image/png"; +inline constexpr char const MIME_IMAGE_SVG[] = "image/svg+xml"; +inline constexpr char const MIME_IMAGE_WEBP[] = "image/webp"; + +inline constexpr char const MIME_VIDEO_AV1[] = "video/AV1"; +inline constexpr char const MIME_VIDEO_H264[] = "video/H264"; +inline constexpr char const MIME_VIDEO_H265[] = "video/H265"; +inline constexpr char const MIME_VIDEO_H266[] = "video/H266"; +inline constexpr char const MIME_VIDEO_MATROSKA[] = "video/matroska"; +inline constexpr char const MIME_VIDEO_MP4[] = "video/mp4"; +inline constexpr char const MIME_VIDEO_RAW[] = "video/raw"; +inline constexpr char const MIME_VIDEO_VP8[] = "video/VP8"; +inline constexpr char const MIME_VIDEO_VP9[] = "video/VP9"; + +inline constexpr char const MIME_MODEL_GLTF_BINARY[] = "model/gltf+binary"; +inline constexpr char const MIME_MODEL_GLTF_JSON[] = "model/gltf+json"; +inline constexpr char const MIME_MODEL_MESH[] = "model/mesh"; +inline constexpr char const MIME_MODEL_MTL[] = "model/mtl"; +inline constexpr char const MIME_MODEL_OBJ[] = "model/obj"; +inline constexpr char const MIME_MODEL_STL[] = "model/stl"; + +inline constexpr char const MIME_FONT_OTF[] = "font/otf"; +inline constexpr char const MIME_FONT_SFNT[] = "font/sfnt"; +inline constexpr char const MIME_FONT_TTF[] = "font/ttf"; +inline constexpr char const MIME_FONT_WOFF[] = "font/woff"; +inline constexpr char const MIME_FONT_WOFF2[] = "font/woff2"; struct ClipBoard { diff --git a/ashura/engine/renderer.h b/ashura/engine/renderer.h index 1fbe8769c..4d2529d14 100644 --- a/ashura/engine/renderer.h +++ b/ashura/engine/renderer.h @@ -3,7 +3,6 @@ #include "ashura/engine/gpu_context.h" #include "ashura/engine/passes.h" #include "ashura/std/dyn.h" -#include "ashura/std/math.h" namespace ash { @@ -158,7 +157,7 @@ struct Renderer p->acquire(ctx, passes, assets); } - resources.resize_defaulted(ctx.buffering).unwrap(); + resources.resize(ctx.buffering).unwrap(); } void release(GpuContext & ctx, AssetMap & assets) diff --git a/ashura/engine/shader.cc b/ashura/engine/shader.cc index 9bcf66a45..5b10cfc23 100644 --- a/ashura/engine/shader.cc +++ b/ashura/engine/shader.cc @@ -321,7 +321,7 @@ ShaderCompileError language = EShLanguage::EShLangVertex; break; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } char const * buff_p = (char *) buff.data(); diff --git a/ashura/engine/shader.h b/ashura/engine/shader.h index 96d3438f0..c085e111c 100644 --- a/ashura/engine/shader.h +++ b/ashura/engine/shader.h @@ -1,9 +1,9 @@ /// SPDX-License-Identifier: MIT #pragma once -#include "ashura/std/vec.h" #include "ashura/std/log.h" #include "ashura/std/types.h" +#include "ashura/std/vec.h" namespace ash { diff --git a/ashura/engine/text.cc b/ashura/engine/text.cc index 09a3646d3..c9bd24dd9 100644 --- a/ashura/engine/text.cc +++ b/ashura/engine/text.cc @@ -297,7 +297,7 @@ void layout_text(TextBlock const & block, f32 max_width, TextLayout & layout) CHECK(block.fonts.size() <= U32_MAX); CHECK(block.runs.size() == block.fonts.size()); - layout.segments.resize_defaulted(block.text.size()).unwrap(); + layout.segments.resize(block.text.size()).unwrap(); Span segments = layout.segments; fill(segments, TextSegment{}); diff --git a/ashura/engine/text_compositor.h b/ashura/engine/text_compositor.h index 447b78d2a..2fe7a7f73 100644 --- a/ashura/engine/text_compositor.h +++ b/ashura/engine/text_compositor.h @@ -182,12 +182,13 @@ struct TextCompositor Inner(u32 num_buffer_codepoints, u32 num_records) { + // [ ] use make() CHECK(num_buffer_codepoints > 0); CHECK(num_records > 0); CHECK(is_pow2(num_buffer_codepoints)); CHECK(is_pow2(num_records)); buffer.resize_uninit(num_buffer_codepoints).unwrap(); - records.resize_defaulted(num_records).unwrap(); + records.resize(num_records).unwrap(); } void pop_records(u32 num); diff --git a/ashura/engine/view.h b/ashura/engine/view.h index bad90ff5d..de1dcf7c6 100644 --- a/ashura/engine/view.h +++ b/ashura/engine/view.h @@ -398,7 +398,7 @@ struct CoreViewTheme f32 focus_thickness = 0; }; -constexpr CoreViewTheme DEFAULT_THEME = { +inline constexpr CoreViewTheme DEFAULT_THEME = { .background = Vec4U8{0x19, 0x19, 0x19, 0xFF} .norm(), .surface = Vec4U8{0x33, 0x33, 0x33, 0xFF} diff --git a/ashura/engine/view_system.h b/ashura/engine/view_system.h index de0b52a24..21e2681f9 100644 --- a/ashura/engine/view_system.h +++ b/ashura/engine/view_system.h @@ -322,9 +322,9 @@ struct ViewSystem void focus_order() { - iota(focus_ordering.span(), 0U); + iota(focus_ordering.view(), 0U); - indirect_sort(focus_ordering.span(), [&](u32 a, u32 b) { + indirect_sort(focus_ordering.view(), [&](u32 a, u32 b) { return tab_indices[a] < tab_indices[b]; }); @@ -349,7 +349,7 @@ struct ViewSystem { ViewNode const & node = nodes[i]; views[i]->size(extents[i], - extents.span().slice(node.first_child, node.num_children)); + extents.view().slice(node.first_child, node.num_children)); } centers[0] = Vec2::splat(0); @@ -361,8 +361,8 @@ struct ViewSystem i--; ViewNode const & node = nodes[i]; ViewLayout layout = views[i]->fit( - extents[i], extents.span().slice(node.first_child, node.num_children), - centers.span().slice(node.first_child, node.num_children)); + extents[i], extents.view().slice(node.first_child, node.num_children), + centers.view().slice(node.first_child, node.num_children)); extents[i] = layout.extent; viewport_extents[i] = layout.viewport_extent; viewport_transforms[i] = layout.viewport_transform; @@ -418,7 +418,7 @@ struct ViewSystem } } - fill(clips.span(), CRect::from_offset({0, 0}, viewport_extent)); + fill(clips.view(), CRect::from_offset({0, 0}, viewport_extent)); /// recursive view clipping for (u32 i = 0; i < n; i++) @@ -471,7 +471,7 @@ struct ViewSystem ViewNode const & node = nodes[i]; z_indices[i] = views[i]->z_index( z_indices[i], - z_indices.span().slice(node.first_child, node.num_children)); + z_indices.view().slice(node.first_child, node.num_children)); } stacking_contexts[0] = 0; @@ -484,10 +484,10 @@ struct ViewSystem } } - iota(z_ordering.span(), 0U); + iota(z_ordering.view(), 0U); // sort layers with priority: stacking_context, z_index, node depth - indirect_sort(z_ordering.span(), [&](u32 a, u32 b) { + indirect_sort(z_ordering.view(), [&](u32 a, u32 b) { if (stacking_contexts[a] < stacking_contexts[b]) { return true; diff --git a/ashura/engine/views.cc b/ashura/engine/views.cc index 41cceaee7..0b259e4ab 100644 --- a/ashura/engine/views.cc +++ b/ashura/engine/views.cc @@ -16,8 +16,9 @@ void ScalarDragBox::scalar_parse(Span text, ScalarState & styling) { case ScalarInputType::i32: { - i32 value = 0; - auto [ptr, ec] = fast_float::from_chars(text.begin(), text.end(), value); + i32 value = 0; + auto [ptr, ec] = + fast_float::from_chars(text.pbegin(), text.pend(), value); if (ec != std::errc{} || value < styling.min.i32 || value > styling.max.i32) { @@ -29,8 +30,9 @@ void ScalarDragBox::scalar_parse(Span text, ScalarState & styling) case ScalarInputType::f32: { - f32 value = 0; - auto [ptr, ec] = fast_float::from_chars(text.begin(), text.end(), value); + f32 value = 0; + auto [ptr, ec] = + fast_float::from_chars(text.pbegin(), text.pend(), value); if (ec != std::errc{} || value < styling.min.f32 || value > styling.max.f32) { diff --git a/ashura/engine/window.cc b/ashura/engine/window.cc index 84f946e86..d02c740f3 100644 --- a/ashura/engine/window.cc +++ b/ashura/engine/window.cc @@ -458,7 +458,7 @@ struct WindowSystemImpl : WindowSystem case SDL_SystemTheme::SDL_SYSTEM_THEME_UNKNOWN: return SystemTheme::Unknown; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } } @@ -568,7 +568,7 @@ struct WindowSystemImpl : WindowSystem mouse_event.button = MouseButtons::A2; break; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } switch (event.type) diff --git a/ashura/gpu/gpu.h b/ashura/gpu/gpu.h index cb909abdc..fb0c6a3c7 100644 --- a/ashura/gpu/gpu.h +++ b/ashura/gpu/gpu.h @@ -13,36 +13,36 @@ namespace ash namespace gpu { -constexpr u32 REMAINING_MIP_LEVELS = ~0U; -constexpr u32 REMAINING_ARRAY_LAYERS = ~0U; -constexpr u64 WHOLE_SIZE = ~0ULL; - -constexpr u32 MAX_IMAGE_EXTENT_1D = 8'192; -constexpr u32 MAX_IMAGE_EXTENT_2D = 8'192; -constexpr u32 MAX_IMAGE_EXTENT_3D = 2'048; -constexpr u32 MAX_IMAGE_EXTENT_CUBE = 8'192; -constexpr u32 MAX_IMAGE_ARRAY_LAYERS = 1'024; -constexpr u32 MAX_VIEWPORT_EXTENT = 8'192; -constexpr u32 MAX_FRAMEBUFFER_EXTENT = 8'192; -constexpr u32 MAX_FRAMEBUFFER_LAYERS = 1'024; -constexpr u32 MAX_VERTEX_ATTRIBUTES = 16; -constexpr u32 MAX_PUSH_CONSTANTS_SIZE = 128; -constexpr u32 MAX_UPDATE_BUFFER_SIZE = 65'536; -constexpr u32 MAX_PIPELINE_DESCRIPTOR_SETS = 8; -constexpr u32 MAX_PIPELINE_DYNAMIC_UNIFORM_BUFFERS = 8; -constexpr u32 MAX_PIPELINE_DYNAMIC_STORAGE_BUFFERS = 8; -constexpr u32 MAX_PIPELINE_INPUT_ATTACHMENTS = 8; -constexpr u32 MAX_PIPELINE_COLOR_ATTACHMENTS = 8; -constexpr u32 MAX_DESCRIPTOR_SET_DESCRIPTORS = 4'096; -constexpr u32 MAX_BINDING_DESCRIPTORS = 4'096; -constexpr u32 MAX_DESCRIPTOR_SET_BINDINGS = 16; -constexpr u32 MAX_FRAME_BUFFERING = 4; -constexpr u32 MAX_SWAPCHAIN_IMAGES = 4; -constexpr u64 MAX_UNIFORM_BUFFER_RANGE = 65'536; -constexpr f32 MAX_SAMPLER_ANISOTROPY = 16; -constexpr u32 MAX_CLIP_DISTANCES = 8; -constexpr u32 MAX_CULL_DISTANCES = 8; -constexpr u32 MAX_COMBINED_CLIP_AND_CULL_DISTANCES = 8; +inline constexpr u32 REMAINING_MIP_LEVELS = ~0U; +inline constexpr u32 REMAINING_ARRAY_LAYERS = ~0U; +inline constexpr u64 WHOLE_SIZE = ~0ULL; + +inline constexpr u32 MAX_IMAGE_EXTENT_1D = 8'192; +inline constexpr u32 MAX_IMAGE_EXTENT_2D = 8'192; +inline constexpr u32 MAX_IMAGE_EXTENT_3D = 2'048; +inline constexpr u32 MAX_IMAGE_EXTENT_CUBE = 8'192; +inline constexpr u32 MAX_IMAGE_ARRAY_LAYERS = 1'024; +inline constexpr u32 MAX_VIEWPORT_EXTENT = 8'192; +inline constexpr u32 MAX_FRAMEBUFFER_EXTENT = 8'192; +inline constexpr u32 MAX_FRAMEBUFFER_LAYERS = 1'024; +inline constexpr u32 MAX_VERTEX_ATTRIBUTES = 16; +inline constexpr u32 MAX_PUSH_CONSTANTS_SIZE = 128; +inline constexpr u32 MAX_UPDATE_BUFFER_SIZE = 65'536; +inline constexpr u32 MAX_PIPELINE_DESCRIPTOR_SETS = 8; +inline constexpr u32 MAX_PIPELINE_DYNAMIC_UNIFORM_BUFFERS = 8; +inline constexpr u32 MAX_PIPELINE_DYNAMIC_STORAGE_BUFFERS = 8; +inline constexpr u32 MAX_PIPELINE_INPUT_ATTACHMENTS = 8; +inline constexpr u32 MAX_PIPELINE_COLOR_ATTACHMENTS = 8; +inline constexpr u32 MAX_DESCRIPTOR_SET_DESCRIPTORS = 4'096; +inline constexpr u32 MAX_BINDING_DESCRIPTORS = 4'096; +inline constexpr u32 MAX_DESCRIPTOR_SET_BINDINGS = 16; +inline constexpr u32 MAX_FRAME_BUFFERING = 4; +inline constexpr u32 MAX_SWAPCHAIN_IMAGES = 4; +inline constexpr u64 MAX_UNIFORM_BUFFER_RANGE = 65'536; +inline constexpr f32 MAX_SAMPLER_ANISOTROPY = 16; +inline constexpr u32 MAX_CLIP_DISTANCES = 8; +inline constexpr u32 MAX_CULL_DISTANCES = 8; +inline constexpr u32 MAX_COMBINED_CLIP_AND_CULL_DISTANCES = 8; typedef Vec2U Offset; typedef Vec2U Extent; diff --git a/ashura/gpu/image.h b/ashura/gpu/image.h index a5b20396c..4c83f77f6 100644 --- a/ashura/gpu/image.h +++ b/ashura/gpu/image.h @@ -44,7 +44,7 @@ inline u8 pixel_pitch(Format fmt) case Format::R32G32B32A32_SFLOAT: return 16; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } } diff --git a/ashura/gpu/vulkan.cc b/ashura/gpu/vulkan.cc index ab255997d..f4d330584 100644 --- a/ashura/gpu/vulkan.cc +++ b/ashura/gpu/vulkan.cc @@ -744,7 +744,7 @@ inline u64 index_type_size(gpu::IndexType type) case gpu::IndexType::Uint32: return 4; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } } @@ -3793,7 +3793,7 @@ void Device::update_descriptor_set(gpu::DescriptorSetUpdate const & update) break; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } switch (binding.type) @@ -3947,7 +3947,7 @@ void Device::update_descriptor_set(gpu::DescriptorSetUpdate const & update) break; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } VkWriteDescriptorSet vk_write{.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, @@ -4002,7 +4002,7 @@ void Device::update_descriptor_set(gpu::DescriptorSetUpdate const & update) break; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } } @@ -5737,7 +5737,7 @@ void CommandEncoder::access_compute_bindings(DescriptorSet const & set) break; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } } } @@ -5814,7 +5814,7 @@ void CommandEncoder::access_graphics_bindings(DescriptorSet const & set) case gpu::DescriptorType::Sampler: break; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } } } diff --git a/ashura/gpu/vulkan.h b/ashura/gpu/vulkan.h index 1c39479b9..9426d5541 100644 --- a/ashura/gpu/vulkan.h +++ b/ashura/gpu/vulkan.h @@ -19,14 +19,14 @@ namespace vk using gpu::Status; -constexpr char const * ENGINE_NAME = "Ash"; -constexpr u32 ENGINE_VERSION = VK_MAKE_API_VERSION(0, 0, 0, 1); -constexpr char const * CLIENT_NAME = "Ash Client"; -constexpr u32 CLIENT_VERSION = VK_MAKE_API_VERSION(0, 0, 0, 1); +inline constexpr char const * ENGINE_NAME = "Ash"; +inline constexpr u32 ENGINE_VERSION = VK_MAKE_API_VERSION(0, 0, 0, 1); +inline constexpr char const * CLIENT_NAME = "Ash Client"; +inline constexpr u32 CLIENT_VERSION = VK_MAKE_API_VERSION(0, 0, 0, 1); -constexpr u32 MAX_MEMORY_HEAP_PROPERTIES = 32; -constexpr u32 MAX_MEMORY_HEAPS = 16; -constexpr u8 NUM_DESCRIPTOR_TYPES = 11; +inline constexpr u32 MAX_MEMORY_HEAP_PROPERTIES = 32; +inline constexpr u32 MAX_MEMORY_HEAPS = 16; +inline constexpr u8 NUM_DESCRIPTOR_TYPES = 11; typedef VkSampler Sampler; typedef VkShaderModule Shader; @@ -268,9 +268,9 @@ struct BufferView VkBufferView vk_view = nullptr; }; -constexpr u32 COLOR_ASPECT_IDX = 0; -constexpr u32 DEPTH_ASPECT_IDX = 0; -constexpr u32 STENCIL_ASPECT_IDX = 1; +inline constexpr u32 COLOR_ASPECT_IDX = 0; +inline constexpr u32 DEPTH_ASPECT_IDX = 0; +inline constexpr u32 STENCIL_ASPECT_IDX = 1; struct Image { diff --git a/ashura/std/allocators.h b/ashura/std/allocators.h index 88afbc6da..678ab3c09 100644 --- a/ashura/std/allocators.h +++ b/ashura/std/allocators.h @@ -142,7 +142,7 @@ struct Arena final : Allocator [[nodiscard]] inline Arena to_arena(Span buffer) { - return Arena{buffer.data(), buffer.end(), buffer.begin()}; + return Arena{buffer.pbegin(), buffer.pend(), buffer.pbegin()}; } /// @max_num_arenas: maximum number of arenas that can be allocated diff --git a/ashura/std/async.cc b/ashura/std/async.cc index 5de4bcae0..4696727d2 100644 --- a/ashura/std/async.cc +++ b/ashura/std/async.cc @@ -7,7 +7,6 @@ #include "ashura/std/error.h" #include "ashura/std/list.h" #include "ashura/std/log.h" -#include "ashura/std/rc.h" #include "ashura/std/time.h" #include "ashura/std/types.h" #include "ashura/std/vec.h" @@ -17,28 +16,30 @@ namespace ash { -constexpr usize TASK_ARENA_SIZE = PAGE_SIZE; +inline constexpr usize TASK_ARENA_SIZE = PAGE_SIZE; -/// memory is returned back to the scheduler once ac reaches 0. +/// @brief memory is returned back to the scheduler once ac reaches 0. /// /// arenas are individually allocated from heap and span a page boundary. /// -struct TaskArena +struct TaskArena : Pin<> { - AliasCount ac{}; - Arena arena{}; + TaskArena * next = nullptr; + TaskArena * prev = nullptr; + AliasCount ac{}; + Arena arena{}; - static constexpr auto node_flex() + static constexpr auto flex() { - return Flex{ - {layout>, + return Flex{ + {layout, Layout{.alignment = MAX_STANDARD_ALIGNMENT, .size = TASK_ARENA_SIZE}} }; } }; -/// once task is executed, the arena holding the memory associated with the task -/// is returned back to the source. +/// @brief once the task is executed, the arena holding the memory associated +/// with the task is returned back to the source. /// /// the arena holds the memory for this Task struct, and the memory for its /// related data. this has the advantage that accessing the struct is @@ -59,6 +60,10 @@ struct Task typedef bool (*Run)(void *); + Task * next = nullptr; + + Task * prev = nullptr; + Layout frame_layout{}; Poll poll = [](void *) { return true; }; @@ -68,12 +73,12 @@ struct Task Uninit uninit = noop; /// @brief arena this task was allocated from. always non-null. - ListNode * arena = nullptr; + TaskArena * arena = nullptr; - static constexpr auto node_flex(Layout frame_layout) + static constexpr auto flex(Layout frame_layout) { - return Flex{ - {layout>, frame_layout} + return Flex{ + {layout, frame_layout} }; } }; @@ -88,19 +93,19 @@ static_assert(TASK_ARENA_SIZE >= (MAX_TASK_FRAME_SIZE << 2), "Task arena size is too small"); static_assert(MAX_TASK_FRAME_SIZE >= MAX_STANDARD_ALIGNMENT, - "Task frame size is too small"); + "Maximum task frame size is too small"); // assuming it has maximum alignment as well, although this would typically be // maximum of MAX_STANDARD_ALIGNMENT -constexpr Layout MAX_TASK_FRAME_LAYOUT{.alignment = MAX_TASK_FRAME_SIZE, - .size = MAX_TASK_FRAME_SIZE}; +inline constexpr Layout MAX_TASK_FRAME_LAYOUT{.alignment = MAX_TASK_FRAME_SIZE, + .size = MAX_TASK_FRAME_SIZE}; -constexpr Layout MAX_TASK_NODE_FLEX_LAYOUT = - Task::node_flex(MAX_TASK_FRAME_LAYOUT).layout(); +inline constexpr Layout MAX_TASK_FLEX_LAYOUT = + Task::flex(MAX_TASK_FRAME_LAYOUT).layout(); -static_assert(TASK_ARENA_SIZE >= MAX_TASK_NODE_FLEX_LAYOUT.size, +static_assert(TASK_ARENA_SIZE >= MAX_TASK_FLEX_LAYOUT.size, "Task arena size is too small to fit the maximum task frame and " - "task metadata"); + "task context"); struct TaskAllocator { @@ -116,11 +121,11 @@ struct TaskAllocator SpinLock lock{}; List list{}; - ListNode * pop() + TaskArena * pop() { - LockGuard guard{lock}; + LockGuard guard{lock}; // return the most recently used arena - ListNode * arena = list.pop_back(); + TaskArena * arena = list.pop_back(); return arena; } @@ -131,8 +136,8 @@ struct TaskAllocator /// allocate a new arena and make it the current arena. struct alignas(CACHELINE_ALIGNMENT) { - SpinLock lock{}; - ListNode * node = nullptr; + SpinLock lock{}; + TaskArena * node = nullptr; } current_arena{}; @@ -161,106 +166,96 @@ struct TaskAllocator } } - void release_arena(ListNode * arena) + void release_arena(TaskArena * arena) { // decrease alias count of arena, if only alias left, add to the arena // free list. - if (arena->v.ac.unalias()) + if (arena->ac.unalias()) { - arena->v.arena.reclaim(); + arena->arena.reclaim(); LockGuard guard{free_list.lock}; free_list.list.push_back(arena); } } - bool alloc_arena(ListNode *& arena) + bool alloc_arena(TaskArena *& out) { - Flex const flex = TaskArena::node_flex(); + auto const flex = TaskArena::flex(); Layout const layout = flex.layout(); - u8 * head; + u8 * stack; - if (!source.alloc(layout.alignment, layout.size, head)) + if (!source.alloc(layout.alignment, layout.size, stack)) { return false; } - u8 * memory; - flex.unpack(head, arena, memory); + auto [arena, memory] = flex.unpack(stack); - new (arena) ListNode{ - .v{.arena = to_arena(Span{memory, TASK_ARENA_SIZE})}}; + out = new (arena.data()) TaskArena{.arena = to_arena(memory)}; return true; } - void dealloc_arena(ListNode * arena) + void dealloc_arena(TaskArena * arena) { - Flex const flex = TaskArena::node_flex(); - Layout const layout = flex.layout(); + Layout const layout = TaskArena::flex().layout(); source.dealloc(layout.alignment, (u8 *) arena, layout.size); } - bool request_arena(ListNode *& arena) + bool request_arena(TaskArena *& out) { /// get from free list, otherwise allocate a new arena - ListNode * a = free_list.pop(); + TaskArena * a = free_list.pop(); if (a != nullptr) { - arena = a; + out = a; return true; } - return alloc_arena(arena); + return alloc_arena(out); } - static bool alloc_task(ListNode & arena, TaskInfo const & info, - ListNode *& task) + static bool alloc_task(TaskArena & arena, TaskInfo const & info, Task *& out) { - Flex const flex = Task::node_flex(info.frame_layout); + auto const flex = Task::flex(info.frame_layout); Layout const layout = flex.layout(); - u8 * head; + u8 * stack; - if (!arena.v.arena.alloc(layout.alignment, layout.size, head)) + if (!arena.arena.alloc(layout.alignment, layout.size, stack)) { return false; } - arena.v.ac.alias(); + arena.ac.alias(); - u8 * ctx; + auto [task, ctx] = flex.unpack(stack); - flex.unpack(head, task, ctx); - - new (task) ListNode{ - .v{.frame_layout = info.frame_layout, - .poll = info.poll, - .run = info.run, - .uninit = info.uninit, - .arena = &arena} - }; + out = new (task.data()) Task{.frame_layout = info.frame_layout, + .poll = info.poll, + .run = info.run, + .uninit = info.uninit, + .arena = &arena}; - info.init(ctx); + info.init(ctx.data()); return true; } - static void uninit_task(ListNode * task) + static void uninit_task(Task * task) { - Flex const flex = Task::node_flex(task->v.frame_layout); - u8 * ctx; - flex.unpack(task, task, ctx); - task->v.uninit(ctx); + auto [_, ctx] = Task::flex(task->frame_layout).unpack(task); + task->uninit(ctx.data()); } - void release_task(ListNode * task) + void release_task(Task * task) { - ListNode * arena = task->v.arena; + TaskArena * arena = task->arena; uninit_task(task); release_arena(arena); } - bool create_task(TaskInfo const & info, ListNode *& task) + bool create_task(TaskInfo const & info, Task *& task) { LockGuard guard{current_arena.lock}; @@ -279,9 +274,9 @@ struct TaskAllocator // decrease alias count of current arena, if last alias, reclaim the memory // instead - if (current_arena.node->v.ac.unalias()) [[unlikely]] + if (current_arena.node->ac.unalias()) [[unlikely]] { - current_arena.node->v.arena.reclaim(); + current_arena.node->arena.reclaim(); } else { @@ -323,16 +318,16 @@ struct TaskQueue return tasks.is_empty(); } - ListNode * pop_task() + Task * pop_task() { - LockGuard guard{lock}; - ListNode * t = tasks.pop_front(); + LockGuard guard{lock}; + Task * t = tasks.pop_front(); return t; } /// @brief push task on the queue /// @param t non-null task node - void push_task(ListNode * t) + void push_task(Task * t) { LockGuard guard{lock}; tasks.push_back(t); @@ -340,7 +335,7 @@ struct TaskQueue void push_task(TaskInfo const & info) { - ListNode * t; + Task * t; CHECK(allocator.create_task(info, t)); push_task(t); } @@ -425,7 +420,7 @@ struct ASH_DLL_EXPORT SchedulerImpl : Scheduler, Pin<> while (true) { - ListNode * task = main_queue.pop_task(); + Task * task = main_queue.pop_task(); if (task == nullptr) { @@ -451,7 +446,7 @@ struct ASH_DLL_EXPORT SchedulerImpl : Scheduler, Pin<> break; } - ListNode * task = q.pop_task(); + Task * task = q.pop_task(); if (task == nullptr) [[unlikely]] { @@ -460,13 +455,9 @@ struct ASH_DLL_EXPORT SchedulerImpl : Scheduler, Pin<> continue; } - Flex const flex = Task::node_flex(task->v.frame_layout); - - u8 * frame; - - flex.unpack(task, task, frame); + auto [_, frame] = Task::flex(task->frame_layout).unpack(task); - if (!task->v.poll(frame)) [[unlikely]] + if (!task->poll(frame.data())) [[unlikely]] { q.push_task(task); continue; @@ -475,7 +466,7 @@ struct ASH_DLL_EXPORT SchedulerImpl : Scheduler, Pin<> // finally gotten a ready task, reset poll counter poll = 0; - bool const repeat = task->v.run(frame); + bool const repeat = task->run(frame.data()); if (repeat) [[unlikely]] { @@ -491,7 +482,7 @@ struct ASH_DLL_EXPORT SchedulerImpl : Scheduler, Pin<> // run loop done. purge pending tasks while (true) { - ListNode * task = q.pop_task(); + Task * task = q.pop_task(); if (task == nullptr) { @@ -516,7 +507,7 @@ struct ASH_DLL_EXPORT SchedulerImpl : Scheduler, Pin<> break; } - ListNode * task = q.pop_task(); + Task * task = q.pop_task(); if (task == nullptr) [[unlikely]] { @@ -533,19 +524,15 @@ struct ASH_DLL_EXPORT SchedulerImpl : Scheduler, Pin<> } } - Flex const flex = Task::node_flex(task->v.frame_layout); - - u8 * frame; - - flex.unpack(task, task, frame); + auto [_, frame] = Task::flex(task->frame_layout).unpack(task); - if (!task->v.poll(frame)) [[unlikely]] + if (!task->poll(frame.data())) [[unlikely]] { q.push_task(task); continue; } - bool const repeat = task->v.run(frame); + bool const repeat = task->run(frame.data()); if (repeat) [[unlikely]] { @@ -616,10 +603,10 @@ void Scheduler::init(AllocatorImpl allocator, std::thread::id main_thread_id, u32 const num_worker_threads = worker_thread_sleep.size32(); impl->dedicated_threads = - pin_vec(num_dedicated_threads, allocator).unwrap(); + PinVec::make(num_dedicated_threads, allocator).unwrap(); impl->worker_threads = - pin_vec(num_worker_threads, allocator).unwrap(); + PinVec::make(num_worker_threads, allocator).unwrap(); for (u32 i = 0; i < num_dedicated_threads; i++) { diff --git a/ashura/std/async.h b/ashura/std/async.h index d34001681..c74977f30 100644 --- a/ashura/std/async.h +++ b/ashura/std/async.h @@ -6,11 +6,11 @@ #include "ashura/std/allocator.h" #include "ashura/std/cfg.h" #include "ashura/std/error.h" -#include "ashura/std/tuple.h" #include "ashura/std/mem.h" #include "ashura/std/rc.h" #include "ashura/std/result.h" #include "ashura/std/time.h" +#include "ashura/std/tuple.h" #include "ashura/std/types.h" #include @@ -767,7 +767,7 @@ template return await_semaphores(semaphores, stages, timeout); } -constexpr usize MAX_TASK_FRAME_SIZE = PAGE_SIZE >> 4; +inline constexpr usize MAX_TASK_FRAME_SIZE = PAGE_SIZE >> 4; template concept TaskFrame = requires (F f) { @@ -945,7 +945,7 @@ struct Scheduler schedule_main(info); return; default: - UNREACHABLE(); + CHECK_UNREACHABLE(); } } }; diff --git a/ashura/std/bench/hash_map.cc b/ashura/std/bench/hash_map.cc index 010a943a0..d9b6b68b9 100644 --- a/ashura/std/bench/hash_map.cc +++ b/ashura/std/bench/hash_map.cc @@ -1214,7 +1214,7 @@ struct std::less> { bool operator()(Span a, Span b) const { - return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); + return std::lexicographical_compare(a.pbegin(), a.pend(), b.pbegin(), b.pend()); } }; diff --git a/ashura/std/buffer.h b/ashura/std/buffer.h index 43ebd2992..cc3b2aba1 100644 --- a/ashura/std/buffer.h +++ b/ashura/std/buffer.h @@ -55,12 +55,6 @@ constexpr Buffer buffer(Span span) return Buffer{.data_ = span.data(), .capacity_ = span.size(), .size_ = 0}; } -template -constexpr Span span(Buffer buffer) -{ - return Span{buffer.data(), buffer.size()}; -} - /// @capacity: must be a non-zero power of 2 template struct [[nodiscard]] RingBuffer diff --git a/ashura/std/cfg.h b/ashura/std/cfg.h index d5291a122..147b6ecd0 100644 --- a/ashura/std/cfg.h +++ b/ashura/std/cfg.h @@ -271,3 +271,14 @@ #else # define ASH_TAILCALL #endif + +#if ASH_HAS_BUILTIN(unreachable) +# define ASH_UNREACHABLE __builtin_unreachable() +#else +# if ASH_CFG(COMPILER, MSVC) +# define ASH_UNREACHABLE __assume(0) +# else +# include +# define ASH_UNREACHABLE std::abort() +# endif +#endif diff --git a/ashura/std/enum.gen.h b/ashura/std/enum.gen.h index 4f8c6ec9d..120d08f75 100644 --- a/ashura/std/enum.gen.h +++ b/ashura/std/enum.gen.h @@ -5,18 +5,17 @@ #include "ashura/std/v.h" #include "ashura/std/error.h" #include "ashura/std/log.h" +#include "ashura/std/tuple.h" #include "ashura/std/types.h" namespace ash { -static constexpr usize MAX_ENUM_SIZE = 16; +inline constexpr usize MAX_ENUM_SIZE = 16; template -struct Enum -{ -static_assert("Enum size exceeds MAX_ENUM_SIZE"); -}; +requires(sizeof...(T) <= MAX_ENUM_SIZE) +struct Enum; namespace intr{ @@ -591,14 +590,172 @@ if(src == dst) enum_destruct(dst); enum_copy_construct(src, dst); } + + +template +constexpr decltype(auto) match(Enum && e, Fns && ... fns) +{ + Tuple fns_ref{ static_cast(fns)... }; + + +if constexpr(SIZE > 0) +{ + if(e.index_ == 0) + { + return fns_ref.v0(e.v0_); + } +} + + +if constexpr(SIZE > 1) +{ + if(e.index_ == 1) + { + return fns_ref.v1(e.v1_); + } +} + + +if constexpr(SIZE > 2) +{ + if(e.index_ == 2) + { + return fns_ref.v2(e.v2_); + } +} + + +if constexpr(SIZE > 3) +{ + if(e.index_ == 3) + { + return fns_ref.v3(e.v3_); + } +} + + +if constexpr(SIZE > 4) +{ + if(e.index_ == 4) + { + return fns_ref.v4(e.v4_); + } +} + + +if constexpr(SIZE > 5) +{ + if(e.index_ == 5) + { + return fns_ref.v5(e.v5_); + } +} + + +if constexpr(SIZE > 6) +{ + if(e.index_ == 6) + { + return fns_ref.v6(e.v6_); + } +} + + +if constexpr(SIZE > 7) +{ + if(e.index_ == 7) + { + return fns_ref.v7(e.v7_); + } +} + + +if constexpr(SIZE > 8) +{ + if(e.index_ == 8) + { + return fns_ref.v8(e.v8_); + } +} + + +if constexpr(SIZE > 9) +{ + if(e.index_ == 9) + { + return fns_ref.v9(e.v9_); + } +} + + +if constexpr(SIZE > 10) +{ + if(e.index_ == 10) + { + return fns_ref.v10(e.v10_); + } +} + + +if constexpr(SIZE > 11) +{ + if(e.index_ == 11) + { + return fns_ref.v11(e.v11_); + } +} + + +if constexpr(SIZE > 12) +{ + if(e.index_ == 12) + { + return fns_ref.v12(e.v12_); + } +} + + +if constexpr(SIZE > 13) +{ + if(e.index_ == 13) + { + return fns_ref.v13(e.v13_); + } +} + + +if constexpr(SIZE > 14) +{ + if(e.index_ == 14) + { + return fns_ref.v14(e.v14_); + } +} + + +if constexpr(SIZE > 15) +{ + if(e.index_ == 15) + { + return fns_ref.v15(e.v15_); + } } + + ASH_UNREACHABLE; +} + +} // namespace intr + + template<> struct Enum<> { + + static constexpr usize SIZE = 0; static constexpr usize size() @@ -607,6 +764,18 @@ static constexpr usize size() } +constexpr bool is(usize) const +{ + return false; +} + +constexpr void match() +{ +} + +constexpr void match() const +{ +} }; @@ -616,6 +785,10 @@ struct Enum typedef T0 E0; +template +using E = index_pack; + + static constexpr usize SIZE = 1; static constexpr usize size() @@ -675,10 +848,9 @@ v0_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -695,18 +867,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -716,6 +891,10 @@ struct Enum typedef T0 E0; typedef T1 E1; +template +using E = index_pack; + + static constexpr usize SIZE = 2; static constexpr usize size() @@ -782,10 +961,9 @@ v1_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -802,18 +980,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -824,6 +1005,10 @@ typedef T0 E0; typedef T1 E1; typedef T2 E2; +template +using E = index_pack; + + static constexpr usize SIZE = 3; static constexpr usize size() @@ -897,10 +1082,9 @@ v2_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -917,18 +1101,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -940,6 +1127,10 @@ typedef T1 E1; typedef T2 E2; typedef T3 E3; +template +using E = index_pack; + + static constexpr usize SIZE = 4; static constexpr usize size() @@ -1020,10 +1211,9 @@ v3_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -1040,18 +1230,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -1064,6 +1257,10 @@ typedef T2 E2; typedef T3 E3; typedef T4 E4; +template +using E = index_pack; + + static constexpr usize SIZE = 5; static constexpr usize size() @@ -1151,10 +1348,9 @@ v4_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -1171,18 +1367,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -1196,6 +1395,10 @@ typedef T3 E3; typedef T4 E4; typedef T5 E5; +template +using E = index_pack; + + static constexpr usize SIZE = 6; static constexpr usize size() @@ -1290,10 +1493,9 @@ v5_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -1310,18 +1512,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -1336,6 +1541,10 @@ typedef T4 E4; typedef T5 E5; typedef T6 E6; +template +using E = index_pack; + + static constexpr usize SIZE = 7; static constexpr usize size() @@ -1437,10 +1646,9 @@ v6_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -1457,18 +1665,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -1484,6 +1695,10 @@ typedef T5 E5; typedef T6 E6; typedef T7 E7; +template +using E = index_pack; + + static constexpr usize SIZE = 8; static constexpr usize size() @@ -1592,10 +1807,9 @@ v7_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -1612,18 +1826,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -1640,6 +1857,10 @@ typedef T6 E6; typedef T7 E7; typedef T8 E8; +template +using E = index_pack; + + static constexpr usize SIZE = 9; static constexpr usize size() @@ -1755,10 +1976,9 @@ v8_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -1775,18 +1995,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -1804,6 +2027,10 @@ typedef T7 E7; typedef T8 E8; typedef T9 E9; +template +using E = index_pack; + + static constexpr usize SIZE = 10; static constexpr usize size() @@ -1926,10 +2153,9 @@ v9_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -1946,18 +2172,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -1976,6 +2205,10 @@ typedef T8 E8; typedef T9 E9; typedef T10 E10; +template +using E = index_pack; + + static constexpr usize SIZE = 11; static constexpr usize size() @@ -2105,10 +2338,9 @@ v10_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -2125,18 +2357,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -2156,6 +2391,10 @@ typedef T9 E9; typedef T10 E10; typedef T11 E11; +template +using E = index_pack; + + static constexpr usize SIZE = 12; static constexpr usize size() @@ -2292,10 +2531,9 @@ v11_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -2312,18 +2550,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -2344,6 +2585,10 @@ typedef T10 E10; typedef T11 E11; typedef T12 E12; +template +using E = index_pack; + + static constexpr usize SIZE = 13; static constexpr usize size() @@ -2487,10 +2732,9 @@ v12_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -2507,18 +2751,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -2540,6 +2787,10 @@ typedef T11 E11; typedef T12 E12; typedef T13 E13; +template +using E = index_pack; + + static constexpr usize SIZE = 14; static constexpr usize size() @@ -2690,10 +2941,9 @@ v13_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -2710,18 +2960,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -2744,6 +2997,10 @@ typedef T12 E12; typedef T13 E13; typedef T14 E14; +template +using E = index_pack; + + static constexpr usize SIZE = 15; static constexpr usize size() @@ -2901,10 +3158,9 @@ v14_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -2921,18 +3177,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; template @@ -2956,6 +3215,10 @@ typedef T13 E13; typedef T14 E14; typedef T15 E15; +template +using E = index_pack; + + static constexpr usize SIZE = 16; static constexpr usize size() @@ -3120,10 +3383,9 @@ v15_{static_cast(v)} { } -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const { - return index_ == I; + return index_ == i; } template requires(I < SIZE) @@ -3140,18 +3402,21 @@ constexpr auto const& operator[](V) const return intr::enum_member(*this); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) { - + return intr::match(*this, static_cast(fns)... ); } -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const { - + return intr::match(*this, static_cast(fns)... ); } + }; } // namespace ash diff --git a/ashura/std/enum.py b/ashura/std/enum.py index 73715bd1b..760d543eb 100644 --- a/ashura/std/enum.py +++ b/ashura/std/enum.py @@ -17,18 +17,17 @@ def out(code): return file.write(code) #include "ashura/std/v.h" #include "ashura/std/error.h" #include "ashura/std/log.h" +#include "ashura/std/tuple.h" #include "ashura/std/types.h" namespace ash {{ -static constexpr usize MAX_ENUM_SIZE = {MAX_ENUM_SIZE}; +inline constexpr usize MAX_ENUM_SIZE = {MAX_ENUM_SIZE}; template -struct Enum -{{ -static_assert("Enum size exceeds MAX_ENUM_SIZE"); -}}; +requires(sizeof...(T) <= MAX_ENUM_SIZE) +struct Enum; """ ) @@ -138,9 +137,38 @@ def out(code): return file.write(code) enum_destruct(dst); enum_copy_construct(src, dst); }} + +""") + +match_cases = [ +f""" +if constexpr(SIZE > {i}) +{{ + if(e.index_ == {i}) + {{ + return fns_ref.v{i}(e.v{i}_); + }} +}} +""" for i in range(MAX_ENUM_SIZE) +] + +out( +f""" +template +constexpr decltype(auto) match(Enum && e, Fns && ... fns) +{{ + Tuple fns_ref{{ static_cast(fns)... }}; + + {"\n".join(match_cases)} + + ASH_UNREACHABLE; }} """) +out(f""" +}} // namespace intr + +""") for size in range(0, MAX_ENUM_SIZE + 1): @@ -169,6 +197,11 @@ def out(code): return file.write(code) {"\n".join(alias_decls)} +{"" if size == 0 else +f"""template +using E = index_pack; +"""} + static constexpr usize SIZE = {size}; static constexpr usize size() @@ -177,9 +210,23 @@ def out(code): return file.write(code) }} { - """ +f""" +constexpr bool is(usize) const +{{ + return false; +}} + +constexpr void match() +{{ +}} + +constexpr void match() const +{{ +}} """ + if size == 0 else + f""" usize index_; @@ -227,10 +274,9 @@ def out(code): return file.write(code) {"\n".join(value_constructors)} -template requires(I < SIZE) -constexpr bool is() +constexpr bool is(usize i) const {{ - return index_ == I; + return index_ == i; }} template requires(I < SIZE) @@ -247,31 +293,25 @@ def out(code): return file.write(code) return intr::enum_member(*this); }} -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) {{ - + return intr::match(*this, static_cast(fns)... ); }} -template requires(sizeof...(Lambdas) == SIZE) -constexpr decltype(auto) match(Lambdas && ... lambdas) const +template +requires(sizeof...(Fns) == SIZE) +constexpr decltype(auto) match(Fns && ... fns) const {{ - + return intr::match(*this, static_cast(fns)... ); }} -template -constexpr decltype(auto) visit(Visitors && ... visitors); - -template -constexpr decltype(auto) visit(Visitors && ... visitors) const; - """ } }}; """) - # deduction guides - out(f""" }} // namespace ash diff --git a/ashura/std/error.h b/ashura/std/error.h index fb7a42ddc..62c4af677 100644 --- a/ashura/std/error.h +++ b/ashura/std/error.h @@ -31,5 +31,5 @@ CHECK_EX(*::ash::logger, ::ash::SourceLocation::current(), cond_expr, \ "[no description provided]") -#define UNREACHABLE() \ +#define CHECK_UNREACHABLE() \ CHECK_DESC(false, "Expected code section to be unreachable") diff --git a/ashura/std/format.cc b/ashura/std/format.cc index acf88b061..54649543f 100644 --- a/ashura/std/format.cc +++ b/ashura/std/format.cc @@ -41,14 +41,14 @@ bool push_int(fmt::Context const & ctx, fmt::Spec const & spec, IntT value) } auto [ptr, ec] = - std::to_chars(ctx.scratch.begin(), ctx.scratch.end(), value, base); + std::to_chars(ctx.scratch.pbegin(), ctx.scratch.pend(), value, base); if (ec != std::errc{}) { return false; } return ctx.push( - Span{ctx.scratch.begin(), (usize) (ptr - ctx.scratch.begin())}); + Span{ctx.scratch.pbegin(), (usize) (ptr - ctx.scratch.pbegin())}); } template @@ -71,19 +71,19 @@ bool push_float(fmt::Context const & ctx, fmt::Spec const & spec, FloatT value) std::to_chars_result result{}; if (spec.precision > 0) { - result = std::to_chars(ctx.scratch.begin(), ctx.scratch.end(), value, + result = std::to_chars(ctx.scratch.pbegin(), ctx.scratch.pend(), value, format, spec.precision); } else { result = - std::to_chars(ctx.scratch.begin(), ctx.scratch.end(), value, format); + std::to_chars(ctx.scratch.pbegin(), ctx.scratch.pend(), value, format); } if (result.ec == std::errc{}) { - return ctx.push( - Span{ctx.scratch.begin(), (usize) (result.ptr - ctx.scratch.begin())}); + return ctx.push(Span{ctx.scratch.pbegin(), + (usize) (result.ptr - ctx.scratch.pbegin())}); } return false; } diff --git a/ashura/std/fs.h b/ashura/std/fs.h index 22d1076f0..bf172ca1c 100644 --- a/ashura/std/fs.h +++ b/ashura/std/fs.h @@ -7,7 +7,7 @@ namespace ash { -static constexpr usize MAX_PATH_SIZE = 256; +inline constexpr usize MAX_PATH_SIZE = 256; enum class [[nodiscard]] IoErr : i32 { diff --git a/ashura/std/hash.cc b/ashura/std/hash.cc index 15a2e918b..0b00477a9 100644 --- a/ashura/std/hash.cc +++ b/ashura/std/hash.cc @@ -1,7 +1,8 @@ /// SPDX-License-Identifier: MIT +#define XXH_INLINE_ALL #include "ashura/std/hash.h" #include "ashura/std/types.h" -#include "xxh3.h" +#include "xxhash.h" namespace ash { diff --git a/ashura/std/hash.h b/ashura/std/hash.h index 56467d39e..3e38c337d 100644 --- a/ashura/std/hash.h +++ b/ashura/std/hash.h @@ -52,7 +52,61 @@ struct BitHasher } }; -constexpr StrHasher str_hash; -constexpr BitHasher bit_hash; +struct IdentityHasher +{ + constexpr hash64 operator()(u8 a) const + { + return static_cast(a); + } + + constexpr hash64 operator()(u16 a) const + { + return static_cast(a); + } + + constexpr hash64 operator()(u32 a) const + { + return static_cast(a); + } + + constexpr hash64 operator()(u64 a) const + { + return static_cast(a); + } + + constexpr hash64 operator()(i8 a) const + { + return static_cast(a); + } + + constexpr hash64 operator()(i16 a) const + { + return static_cast(a); + } + + constexpr hash64 operator()(i32 a) const + { + return static_cast(a); + } + + constexpr hash64 operator()(i64 a) const + { + return static_cast(a); + } + + constexpr hash64 operator()(f32 a) const + { + return static_cast(bit_cast(a)); + } + + constexpr hash64 operator()(f64 a) const + { + return bit_cast(a); + } +}; + +inline constexpr StrHasher str_hash; +inline constexpr BitHasher bit_hash; +inline constexpr IdentityHasher identity_hash; } // namespace ash diff --git a/ashura/std/index_pack.gen.h b/ashura/std/index_pack.gen.h new file mode 100644 index 000000000..1390f206b --- /dev/null +++ b/ashura/std/index_pack.gen.h @@ -0,0 +1,279 @@ +/// SPDX-License-Identifier: MIT +/// Meta-Generated Source Code +// clang-format off +#pragma once +#include "ashura/std/types.h" + +namespace ash +{ + +inline constexpr usize MAX_PACK_SIZE = 32; + +namespace intr +{ + +template +requires((I < sizeof...(T)) && (sizeof...(T) <= MAX_PACK_SIZE)) +struct index_pack; + + +template +struct index_pack<0, E0, E...> +{ + using Type = E0; +}; + + + +template +struct index_pack<1, E0, E1, E...> +{ + using Type = E1; +}; + + + +template +struct index_pack<2, E0, E1, E2, E...> +{ + using Type = E2; +}; + + + +template +struct index_pack<3, E0, E1, E2, E3, E...> +{ + using Type = E3; +}; + + + +template +struct index_pack<4, E0, E1, E2, E3, E4, E...> +{ + using Type = E4; +}; + + + +template +struct index_pack<5, E0, E1, E2, E3, E4, E5, E...> +{ + using Type = E5; +}; + + + +template +struct index_pack<6, E0, E1, E2, E3, E4, E5, E6, E...> +{ + using Type = E6; +}; + + + +template +struct index_pack<7, E0, E1, E2, E3, E4, E5, E6, E7, E...> +{ + using Type = E7; +}; + + + +template +struct index_pack<8, E0, E1, E2, E3, E4, E5, E6, E7, E8, E...> +{ + using Type = E8; +}; + + + +template +struct index_pack<9, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E...> +{ + using Type = E9; +}; + + + +template +struct index_pack<10, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E...> +{ + using Type = E10; +}; + + + +template +struct index_pack<11, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E...> +{ + using Type = E11; +}; + + + +template +struct index_pack<12, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E...> +{ + using Type = E12; +}; + + + +template +struct index_pack<13, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E...> +{ + using Type = E13; +}; + + + +template +struct index_pack<14, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E...> +{ + using Type = E14; +}; + + + +template +struct index_pack<15, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E...> +{ + using Type = E15; +}; + + + +template +struct index_pack<16, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E...> +{ + using Type = E16; +}; + + + +template +struct index_pack<17, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E...> +{ + using Type = E17; +}; + + + +template +struct index_pack<18, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E...> +{ + using Type = E18; +}; + + + +template +struct index_pack<19, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E...> +{ + using Type = E19; +}; + + + +template +struct index_pack<20, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E...> +{ + using Type = E20; +}; + + + +template +struct index_pack<21, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E...> +{ + using Type = E21; +}; + + + +template +struct index_pack<22, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E...> +{ + using Type = E22; +}; + + + +template +struct index_pack<23, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E...> +{ + using Type = E23; +}; + + + +template +struct index_pack<24, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E...> +{ + using Type = E24; +}; + + + +template +struct index_pack<25, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E...> +{ + using Type = E25; +}; + + + +template +struct index_pack<26, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E...> +{ + using Type = E26; +}; + + + +template +struct index_pack<27, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E...> +{ + using Type = E27; +}; + + + +template +struct index_pack<28, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E...> +{ + using Type = E28; +}; + + + +template +struct index_pack<29, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E...> +{ + using Type = E29; +}; + + + +template +struct index_pack<30, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E...> +{ + using Type = E30; +}; + + + +template +struct index_pack<31, E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E...> +{ + using Type = E31; +}; + + + +} // namespace intr +} // namespace ash + + \ No newline at end of file diff --git a/ashura/std/index_pack.h b/ashura/std/index_pack.h new file mode 100644 index 000000000..a0475e484 --- /dev/null +++ b/ashura/std/index_pack.h @@ -0,0 +1,29 @@ +/// SPDX-License-Identifier: MIT +#pragma once +#include "ashura/std/index_pack.gen.h" +#include "ashura/std/types.h" + +namespace ash +{ + +template +using index_pack = intr::index_pack::Type; + +namespace intr +{ + +template +constexpr decltype(auto) index_apply(F && f, std::index_sequence) +{ + return static_cast(f).template operator()(); +} + +} // namespace intr + +template +constexpr decltype(auto) index_apply(F && f) +{ + return intr::index_apply(static_cast(f), std::make_index_sequence{}); +} + +} // namespace ash diff --git a/ashura/std/index_pack.py b/ashura/std/index_pack.py new file mode 100644 index 000000000..67a7cef5b --- /dev/null +++ b/ashura/std/index_pack.py @@ -0,0 +1,51 @@ +import sys +MAX_SIZE = 32 + +assert len(sys.argv) > 1 + +file = open(sys.argv[1], "w", encoding="ascii") + +def out(code): return file.write(code) + + +out(f"""/// SPDX-License-Identifier: MIT +/// Meta-Generated Source Code +// clang-format off +#pragma once +#include "ashura/std/types.h" + +namespace ash +{{ + +inline constexpr usize MAX_PACK_SIZE = {MAX_SIZE}; + +namespace intr +{{ + +template +requires((I < sizeof...(T)) && (sizeof...(T) <= MAX_PACK_SIZE)) +struct index_pack; + + """) + +for index in range(MAX_SIZE): + types = [f"E{i}" for i in range(index+1)] + typenames = [f"typename E{i}" for i in range(index+1)] + out(f""" +template<{", ".join(typenames) }, typename... E> +struct index_pack<{index}, {", ".join(types)}, E...> +{{ + using Type = E{index}; +}}; + + +""") + + +out(f""" +}} // namespace intr +}} // namespace ash + + """) + + diff --git a/ashura/std/lambda.h b/ashura/std/lambda.h index 228d2d087..f135d2bf4 100644 --- a/ashura/std/lambda.h +++ b/ashura/std/lambda.h @@ -7,9 +7,9 @@ namespace ash { -static constexpr usize DEFAULT_LAMBDA_ALIGNMENT = 32; +inline constexpr usize DEFAULT_LAMBDA_ALIGNMENT = 32; -static constexpr usize DEFAULT_LAMBDA_CAPACITY = 48; +inline constexpr usize DEFAULT_LAMBDA_CAPACITY = 48; template @@ -27,6 +27,7 @@ struct Lambda; /// @tparam Alignment alignment of the internal storage in bytes /// @tparam Capacity capacity of the internal storage in bytes template +requires (Alignment > 0 && Capacity > 0) struct Lambda { static constexpr usize ALIGNMENT = Alignment; @@ -55,23 +56,23 @@ struct Lambda } }; - alignas(ALIGNMENT) mutable u8 storage[CAPACITY]; + alignas(ALIGNMENT) mutable u8 storage_[CAPACITY]; - Thunk thunk; + Thunk thunk_; - Lifecycle lifecycle; + Lifecycle lifecycle_; - template + template requires (ALIGNMENT >= alignof(Functor) && CAPACITY >= sizeof(Functor) && Callable && Convertible, R>) constexpr Lambda(Functor functor, Thunk thunk = &FunctorThunk::thunk, Lifecycle lifecycle = LIFECYCLE) : - thunk{thunk}, - lifecycle{lifecycle} + thunk_{thunk}, + lifecycle_{lifecycle} { - new (storage) Functor{static_cast(functor)}; + new (storage_) Functor{static_cast(functor)}; } constexpr Lambda(Lambda const &) = delete; @@ -81,12 +82,12 @@ struct Lambda template requires (ALIGNMENT >= SrcAlignment && CAPACITY >= SrcCapacity) constexpr Lambda(Lambda && other) : - thunk{other.thunk}, - lifecycle{other.lifecycle} + thunk_{other.thunk_}, + lifecycle_{other.lifecycle_} { - other.lifecycle(other.storage, storage); - other.lifecycle = noop; - other.thunk = nullptr; + other.lifecycle_(other.storage_, storage_); + other.lifecycle_ = noop; + other.thunk_ = nullptr; } template @@ -102,24 +103,24 @@ struct Lambda } } - lifecycle(storage, nullptr); - other.lifecycle(other.storage, storage); - lifecycle = other.lifecycle; - other.lifecycle = noop; - thunk = other.thunk; - other.thunk = nullptr; + lifecycle_(storage_, nullptr); + other.lifecycle_(other.storage_, storage_); + lifecycle_ = other.lifecycle_; + other.lifecycle_ = noop; + thunk_ = other.thunk_; + other.thunk_ = nullptr; return *this; } constexpr ~Lambda() { - lifecycle(storage, nullptr); + lifecycle_(storage_, nullptr); } constexpr R operator()(Args... args) const { - return thunk(storage, static_cast(args)...); + return thunk_(storage_, static_cast(args)...); } }; diff --git a/ashura/std/list.h b/ashura/std/list.h index 5b26b1fa2..4c1be5fb1 100644 --- a/ashura/std/list.h +++ b/ashura/std/list.h @@ -6,228 +6,286 @@ namespace ash { -/// @brief Circular Doubly-Linked list node. -/// head->next and head->prev are always non-null. -/// -/// always construct with operator new. -/// -/// @warning only use for scenarios where O(1) random insertion and/or removal -/// is a must. ListNode requires stable addressing, must not be relocated once -/// constructed. -/// -template -struct [[nodiscard]] ListNode : Pin<> +namespace intr { - ListNode * next = this; - ListNode * prev = this; - T v = {}; - - void isolate() - { - next = this; - prev = this; - } - - [[nodiscard]] constexpr bool is_linked() const - { - return next != nullptr && prev != nullptr; - } - - [[nodiscard]] constexpr bool is_isolated() const - { - return next == this && prev == this; - } -}; namespace list { -/// @brief +/// @brief Unlink Node `head` from the List, producing a new one-element List /// @tparam T -/// @param node must be valid and non-null -template -static constexpr void unlink_node(ListNode * node) +/// @param head must be valid and non-null +/// @return popped list, never null +template +constexpr void unlink(Node * head) { // detach from siblings - node->next->prev = node->prev; - node->prev->next = node->next; + head->*next->*prev = head->*prev; + head->*prev->*next = head->*next; // create 1 element node - node->next = node; - node->prev = node; + head->*next = head; + head->*prev = head; } -/// @brief +/// @brief Remove from the front of the list, producing a new one-element List /// @tparam T /// @param head must be valid and non-null, set to null if empty -/// @return popped element or null -template -[[nodiscard]] constexpr ListNode * pop_front(ListNode *& head) +/// @return unlinked element or null +template +[[nodiscard]] constexpr Node * unlink_front(Node *& head) { - ListNode * out = head; - ListNode * new_head = (head->next == head) ? nullptr : head->next; - unlink_node(out); + Node * out = head; + Node * new_head = (head->*next == head) ? nullptr : head->*next; + unlink(out); head = new_head; return out; } -/// @brief +/// @brief Remove from the back of the list, producing a new one-element List /// @tparam T /// @param head must be valid and non-null, set to null if empty -/// @return -template -[[nodiscard]] constexpr ListNode * pop_back(ListNode *& head) +/// @return unlinked element or null +template +[[nodiscard]] constexpr Node * unlink_back(Node *& head) { - ListNode * out = head->prev; - ListNode * new_head = (head->prev == head) ? nullptr : head; - unlink_node(out); + Node * out = head->*prev; + Node * new_head = (head->*prev == head) ? nullptr : head; + unlink(out); head = new_head; return out; } -/// -/// @brief +/// @brief Attach List `ext` to the end of List `head` /// /// @tparam T -/// @param node must be valid and non-null +/// @param head must be valid and non-null /// @param ext must be valid and non-null /// -template -constexpr void attach(ListNode * node, ListNode * ext) +template +constexpr void link(Node * ASH_RESTRICT head, Node * ASH_RESTRICT ext) { - ListNode * node_head = node; - ListNode * node_tail = node->prev; - ListNode * ext_head = ext; - ListNode * ext_tail = ext->prev; - ext_head->prev = node_tail; - ext_tail->next = node_head; - node_head->prev = ext_tail; - node_tail->next = ext_head; + Node * node_head = head; + Node * node_tail = head->*prev; + Node * ext_head = ext; + Node * ext_tail = ext->*prev; + ext_head->*prev = node_tail; + ext_tail->*next = node_head; + node_head->*prev = ext_tail; + node_tail->*next = ext_head; } +/// @brief Attach List `ext` to the back of List `head`, using `head` as anchor /// -/// @brief -/// -/// @tparam T /// @param head must be valid and non-null /// @param ext must be valid and non-null -/// -template -[[nodiscard]] constexpr ListNode * push_back(ListNode * head, - ListNode * ext) +/// @return the new head of the list +template +[[nodiscard]] constexpr Node * link_back(Node * ASH_RESTRICT head, + Node * ASH_RESTRICT ext) { - attach(head, ext); + link(head, ext); return head; } +/// @brief Attach List `ext` to the front of List `head`, using `head` as anchor /// -/// @brief -/// -/// @tparam T /// @param head must be valid and non-null /// @param ext must be valid and non-null -/// -template -[[nodiscard]] constexpr ListNode * push_front(ListNode * head, - ListNode * ext) +/// @return the new head of the list +template +[[nodiscard]] constexpr Node * link_front(Node * ASH_RESTRICT head, + Node * ASH_RESTRICT ext) { - attach(ext, head); + link(ext, head); return ext; } } // namespace list +} // namespace intr -// [ ] iterator model /// @brief A non-owning intrusive doubly circularly linked list. This is backed /// by an external allocator. -/// @tparam T type contained by the list's nodes -template +/// @tparam N node type +/// @tparam prev previous element getter +/// @tparam next next element getter +template struct [[nodiscard]] List { - ListNode * head; + typedef N Node; - constexpr List() : head{nullptr} + static constexpr Node * Node::* PREV = prev; + + static constexpr Node * Node::* NEXT = next; + + struct Iter { - } + Node * iter_ = nullptr; + Node * head_ = nullptr; + bool past_head_ = true; + + constexpr Node & operator*() const + { + return *iter_; + } + + constexpr Iter & operator++() + { + iter_ = iter_->next; + past_head_ = true; + return *this; + } + + constexpr bool operator!=(IterEnd) const + { + bool const finished = (past_head_ && iter_ == head_); + return !finished; + } + }; - explicit constexpr List(ListNode * head) : head{head} + Node * head_ = nullptr; + + constexpr List() = default; + + explicit constexpr List(Node * head) : head_{head} { } constexpr List(List const &) = delete; - constexpr List(List && other) : head{other.head} + constexpr List(List && other) : head_{other.head_} { - other.head = nullptr; + other.head_ = nullptr; } constexpr List & operator=(List const &) = delete; constexpr List & operator=(List && other) { - swap(head, other.head); + swap(head_, other.head_); return *this; } constexpr ~List() { - CHECK_DESC("Linked list's elements were leaked", head == nullptr); + CHECK_DESC(head_ == nullptr, "Linked list's elements were not released"); + } + + constexpr void leak() + { + head_ = nullptr; } constexpr bool is_empty() const { - return head == nullptr; + return head_ == nullptr; } - [[nodiscard]] constexpr ListNode * tail() const + [[nodiscard]] constexpr Node * head() const { - if (head == nullptr) [[unlikely]] + return head_; + } + + [[nodiscard]] constexpr Node * tail() const + { + if (head_ == nullptr) [[unlikely]] { return nullptr; } - return head->prev; + return head_->*prev; } - [[nodiscard]] constexpr ListNode * pop_front() + [[nodiscard]] constexpr Node * pop_front() { - if (head == nullptr) [[unlikely]] + if (head_ == nullptr) [[unlikely]] { return nullptr; } - return list::pop_front(head); + Node * node = intr::list::unlink_front(head_); + node->*prev = nullptr; + node->*next = nullptr; + + return node; } - [[nodiscard]] constexpr ListNode * pop_back() + [[nodiscard]] constexpr Node * pop_back() { - if (head == nullptr) [[unlikely]] + if (head_ == nullptr) [[unlikely]] { return nullptr; } - return list::pop_back(head); + Node * node = intr::list::unlink_back(head_); + node->*prev = nullptr; + node->*next = nullptr; + + return node; + } + + /// @param node non-null node to push + constexpr void push_front(Node * node) + { + node->*next = node; + node->*prev = node; + + if (head_ == nullptr) [[unlikely]] + { + head_ = node; + return; + } + + head_ = intr::list::link_front(head_, node); } - constexpr void push_front(ListNode * ext) + /// @param node non-null node to push + constexpr void push_back(Node * node) { - if (head == nullptr) [[unlikely]] + node->*next = node; + node->*prev = node; + + if (head_ == nullptr) [[unlikely]] { - head = ext; + head_ = node; return; } - head = list::push_front(head, ext); + head_ = intr::list::link_back(head_, node); } - constexpr void push_back(ListNode * ext) + constexpr void extend_front(List list) { - if (head == nullptr) [[unlikely]] + if (list.head_ == nullptr) [[unlikely]] { - head = ext; return; } - head = list::push_back(head, ext); + head_ = intr::list::link_front(head_, list.head_); + + list.leak(); + } + + constexpr void extend_back(List list) + { + if (list.head_ == nullptr) [[unlikely]] + { + return; + } + + head_ = intr::list::link_back(head_, list.head_); + + list.leak(); + } + + constexpr Iter begin() const + { + return Iter{ + .iter_ = head_, .head_ = head_, .past_head_ = (head_ == nullptr)}; + } + + constexpr auto end() const + { + return IterEnd{}; } }; diff --git a/ashura/std/locale.h b/ashura/std/locale.h index c9123655d..9a29ff4e6 100644 --- a/ashura/std/locale.h +++ b/ashura/std/locale.h @@ -4,135 +4,135 @@ namespace ash { -// IETF BCP 47 language tags. See: -// https://en.wikipedia.org/wiki/IETF_language_tag -namespace languages +/// @brief IETF BCP 47 language tags. See: +/// https://en.wikipedia.org/wiki/IETF_language_tag +namespace lang { -constexpr char AFRIKAANS[] = "af"; -constexpr char AMHARIC[] = "am"; -constexpr char ARABIC[] = "ar"; -constexpr char MAPUDUNGUN[] = "arn"; -constexpr char ASSAMESE[] = "as"; -constexpr char AZERBAIJANI[] = "az"; -constexpr char BASHKIR[] = "ba"; -constexpr char BELARUSIAN[] = "be"; -constexpr char BULGARIAN[] = "bg"; -constexpr char BENGALI[] = "bn"; -constexpr char TIBETAN[] = "bo"; -constexpr char BRETON[] = "br"; -constexpr char BOSNIAN[] = "bs"; -constexpr char CATALAN[] = "ca"; -constexpr char CORSICAN[] = "co"; -constexpr char CZECH[] = "cs"; -constexpr char WELSH[] = "cy"; -constexpr char DANISH[] = "da"; -constexpr char GERMAN[] = "de"; -constexpr char LOWER_SORBIAN[] = "dsb"; -constexpr char DIVEHI[] = "dv"; -constexpr char GREEK[] = "el"; -constexpr char ENGLISH[] = "en"; -constexpr char SPANISH[] = "es"; -constexpr char ESTONIAN[] = "et"; -constexpr char BASQUE[] = "eu"; -constexpr char PERSIAN[] = "fa"; -constexpr char FINNISH[] = "fi"; -constexpr char FILIPINO[] = "fil"; -constexpr char FAROESE[] = "fo"; -constexpr char FRENCH[] = "fr"; -constexpr char FRISIAN[] = "fy"; -constexpr char IRISH[] = "ga"; -constexpr char SCOTTISH_GAELIC[] = "gd"; -constexpr char GALICIAN[] = "gl"; -constexpr char ALSATIAN[] = "gsw"; -constexpr char GUJARATI[] = "gu"; -constexpr char HAUSA[] = "ha"; -constexpr char HEBREW[] = "he"; -constexpr char HINDI[] = "hi"; -constexpr char CROATIAN[] = "hr"; -constexpr char UPPER_SORBIAN[] = "hsb"; -constexpr char HUNGARIAN[] = "hu"; -constexpr char ARMENIAN[] = "hy"; -constexpr char INDONESIAN[] = "id"; -constexpr char IGBO[] = "ig"; -constexpr char YI[] = "ii"; -constexpr char ICELANDIC[] = "is"; -constexpr char ITALIAN[] = "it"; -constexpr char INUKTITUT[] = "iu"; -constexpr char JAPANESE[] = "ja"; -constexpr char GEORGIAN[] = "ka"; -constexpr char KAZAKH[] = "kk"; -constexpr char GREENLANDIC[] = "kl"; -constexpr char KHMER[] = "km"; -constexpr char KANNADA[] = "kn"; -constexpr char KOREAN[] = "ko"; -constexpr char KONKANI[] = "kok"; -constexpr char KYRGYZ[] = "ky"; -constexpr char LUXEMBOURGISH[] = "lb"; -constexpr char LAO[] = "lo"; -constexpr char LITHUANIAN[] = "lt"; -constexpr char LATVIAN[] = "lv"; -constexpr char MAORI_REO[] = "mi"; -constexpr char MACEDONIAN[] = "mk"; -constexpr char MALAYALAM[] = "ml"; -constexpr char MONGOLIAN[] = "mn"; -constexpr char MOHAWK[] = "moh"; -constexpr char MARATHI[] = "mr"; -constexpr char MALAY_BAHASA[] = "ms"; -constexpr char MALTESE[] = "mt"; -constexpr char BURMESE[] = "my"; -constexpr char NORWEGIAN_BOKMAL[] = "nb"; -constexpr char NEPALI[] = "ne"; -constexpr char DUTCH[] = "nl"; -constexpr char NORWEGIAN_NYNORSK[] = "nn"; -constexpr char NORWEGIAN[] = "no"; -constexpr char SESOTHO[] = "st"; -constexpr char OCCITAN[] = "oc"; -constexpr char ODIA[] = "or"; -constexpr char PUNJABI[] = "pa"; -constexpr char POLISH[] = "pl"; -constexpr char DARI[] = "prs"; -constexpr char PASHTO[] = "ps"; -constexpr char PORTUGUESE[] = "pt"; -constexpr char KICHE[] = "quc"; -constexpr char QUECHUA[] = "qu"; -constexpr char ROMANSH[] = "rm"; -constexpr char ROMANIAN[] = "ro"; -constexpr char RUSSIAN[] = "ru"; -constexpr char KINYARWANDA[] = "rw"; -constexpr char SANSKRIT[] = "sa"; -constexpr char YAKUT[] = "sah"; -constexpr char SAMI_NORTHERN[] = "se"; -constexpr char SINHALA[] = "si"; -constexpr char SLOVAK[] = "sk"; -constexpr char SLOVENIAN[] = "sl"; -constexpr char SAMI_SOUTHERN[] = "sma"; -constexpr char SAMI_LULE[] = "smj"; -constexpr char SAMI_INARI[] = "smn"; -constexpr char SAMI_SKOLT[] = "sms"; -constexpr char ALBANIAN[] = "sq"; -constexpr char SERBIAN[] = "sr"; -constexpr char SWEDISH[] = "sv"; -constexpr char KISWAHILI[] = "sw"; -constexpr char SYRIAC[] = "syc"; -constexpr char TAMIL[] = "ta"; -constexpr char TELUGU[] = "te"; -constexpr char TAJIK[] = "tg"; -constexpr char THAI[] = "th"; -constexpr char TURKMEN[] = "tk"; -constexpr char TSWANA[] = "tn"; -constexpr char TURKISH[] = "tr"; -constexpr char TATAR[] = "tt"; -constexpr char TAMAZIGHT[] = "tzm"; -constexpr char UYGHUR[] = "ug"; -constexpr char UKRAINIAN[] = "uk"; -constexpr char URDU[] = "ur"; -constexpr char UZBEK[] = "uz"; -constexpr char VIETNAMESE[] = "vi"; -constexpr char WOLOF[] = "wo"; -constexpr char XHOSA[] = "xh"; -constexpr char YORUBA[] = "yo"; -constexpr char CHINESE[] = "zh"; -constexpr char ZULU[] = "zu"; -} // namespace languages +inline constexpr char AFRIKAANS[] = "af"; +inline constexpr char AMHARIC[] = "am"; +inline constexpr char ARABIC[] = "ar"; +inline constexpr char MAPUDUNGUN[] = "arn"; +inline constexpr char ASSAMESE[] = "as"; +inline constexpr char AZERBAIJANI[] = "az"; +inline constexpr char BASHKIR[] = "ba"; +inline constexpr char BELARUSIAN[] = "be"; +inline constexpr char BULGARIAN[] = "bg"; +inline constexpr char BENGALI[] = "bn"; +inline constexpr char TIBETAN[] = "bo"; +inline constexpr char BRETON[] = "br"; +inline constexpr char BOSNIAN[] = "bs"; +inline constexpr char CATALAN[] = "ca"; +inline constexpr char CORSICAN[] = "co"; +inline constexpr char CZECH[] = "cs"; +inline constexpr char WELSH[] = "cy"; +inline constexpr char DANISH[] = "da"; +inline constexpr char GERMAN[] = "de"; +inline constexpr char LOWER_SORBIAN[] = "dsb"; +inline constexpr char DIVEHI[] = "dv"; +inline constexpr char GREEK[] = "el"; +inline constexpr char ENGLISH[] = "en"; +inline constexpr char SPANISH[] = "es"; +inline constexpr char ESTONIAN[] = "et"; +inline constexpr char BASQUE[] = "eu"; +inline constexpr char PERSIAN[] = "fa"; +inline constexpr char FINNISH[] = "fi"; +inline constexpr char FILIPINO[] = "fil"; +inline constexpr char FAROESE[] = "fo"; +inline constexpr char FRENCH[] = "fr"; +inline constexpr char FRISIAN[] = "fy"; +inline constexpr char IRISH[] = "ga"; +inline constexpr char SCOTTISH_GAELIC[] = "gd"; +inline constexpr char GALICIAN[] = "gl"; +inline constexpr char ALSATIAN[] = "gsw"; +inline constexpr char GUJARATI[] = "gu"; +inline constexpr char HAUSA[] = "ha"; +inline constexpr char HEBREW[] = "he"; +inline constexpr char HINDI[] = "hi"; +inline constexpr char CROATIAN[] = "hr"; +inline constexpr char UPPER_SORBIAN[] = "hsb"; +inline constexpr char HUNGARIAN[] = "hu"; +inline constexpr char ARMENIAN[] = "hy"; +inline constexpr char INDONESIAN[] = "id"; +inline constexpr char IGBO[] = "ig"; +inline constexpr char YI[] = "ii"; +inline constexpr char ICELANDIC[] = "is"; +inline constexpr char ITALIAN[] = "it"; +inline constexpr char INUKTITUT[] = "iu"; +inline constexpr char JAPANESE[] = "ja"; +inline constexpr char GEORGIAN[] = "ka"; +inline constexpr char KAZAKH[] = "kk"; +inline constexpr char GREENLANDIC[] = "kl"; +inline constexpr char KHMER[] = "km"; +inline constexpr char KANNADA[] = "kn"; +inline constexpr char KOREAN[] = "ko"; +inline constexpr char KONKANI[] = "kok"; +inline constexpr char KYRGYZ[] = "ky"; +inline constexpr char LUXEMBOURGISH[] = "lb"; +inline constexpr char LAO[] = "lo"; +inline constexpr char LITHUANIAN[] = "lt"; +inline constexpr char LATVIAN[] = "lv"; +inline constexpr char MAORI_REO[] = "mi"; +inline constexpr char MACEDONIAN[] = "mk"; +inline constexpr char MALAYALAM[] = "ml"; +inline constexpr char MONGOLIAN[] = "mn"; +inline constexpr char MOHAWK[] = "moh"; +inline constexpr char MARATHI[] = "mr"; +inline constexpr char MALAY_BAHASA[] = "ms"; +inline constexpr char MALTESE[] = "mt"; +inline constexpr char BURMESE[] = "my"; +inline constexpr char NORWEGIAN_BOKMAL[] = "nb"; +inline constexpr char NEPALI[] = "ne"; +inline constexpr char DUTCH[] = "nl"; +inline constexpr char NORWEGIAN_NYNORSK[] = "nn"; +inline constexpr char NORWEGIAN[] = "no"; +inline constexpr char SESOTHO[] = "st"; +inline constexpr char OCCITAN[] = "oc"; +inline constexpr char ODIA[] = "or"; +inline constexpr char PUNJABI[] = "pa"; +inline constexpr char POLISH[] = "pl"; +inline constexpr char DARI[] = "prs"; +inline constexpr char PASHTO[] = "ps"; +inline constexpr char PORTUGUESE[] = "pt"; +inline constexpr char KICHE[] = "quc"; +inline constexpr char QUECHUA[] = "qu"; +inline constexpr char ROMANSH[] = "rm"; +inline constexpr char ROMANIAN[] = "ro"; +inline constexpr char RUSSIAN[] = "ru"; +inline constexpr char KINYARWANDA[] = "rw"; +inline constexpr char SANSKRIT[] = "sa"; +inline constexpr char YAKUT[] = "sah"; +inline constexpr char SAMI_NORTHERN[] = "se"; +inline constexpr char SINHALA[] = "si"; +inline constexpr char SLOVAK[] = "sk"; +inline constexpr char SLOVENIAN[] = "sl"; +inline constexpr char SAMI_SOUTHERN[] = "sma"; +inline constexpr char SAMI_LULE[] = "smj"; +inline constexpr char SAMI_INARI[] = "smn"; +inline constexpr char SAMI_SKOLT[] = "sms"; +inline constexpr char ALBANIAN[] = "sq"; +inline constexpr char SERBIAN[] = "sr"; +inline constexpr char SWEDISH[] = "sv"; +inline constexpr char KISWAHILI[] = "sw"; +inline constexpr char SYRIAC[] = "syc"; +inline constexpr char TAMIL[] = "ta"; +inline constexpr char TELUGU[] = "te"; +inline constexpr char TAJIK[] = "tg"; +inline constexpr char THAI[] = "th"; +inline constexpr char TURKMEN[] = "tk"; +inline constexpr char TSWANA[] = "tn"; +inline constexpr char TURKISH[] = "tr"; +inline constexpr char TATAR[] = "tt"; +inline constexpr char TAMAZIGHT[] = "tzm"; +inline constexpr char UYGHUR[] = "ug"; +inline constexpr char UKRAINIAN[] = "uk"; +inline constexpr char URDU[] = "ur"; +inline constexpr char UZBEK[] = "uz"; +inline constexpr char VIETNAMESE[] = "vi"; +inline constexpr char WOLOF[] = "wo"; +inline constexpr char XHOSA[] = "xh"; +inline constexpr char YORUBA[] = "yo"; +inline constexpr char CHINESE[] = "zh"; +inline constexpr char ZULU[] = "zu"; +} // namespace lang } // namespace ash diff --git a/ashura/std/log.cc b/ashura/std/log.cc index ee3280013..402847af6 100644 --- a/ashura/std/log.cc +++ b/ashura/std/log.cc @@ -86,9 +86,9 @@ void StdioSink::log(LogLevels level, Span log_message) break; } - constexpr char const time_format[] = "%d/%m/%Y, %H:%M:%S"; - char time_string[256]; - usize time_string_length = 0; + static constexpr char const time_format[] = "%d/%m/%Y, %H:%M:%S"; + char time_string[256]; + usize time_string_length = 0; std::time_t current_time = std::time(nullptr); if (current_time != (std::time_t) -1) @@ -120,10 +120,10 @@ void StdioSink::flush() void FileSink::log(LogLevels level, Span log_message) { - char const * level_str = get_level_str(level); - constexpr char const time_format[] = "%d/%m/%Y, %H:%M:%S"; - char time_string[256]; - usize time_string_length = 0; + char const * level_str = get_level_str(level); + static constexpr char const time_format[] = "%d/%m/%Y, %H:%M:%S"; + char time_string[256]; + usize time_string_length = 0; std::time_t current_time = std::time(nullptr); if (current_time != (std::time_t) -1) diff --git a/ashura/std/map.h b/ashura/std/map.h index e5d2eded0..a71b5bae0 100644 --- a/ashura/std/map.h +++ b/ashura/std/map.h @@ -57,16 +57,16 @@ struct [[nodiscard]] Map { break; } - iter_++; - probe_++; + ++iter_; + ++probe_; } } constexpr Iter & operator++() { // advancement past the current element must occur - iter_++; - probe_++; + ++iter_; + ++probe_; seek(); @@ -78,13 +78,13 @@ struct [[nodiscard]] Map return *probe_; } - constexpr bool operator!=(IterEnd const &) const + constexpr bool operator!=(IterEnd) const { return iter_ != end_; } }; - struct Range + struct View { Distance * iter_ = nullptr; Distance const * end_ = nullptr; @@ -527,7 +527,7 @@ struct [[nodiscard]] Map return false; } - constexpr Range span() const + constexpr View view() const { Iter iter{.iter_ = probe_dists_, .end_ = probe_dists_ + num_probes_, @@ -535,15 +535,15 @@ struct [[nodiscard]] Map iter.seek(); - return Range{.iter_ = iter.iter_, .end_ = iter.end_, .probe_ = iter.probe_}; + return View{.iter_ = iter.iter_, .end_ = iter.end_, .probe_ = iter.probe_}; } constexpr Iter begin() const { - return span().begin(); + return view().begin(); } - constexpr IterEnd end() const + constexpr auto end() const { return IterEnd{}; } diff --git a/ashura/std/math.h b/ashura/std/math.h index 75a7a831b..933e3a984 100644 --- a/ashura/std/math.h +++ b/ashura/std/math.h @@ -2542,11 +2542,15 @@ inline Vec2 rotor(f32 a) return Vec2{cos(a), sin(a)}; } -constexpr Vec2 ALIGNMENT_CENTER{0, 0}; -constexpr Vec2 ALIGNMENT_TOP_LEFT{-1, -1}; -constexpr Vec2 ALIGNMENT_TOP_RIGHT{1, -1}; -constexpr Vec2 ALIGNMENT_BOTTOM_LEFT{-1, 1}; -constexpr Vec2 ALIGNMENT_BOTTOM_RIGHT{1, 1}; +inline constexpr Vec2 ALIGNMENT_CENTER{0, 0}; +inline constexpr Vec2 ALIGNMENT_TOP_LEFT{-1, -1}; +inline constexpr Vec2 ALIGNMENT_TOP_CENTER{0, -1}; +inline constexpr Vec2 ALIGNMENT_TOP_RIGHT{1, -1}; +inline constexpr Vec2 ALIGNMENT_BOTTOM_LEFT{-1, 1}; +inline constexpr Vec2 ALIGNMENT_BOTTOM_CENTER{0, 1}; +inline constexpr Vec2 ALIGNMENT_BOTTOM_RIGHT{1, 1}; +inline constexpr Vec2 ALIGNMENT_LEFT_CENTER{-1, 0}; +inline constexpr Vec2 ALIGNMENT_RIGHT_CENTER{1, 0}; constexpr Vec4 opacity(f32 v) { diff --git a/ashura/std/mem.h b/ashura/std/mem.h index 66414ba0c..fd98818df 100644 --- a/ashura/std/mem.h +++ b/ashura/std/mem.h @@ -1,23 +1,24 @@ /// SPDX-License-Identifier: MIT #pragma once #include "ashura/std/traits.h" +#include "ashura/std/tuple.h" #include "ashura/std/types.h" #include namespace ash { -constexpr usize MAX_STANDARD_ALIGNMENT = alignof(max_align_t); +inline constexpr usize MAX_STANDARD_ALIGNMENT = alignof(max_align_t); /// @brief Just a hint, this is a common cacheline size. not the actual target's /// cacheline size -constexpr usize CACHELINE_ALIGNMENT = 64; +inline constexpr usize CACHELINE_ALIGNMENT = 64; /// @brief Just a hint, this is the common page alignment. not the actual /// target's page alignment. -constexpr usize PAGE_ALIGNMENT = 16_KB; +inline constexpr usize PAGE_ALIGNMENT = 16_KB; -constexpr usize PAGE_SIZE = PAGE_ALIGNMENT; +inline constexpr usize PAGE_SIZE = PAGE_ALIGNMENT; template constexpr T align_offset(T alignment, T offset) @@ -194,6 +195,7 @@ struct Layout } }; +/// @brief Get the memory layout of a type template constexpr Layout layout = Layout{.alignment = alignof(T), .size = sizeof(T)}; @@ -202,10 +204,10 @@ constexpr Layout layout = Layout{.alignment = alignof(T), .size = sizeof(T)}; /// offsets, and sizing requirements of the types and the resulting struct. /// @tparam N number of members in the flexible struct /// @param members memory layout of the members -template +template struct Flex { - Layout members[N]{}; + Layout members[sizeof...(T)]{}; constexpr Layout layout() const { @@ -217,29 +219,22 @@ struct Flex return l.aligned(); } - template - void unpack_at(void const *& stack, usize i, Span & span) const - { - stack = align_ptr(members[i].alignment, stack); - usize const count = members[i].size / sizeof(T); - span = Span{(T *) stack, count}; - stack = ((u8 const *) stack) + members[i].size; - } - - template - void unpack_at(void const *& stack, usize i, T *& ptr) const + template + auto unpack_at_(void const *& stack) const { - Span span; - unpack_at(stack, i, span); - ptr = span.data(); + using M = index_pack; + stack = align_ptr(members[I].alignment, stack); + usize const count = members[I].size / sizeof(M); + Span span{(M *) stack, count}; + stack = ((u8 const *) stack) + members[I].size; + return span; } - template - requires (sizeof...(T) == N) - void unpack(void const * stack, T &... p) const + Tuple...> unpack(void const * stack) const { - usize i = 0; - (unpack_at(stack, i++, p), ...); + return index_apply([&]() { + return Tuple...>{unpack_at_(stack)...}; + }); } }; diff --git a/ashura/std/obj.h b/ashura/std/obj.h index 4d9b7c2af..f5d2de623 100644 --- a/ashura/std/obj.h +++ b/ashura/std/obj.h @@ -12,7 +12,7 @@ namespace obj template constexpr void default_construct(Span dst) { - for (T * iter = dst.begin(); iter != dst.end(); iter++) + for (T * iter = dst.pbegin(); iter != dst.pend(); iter++) { new (iter) T{}; } @@ -21,7 +21,7 @@ constexpr void default_construct(Span dst) template constexpr void move_construct(Span src, U * dst) { - for (T * in = src.begin(); in != src.end(); in++, dst++) + for (T * in = src.pbegin(); in != src.pend(); in++, dst++) { new (dst) T{static_cast(*in)}; } @@ -36,7 +36,7 @@ constexpr void move_construct(Span src, Span dst) template constexpr void copy_construct(Span src, U * dst) { - for (T * in = src.begin(); in != src.end(); in++, dst++) + for (T * in = src.pbegin(); in != src.pend(); in++, dst++) { new (dst) T{*in}; } @@ -53,7 +53,7 @@ constexpr void destruct(Span src) { if constexpr (!TriviallyDestructible) { - for (T * iter = src.begin(); iter != src.end(); iter++) + for (T * iter = src.pbegin(); iter != src.pend(); iter++) { iter->~T(); } @@ -63,7 +63,7 @@ constexpr void destruct(Span src) template constexpr void move_assign(Span src, U * dst) { - for (T * in = src.begin(); in != src.end(); in++, dst++) + for (T * in = src.pbegin(); in != src.pend(); in++, dst++) { *in = static_cast(*dst); } @@ -78,7 +78,7 @@ constexpr void move_assign(Span src, Span dst) template constexpr void copy_assign(Span src, U * dst) { - for (T * in = src.begin(); in != src.end(); in++, dst++) + for (T * in = src.pbegin(); in != src.pend(); in++, dst++) { *dst = *in; } diff --git a/ashura/std/range.h b/ashura/std/range.h index c2883b3e0..05c8bc99c 100644 --- a/ashura/std/range.h +++ b/ashura/std/range.h @@ -30,50 +30,62 @@ struct IndexIter } }; -/// @param inc_ non-zero increment template -struct SkipIndexIter +struct IndexRange { - I i_{}; - I incr_{1}; + I min_{}; I max_{}; - constexpr SkipIndexIter & operator++() + constexpr auto begin() const { - i_ += incr_; - return *this; + return IndexIter{.i_ = min_, .max_ = max_}; } - constexpr I operator*() const + constexpr auto end() const { - return i_; + return IterEnd{}; } - constexpr bool operator!=(IterEnd) const + constexpr I size() const { - return i_ != max_; + return max_ - min_; } }; template -struct IndexRange +constexpr IndexRange range(I max) { - I min_{}; + return IndexRange{.min_ = 0, .max_ = max}; +} + +template +constexpr IndexRange range(I min, I max) +{ + return IndexRange{.min_ = min, .max_ = max}; +} + +/// @param inc_ non-zero increment +template +struct SkipIndexIter +{ + I i_{}; + I incr_{1}; I max_{}; - constexpr auto begin() const + constexpr SkipIndexIter & operator++() { - return IndexIter{.i_ = min_, .max_ = max_}; + i_ += incr_; + return *this; } - constexpr auto end() const + constexpr I operator*() const { - return IterEnd{}; + return i_; } - constexpr I size() const + constexpr bool operator!=(IterEnd) const { - return max_ - min_; + return i_ != max_; } }; @@ -101,41 +113,45 @@ struct SkipIndexRange } }; -template -struct EnumerateIter +template +constexpr SkipIndexRange range(I min, I max, I advance) +{ + return SkipIndexRange{.min_ = min, .max_ = max, .incr_ = advance}; +} + +/// @warning Equality is only determined by the first iterator +template +struct ZipIter { - Index index_{}; - Iter iter_{}; - IterEnd end_{}; + Tuple iters_{}; - constexpr EnumerateIter & operator++() + constexpr ZipIter & operator++() { - ++index_; - ++iter_; + apply([](auto &... iters) { (++iters, ...); }, iters_); return *this; } constexpr auto operator*() const { - return Tuple{index_, iter_}; + return apply( + [](auto... iters) { return Tuple{(*iters)...}; }, + iters_); } - constexpr bool operator!=(IterEnd) const + constexpr bool operator!=(IterEnd end) const { - return iter_ != end_; + return iters_.v0 != end; } }; -template -struct EnumerateRange +template +struct ZipRange { - IterBegin begin_; - IterEnd end_; + Tuple begins_{}; constexpr auto begin() const { - return EnumerateIter{ - .index_ = 0, .iter_ = begin_, .end_ = end_}; + return ZipIter{.iters_{begins_}}; } constexpr auto end() const @@ -144,42 +160,49 @@ struct EnumerateRange } }; -/// @warning Equality is only determined by the first iterator -template -struct ZipIter +/// @brief The size of the head range will be used as the total size of the whole range +template +constexpr auto zip(Base && base, Ranges &&... ranges) { - Tuple iters_{}; - BaseIterEnd end0_{}; + return ZipRange{ + .begins_{begin(base), begin(ranges)...}, + .end_{end(base)} + }; +} - constexpr ZipIter & operator++() +template +struct EnumerateIter +{ + Index index_{}; + Iter iter_{}; + + constexpr EnumerateIter & operator++() { - apply([](auto &... iters) { (++iters, ...); }, iters_); + ++index_; + ++iter_; return *this; } constexpr auto operator*() const { - return apply( - [](auto... iters) { return Tuple{(*iters)...}; }, - iters_); + return Tuple{index_, *iter_}; } - constexpr bool operator!=(IterEnd) const + constexpr bool operator!=(IterEnd end) const { - return iters_.v0 != end0_; + return iter_ != end; } }; -template -struct ZipRange +template +struct EnumerateRange { - Tuple begins_{}; - BaseIterEnd end0_{}; + Iter iter_; constexpr auto begin() const { - return ZipIter{.iters_{begins_}, - .end0_{end0_}}; + return EnumerateIter{.index_ = 0, .iter_ = iter_}; } constexpr auto end() const @@ -188,48 +211,18 @@ struct ZipRange } }; -template -constexpr IndexRange range(I max) -{ - return IndexRange{.i0 = 0, .i1 = max}; -} - -template -constexpr IndexRange range(I min, I max) -{ - return IndexRange{.i0 = min, .i1 = max}; -} - -template -constexpr SkipIndexRange range(I min, I max, I advance) -{ - return SkipIndexRange{.i0 = min, .i1 = max, .advance = advance}; -} - -/// @brief The size of the head range will be used as the total size of the whole range -template -constexpr auto zip(Base && base, Ranges &&... ranges) -{ - return ZipRange{ - .begins_{begin(base), begin(ranges)...}, - .end_{end(base)} - }; -} - template constexpr auto enumerate(R && range) { - return EnumerateRange{ - .begin_{begin(range)}, .end_{end(range)}}; + return EnumerateRange{.iter_{begin(range)}}; } -template +template constexpr void swap_range(A && a, B && b, SwapOp && swap_op = {}) { - auto a_iter = begin(a); - auto a_end = end(a); - auto b_iter = begin(b); + auto a_iter = begin(a); + auto const a_end = end(a); + auto b_iter = begin(b); while (a_iter != a_end) { @@ -239,11 +232,11 @@ constexpr void swap_range(A && a, B && b, SwapOp && swap_op = {}) } } -template +template constexpr void fill(R && dst, U && value) { - auto iter = begin(dst); - auto dst_end = end(dst); + auto iter = begin(dst); + auto const dst_end = end(dst); while (iter != dst_end) { @@ -255,8 +248,8 @@ constexpr void fill(R && dst, U && value) template constexpr bool all(R && range, Predicate && predicate) { - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -272,8 +265,8 @@ constexpr bool all(R && range, Predicate && predicate) template constexpr bool any(R && range, Predicate && predicate) { - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -289,8 +282,8 @@ constexpr bool any(R && range, Predicate && predicate) template constexpr bool none(R && range, Predicate && predicate) { - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -306,8 +299,8 @@ constexpr bool none(R && range, Predicate && predicate) template constexpr bool contains(R && range, U && value, Cmp && cmp = {}) { - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -328,9 +321,9 @@ constexpr bool begins_with(B && body, H && head, Cmp && cmp = {}) return false; } - auto body_iter = begin(body); - auto head_iter = begin(head); - auto head_end = end(head); + auto body_iter = begin(body); + auto head_iter = begin(head); + auto const head_end = end(head); while (head_iter != head_end) { @@ -345,17 +338,17 @@ constexpr bool begins_with(B && body, H && head, Cmp && cmp = {}) return true; } -template -constexpr bool ends_with(B && body, F && foot, Cmp && cmp = {}) +template +constexpr bool ends_with(Span body, Span foot, Cmp && cmp = {}) { - if (size(foot) > size(body)) + if (foot.size() > body.size()) { return false; } - auto foot_iter = begin(foot); - auto foot_end = end(foot); - auto body_iter = end(body) - size(foot); + auto foot_iter = foot.pbegin(); + auto const foot_end = foot.pbegin(); + auto body_iter = body.pend() - foot.size(); while (foot_iter != foot_end) { @@ -372,40 +365,51 @@ constexpr bool ends_with(B && body, F && foot, Cmp && cmp = {}) } /// size is 0 if not found, size is 1 if found +// +// [ ] use range slicing? not all ranges are equal +// template constexpr Span find(Span span, U && value, Cmp && cmp = {}) { - usize offset = 0; - for (; offset < span.size(); ++offset) + auto iter = begin(span); + auto const span_end = end(span); + + while (iter != span_end) { - if (cmp(span[offset], value)) + if (cmp(*iter, value)) { break; } + ++iter; } - return span.slice(offset, 1); + + return Span{iter, span_end}; } template constexpr Span find_if(Span span, Predicate && predicate) { - usize offset = 0; - for (; offset < span.size(); ++offset) + auto iter = begin(span); + auto const span_end = end(span); + + while (iter != span_end) { - if (predicate(span[offset])) + if (predicate(*iter)) { break; } + ++iter; } - return span.slice(offset, 1); + + return Span{iter, span_end}; } template constexpr usize count(R && range, Target && target, Cmp && cmp = {}) { - usize count = 0; - auto iter = begin(range); - auto range_end = end(range); + usize count = 0; + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -413,6 +417,7 @@ constexpr usize count(R && range, Target && target, Cmp && cmp = {}) { count++; } + ++iter; } return count; @@ -423,8 +428,8 @@ constexpr usize count_if(R && range, Predicate && predicate) { usize count = 0; - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -432,6 +437,7 @@ constexpr usize count_if(R && range, Predicate && predicate) { count++; } + ++iter; } return count; @@ -445,9 +451,9 @@ constexpr bool range_eq(A && a, B && b, Cmp && cmp = {}) return false; } - auto a_iter = begin(a); - auto a_end = end(a); - auto b_iter = begin(b); + auto a_iter = begin(a); + auto const a_end = end(a); + auto b_iter = begin(b); while (a_iter != a_end) { @@ -462,12 +468,12 @@ constexpr bool range_eq(A && a, B && b, Cmp && cmp = {}) return true; } -template +template constexpr void transform(I && in, O && out, Map && mapper) { - auto in_iter = begin(in); - auto in_end = end(in); - auto out_iter = begin(out); + auto in_iter = begin(in); + auto const in_end = end(in); + auto out_iter = begin(out); while (in_iter != in_end) { @@ -477,11 +483,24 @@ constexpr void transform(I && in, O && out, Map && mapper) } } +template +constexpr void transform(O && out, Map && mapper) +{ + auto out_iter = begin(out); + auto const out_end = end(out); + + while (out_iter != out_end) + { + *out_iter = mapper(*out_iter); + ++out_iter; + } +} + template constexpr Init reduce(R && range, Init && init, Reduce && reducer = {}) { - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -496,8 +515,8 @@ template constexpr Init transform_reduce(R && range, Init && init, Map && mapper, Reduce && reducer = {}) { - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -508,12 +527,12 @@ constexpr Init transform_reduce(R && range, Init && init, Map && mapper, return static_cast(init); } -template +template constexpr void replace(R && range, E && target, F && replacement, Cmp && cmp = {}) { - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -524,11 +543,11 @@ constexpr void replace(R && range, E && target, F && replacement, } } -template +template constexpr void replace_if(R && range, F && replacement, Test && test) { - auto iter = begin(range); - auto range_end = end(range); + auto iter = begin(range); + auto const range_end = end(range); while (iter != range_end) { @@ -536,24 +555,22 @@ constexpr void replace_if(R && range, F && replacement, Test && test) { *iter = replacement; } + ++iter; } } -template -constexpr void unique(Span, Cmp && cmp = {}); // destroy? retain? - -template -constexpr void reverse(R && range, SwapOp && swap = {}) +template +constexpr void reverse(Span span, SwapOp && swap = {}) { - if (is_empty(range)) + auto * head = span.pbegin(); + auto * tail = span.pend(); + + if (head == tail) { return; } - // [ ] Use range API - - auto head = begin(range); - auto tail = end(range) - 1; + tail--; while (head < tail) { @@ -566,20 +583,13 @@ constexpr void reverse(R && range, SwapOp && swap = {}) template constexpr void split(Span span, Span delimeter, Op op, Cmp && cmp = {}); -// first check if src begins with other -// keep advancing whilst src begins with other -// once it doesn't, store present offset, -// slice from present offset to end, and compare for other -// if equal, move back from end - other.size -// if equal again, move back -// move back until it is no longer equal template constexpr Span strip(Span src, Span other, Cmp && cmp = {}); -template -constexpr void sort(S && span, Cmp && cmp = {}) +template +constexpr void sort(Span span, Cmp && cmp = {}) { - std::sort(begin(span), end(span), cmp); + std::sort(span.pbegin(), span.pend(), cmp); } template @@ -588,10 +598,10 @@ constexpr void indirect_sort(Span indices, Cmp && cmp = {}) sort(indices, [&](I a, I b) { return cmp(a, b); }); } -template -constexpr void stable_sort(S && span, Cmp && cmp = {}) +template +constexpr void stable_sort(Span span, Cmp && cmp = {}) { - std::stable_sort(begin(span), end(span), cmp); + std::stable_sort(span.pbegin(), span.pend(), cmp); } template @@ -600,12 +610,13 @@ constexpr void indirect_stable_sort(Span indices, Cmp && cmp = {}) stable_sort(indices, [&](I a, I b) { return cmp(a, b); }); } -template -constexpr Tuple partition(R && range, Predicate && predicate) +template +constexpr Tuple, Span> partition(Span range, + Predicate && predicate) { - auto iter = begin(range); - auto range_end = end(range); - auto const first = begin(range); + auto iter = range.pbegin(); + auto const range_end = range.pend(); + auto const first = range.pbegin(); while (iter != range_end && predicate(*iter)) { @@ -624,32 +635,29 @@ constexpr Tuple partition(R && range, Predicate && predicate) ++iter; } - usize const first_size = static_cast(next - first); - usize const second_size = static_cast(iter - next); - return Tuple{ - Slice{0, first_size }, - Slice{first_size, second_size} + Span{first, next }, + Span{next, range_end} }; } -template -void iota(Span s, T first) +template +void iota(R && range, T && first) { - for (auto & v : s) + // [ ] use range methods + for (auto & value : range) { - v = first; - ++first; + value = first++; }; } -template -constexpr T inclusive_scan(Span in, Span out, T && init = {}, +template +constexpr T inclusive_scan(Span in, Span out, T init = {}, Op && op = {}) { - T const * in_iter = begin(in); - T const * in_end = end(in); - T * out_iter = begin(out); + I const * in_iter = in.pbegin(); + I const * const in_end = in.pend(); + O * out_iter = out.pbegin(); while (in_iter != in_end) { @@ -662,47 +670,31 @@ constexpr T inclusive_scan(Span in, Span out, T && init = {}, return init; } -template -constexpr T prefix_sum(Span in, Span out, T && init = {}, - Op && op = {}) -{ - return inclusive_scan(in, out, static_cast(init), - static_cast(op)); -} - -template -constexpr T exclusive_scan(Span in, Span out, T && init = {}, +template +constexpr T exclusive_scan(Span in, Span out, T init = {}, Op && op = {}) { - T const * in_iter = begin(in); - T const * in_end = end(in); - T * out_iter = begin(out); + I const * in_iter = in.pbegin(); + I const * const in_end = in.pend(); + O * out_iter = out.pbegin(); while (in_iter != in_end) { *out_iter = op(static_cast(init), *in_iter); init = *out_iter; - ++in_end; + ++in_iter; ++out_iter; } return init; } -template -constexpr T suffix_sum(Span in, Span out, T && init = {}, - Op && op = {}) -{ - return exclusive_scan(in, out, static_cast(init), - static_cast(op)); -} - template struct PrefixRunIter { - Index * run_iter_ = nullptr; - T * data_ = nullptr; - Index * end_ = nullptr; + Index * run_iter_ = nullptr; + Index const * end_ = nullptr; + T * data_ = nullptr; constexpr PrefixRunIter & operator++() { @@ -717,23 +709,23 @@ struct PrefixRunIter return Span{data_ + begin, data_ + end}; } - constexpr bool operator!=(IterEnd const &) const + constexpr bool operator!=(IterEnd) const { return run_iter_ != end_; } }; template -struct PrefixRunSpan +struct PrefixRunRange { - Index * run_begin_; - Index * run_end_; - T * data_; + Index * run_begin_; + Index const * run_end_; + T * data_; constexpr auto begin() const { return PrefixRunIter{ - .run_iter_ = run_begin_, .run_start_ = 0, .data_ = data_}; + .run_iter_ = run_begin_, .end_ = run_end_, .data_ = data_}; } constexpr auto end() const @@ -742,13 +734,23 @@ struct PrefixRunSpan } }; +/// @param ends run-ends of the data. Must be sorted. +template +constexpr PrefixRunRange prefix_run(Span data, + Span runs) +{ + return PrefixRunRange{.run_begin_ = runs.pbegin(), + .run_end_ = runs.pend(), + .data_ = data.data()}; +} + template struct SuffixRunIter { - Index * run_iter_ = nullptr; - Index * run_end_ = nullptr; - Index run_start_ = 0; - T * data_ = nullptr; + Index * run_iter_ = nullptr; + Index const * run_end_ = nullptr; + Index run_start_ = 0; + T * data_ = nullptr; constexpr SuffixRunIter & operator++() { @@ -762,18 +764,18 @@ struct SuffixRunIter return Span{data_ + run_start_, data_ + *run_iter_}; } - constexpr bool operator!=(IterEnd const &) const + constexpr bool operator!=(IterEnd) const { return run_iter_ != run_end_; } }; template -struct SuffixRunSpan +struct SuffixRunRange { - Index * run_begin_; - Index * run_end_; - T * data_; + Index * run_begin_; + Index const * run_end_; + T * data_; constexpr auto begin() const { @@ -791,31 +793,133 @@ struct SuffixRunSpan /// @param ends run-ends of the data. Must be sorted. template -constexpr PrefixRunSpan prefix_run(Span data, - Span ends) +constexpr SuffixRunRange suffix_run(Span data, + Span runs) { - return PrefixRunSpan{ - .run_begin_ = ends.begin(), .run_end_ = ends.end(), .data_ = data.data()}; + return SuffixRunRange{.run_begin_ = runs.pbegin(), + .run_end_ = runs.pend(), + .data_ = data.data()}; } -/// @param ends run-ends of the data. Must be sorted. -template -constexpr SuffixRunSpan suffix_run(Span data, - Span ends) +/// @brief search for first element less than or equal to value +template +constexpr Span lower_bound(Span span, U && value, Cmp && cmp = {}) { - return SuffixRunSpan{ - .run_begin_ = ends.begin(), .run_end_ = ends.end(), .data_ = data.data()}; + usize size = span.size(); + T * iter = span.pbegin(); + + while (size != 0) + { + usize const half_size = size >> 1; + + if (cmp(iter[half_size], value)) + { + size = half_size; + } + else + { + size -= half_size + 1; + iter += half_size; + } + } + + return Span{iter, span.pend()}; } -// TODO: tuple transform: use for sparsevec push +/// @brief search for first element greater than value +template +constexpr Span upper_bound(Span span, U && value, Cmp && cmp = {}) +{ + usize size = span.size(); + T * iter = span.pbegin(); -// [ ] window -// -// is_sorted() -// apply() - in-place -// binary_search() -// lower_bound() -// upper_bound() -// fold() + while (size != 0) + { + usize const half_size = size >> 1; + + if (cmp(value, iter[half_size])) + { + size -= half_size + 1; + iter += half_size; + } + else + { + size = half_size; + } + } + + return Span{iter, span.pend()}; +} + +/// @param window_advance_ must be non-zero +template +struct WindowIter +{ + T * iter_ = nullptr; + T const * end_ = nullptr; + usize window_size_{0}; + usize window_advance_{1}; + + constexpr WindowIter & operator++() + { + iter_ += window_advance_; + return *this; + } + + constexpr Span operator*() const + { + return Span{iter_, window_size_}; + } + + constexpr bool operator==(IterEnd) const + { + return (iter_ + window_size_) >= end_; + } +}; + +template +struct WindowRange +{ + T * begin_ = nullptr; + T const * end_ = nullptr; + usize window_size_{0}; + usize window_advance_{1}; + + constexpr auto begin() const + { + return WindowIter{.iter_ = begin_, + .end_ = end_, + .window_size_ = window_size_, + .window_advance_ = window_advance_}; + } + + constexpr auto end() const + { + return IterEnd{}; + } +}; + +template +constexpr WindowRange window(Span span, usize window_size, usize advance) +{ + if (window_size > span.size()) [[unlikely]] + { + return WindowRange{}; + } + + return WindowRange{.begin_ = span.pbegin(), + .end_ = span.pend(), + .window_size_ = window_size, + .window_advance_ = advance}; +} + +template +constexpr WindowRange window(Span span, usize window_size) +{ + return window(span, window_size, window_size); +} + +// [ ] is_sorted() +// [ ] radix_sort() } // namespace ash diff --git a/ashura/std/super.h b/ashura/std/super.h index cafea4656..98d365ee8 100644 --- a/ashura/std/super.h +++ b/ashura/std/super.h @@ -6,9 +6,9 @@ namespace ash { -static constexpr usize DEFAULT_SUPER_ALIGNMENT = 32; +inline constexpr usize DEFAULT_SUPER_ALIGNMENT = 32; -static constexpr usize DEFAULT_SUPER_CAPACITY = 48; +inline constexpr usize DEFAULT_SUPER_CAPACITY = 48; template @@ -41,19 +41,19 @@ struct Super } }; - alignas(ALIGNMENT) mutable u8 storage[CAPACITY]; + alignas(ALIGNMENT) mutable u8 storage_[CAPACITY]; - Base * base_ptr; + Base * base_; - Lifecycle lifecycle; + Lifecycle lifecycle_; template - requires (Derives && ALIGNMENT >= alignof(Object) && + requires (Derives && ALIGNMENT >= alignof(Object) && CAPACITY >= sizeof(Object)) constexpr Super(Object object, Lifecycle lifecycle = LIFECYCLE) : - lifecycle{lifecycle} + lifecycle_{lifecycle} { - base_ptr = new (storage) Object{static_cast(object)}; + base_ = new (storage_) Object{static_cast(object)}; } constexpr Super(Super const &) = delete; @@ -63,11 +63,11 @@ struct Super template requires (ALIGNMENT >= SrcAlignment && CAPACITY >= SrcCapacity) constexpr Super(Super && other) : - lifecycle{other.lifecycle} + lifecycle_{other.lifecycle_} { - other.lifecycle(other.storage, storage, &base_ptr); - other.lifecycle = noop; - other.base_ptr = nullptr; + other.lifecycle_(other.storage_, storage_, &base_); + other.lifecycle_ = noop; + other.base_ = nullptr; } template @@ -82,28 +82,28 @@ struct Super } } - lifecycle(storage, nullptr, nullptr); - other.lifecycle(other.storage, storage, &base_ptr); - lifecycle = other.lifecycle; - other.lifecycle = noop; - other.base_ptr = nullptr; + lifecycle_(storage_, nullptr, nullptr); + other.lifecycle_(other.storage_, storage_, &base_); + lifecycle_ = other.lifecycle_; + other.lifecycle_ = noop; + other.base_ = nullptr; return *this; } constexpr operator Base &() const { - return *base_ptr; + return *base_; } constexpr Base & get() const { - return *base_ptr; + return *base_; } constexpr ~Super() { - lifecycle(storage, nullptr, nullptr); + lifecycle_(storage_, nullptr, nullptr); } }; diff --git a/ashura/std/tests/enum.cc b/ashura/std/tests/enum.cc index 20a780724..4454d202e 100644 --- a/ashura/std/tests/enum.cc +++ b/ashura/std/tests/enum.cc @@ -9,8 +9,12 @@ TEST(EnumTest, Basic) Enum, int, float, int *> f{nullptr}; EXPECT_EQ(f.index(), 3); - // [ ] map( ) - // [ ] + static constexpr Enum e{0.2F}; - static constexpr Enum e{0.0F}; -} \ No newline at end of file + constexpr auto a = e.match([](f32) { return 1.0F; }, // + [](f32) { return 0.5F; }, // + [](f32) { return 3.0F; }); + + EXPECT_EQ(a, 3.0F); + EXPECT_EQ(e.v2_, 0.2F); +} diff --git a/ashura/std/tests/list.cc b/ashura/std/tests/list.cc index 3b0ba74bc..786f9dbd1 100644 --- a/ashura/std/tests/list.cc +++ b/ashura/std/tests/list.cc @@ -7,19 +7,26 @@ TEST(ListTest, Insertion) { using namespace ash; - ArenaPool pool; + u8 storage[512]; + Arena arena = to_arena(storage); - List l; - ListNode *x; - ListNode *y; - CHECK(pool.nalloc(1, x)); - CHECK(pool.nalloc(1, y)); - x->isolate(); - y->isolate(); + struct Node + { + Node *next = nullptr, *prev = nullptr; + int v = 0; + }; + List l; + Node * x; + Node * y; + CHECK(arena.nalloc(1, x)); + CHECK(arena.nalloc(1, y)); + + EXPECT_EQ(l.head(), nullptr); l.push_front(x); - EXPECT_NE(l.head, nullptr); - EXPECT_EQ(l.head, x); + EXPECT_NE(l.head(), nullptr); + + EXPECT_EQ(l.head(), x); EXPECT_EQ(l.pop_back(), x); EXPECT_EQ(l.pop_back(), nullptr); l.push_front(x); @@ -27,4 +34,4 @@ TEST(ListTest, Insertion) EXPECT_EQ(l.pop_back(), x); EXPECT_EQ(l.pop_back(), y); EXPECT_EQ(l.pop_back(), nullptr); -} \ No newline at end of file +} diff --git a/ashura/std/tests/sparse_vec.cc b/ashura/std/tests/sparse_vec.cc index 3d40182a1..b265212d9 100644 --- a/ashura/std/tests/sparse_vec.cc +++ b/ashura/std/tests/sparse_vec.cc @@ -30,7 +30,7 @@ TEST(SparseVecTest, Start) ASSERT_EQ(f.size(), 10); ASSERT_EQ(f[7], 8); ASSERT_EQ(f[9], 0); - ASSERT_TRUE(f.extend_defaulted(5)); + ASSERT_TRUE(f.extend(5)); ASSERT_EQ(f.size(), 15); ASSERT_EQ(f[10], 0); ASSERT_EQ(f[12], 0); @@ -46,16 +46,23 @@ TEST(SparseVecTest, Start) SparseVec, Vec, BitVec> set; + for (auto [a, b, c] : set) + { + a += 2; + b += 3; + (void) c; + } + ASSERT_TRUE(set.push(69U, 67U, true)); ASSERT_EQ(set.size(), 1); ASSERT_EQ(set.size(), set.dense.v0.size()); ASSERT_TRUE(set.push(42U, 32U, false)); ASSERT_EQ(set.size(), 2); ASSERT_EQ(set.size(), set.dense.v0.size()); - ASSERT_EQ(set.dense.v0[0], 69U); - ASSERT_EQ(set.dense.v0[1], 42U); - ASSERT_EQ(set.dense.v2[0], true); - ASSERT_EQ(set.dense.v2[1], false); + ASSERT_EQ(set[0].v0, 69U); + ASSERT_EQ(set[1].v0, 42U); + ASSERT_EQ(set[0].v2, true); + ASSERT_EQ(set[1].v2, false); ASSERT_TRUE(set.try_erase(0)); ASSERT_EQ(set.size(), 1); ASSERT_EQ(set.size(), set.dense.v0.size()); diff --git a/ashura/std/text.h b/ashura/std/text.h index 0d6e94a24..420398a01 100644 --- a/ashura/std/text.h +++ b/ashura/std/text.h @@ -2,6 +2,7 @@ #pragma once #include "ashura/std/error.h" #include "ashura/std/result.h" +#include "ashura/std/tuple.h" #include "ashura/std/types.h" #include "ashura/std/vec.h" @@ -16,7 +17,7 @@ namespace ash { c8 const * in = text.data(); usize count = 0; - while (in != text.end()) + while (in != text.pend()) { if ((*in & 0xc0) != 0x80) { @@ -34,7 +35,7 @@ namespace ash { c8 const * in = encoded.data(); c32 * out = decoded.data(); - while (in != encoded.end()) + while (in != encoded.pend()) { if ((*in & 0xF8) == 0xF0) { @@ -63,7 +64,7 @@ namespace ash *out++ = c1; } } - return out - decoded.begin(); + return out - decoded.pbegin(); } /// @brief encoded.size must be at least decoded.size * 4 @@ -73,7 +74,7 @@ namespace ash c8 * out = encoded.data(); c32 const * in = decoded.data(); - while (in != decoded.end()) + while (in != decoded.pend()) { if (*in <= 0x7F) { @@ -103,7 +104,7 @@ namespace ash } } - return out - encoded.begin(); + return out - encoded.pbegin(); } /// @brief converts UTF-8 text from @p encoded to UTF-32 and appends into @p @@ -116,7 +117,7 @@ inline Result<> utf8_decode(Span encoded, Vec & decoded) { return Err{}; } - (void) utf8_decode(encoded, decoded.span().slice(first, count)); + (void) utf8_decode(encoded, decoded.view().slice(first, count)); return Ok{}; } @@ -132,7 +133,7 @@ inline Result<> utf8_decode(Span encoded, Vec & decoded) return Err{}; } usize const count = - utf8_encode(decoded, encoded.span().slice(first, max_count)); + utf8_encode(decoded, encoded.view().slice(first, max_count)); encoded.resize_uninit(first + count).unwrap(); return Ok{}; } @@ -140,10 +141,10 @@ inline Result<> utf8_decode(Span encoded, Vec & decoded) constexpr void replace_invalid_codepoints(Span input, Span output, c32 replacement) { - c32 const * in = input.begin(); - c32 * out = output.begin(); + c32 const * in = input.pbegin(); + c32 * out = output.pbegin(); - while (in < input.end()) + while (in < input.pend()) { if (*in > 0x10'FFFF) [[unlikely]] { @@ -159,20 +160,22 @@ constexpr void replace_invalid_codepoints(Span input, } /// Unicode Ranges - -constexpr Slice32 UTF_BASIC_LATIN{0x0020, 0x007F - 0x0020}; -constexpr Slice32 UTF_LATIN1_SUPPLEMENT{0x00A0, 0x00FF - 0x00A0}; -constexpr Slice32 UTF_LATIN_EXTENDED_A{0x0100, 0x017F - 0x0100}; -constexpr Slice32 UTF_LATIN_EXTENDED_B{0x0180, 0x024F - 0x0180}; -constexpr Slice32 UTF_COMBINING_DIACRITICAL_MARKS{0x0300, 0x036F - 0x0300}; -constexpr Slice32 UTF_ARABIC{0x0600, 0x06FF - 0x0600}; -constexpr Slice32 UTF_GENERAL_PUNCTUATION{0x2000, 0x206F - 0x2000}; -constexpr Slice32 UTF_SUPERSCRIPTS_AND_SUBSCRIPTS{0x2070, 0x209F - 0x2070}; -constexpr Slice32 UTF_CURRENCY_SYMBOLS{0x20A0, 0x20CF - 0x20A0}; -constexpr Slice32 UTF_NUMBER_FORMS{0x2150, 0x218F - 0x2150}; -constexpr Slice32 UTF_ARROWS{0x2190, 0x21FF - 0x2190}; -constexpr Slice32 UTF_MATHEMATICAL_OPERATORS{0x2200, 0x22FF - 0x2200}; -constexpr Slice32 UTF_HIRAGANA{0x3040, 0x309F - 0x3040}; -constexpr Slice32 UTF_KATAKANA{0x30A0, 0x30FF - 0x30A0}; +namespace utf +{ +inline constexpr Tuple BASIC_LATIN{0x0020, 0x007F}; +inline constexpr Tuple LATIN1_SUPPLEMENT{0x00A0, 0x00FF}; +inline constexpr Tuple LATIN_EXTENDED_A{0x0100, 0x017F}; +inline constexpr Tuple LATIN_EXTENDED_B{0x0180, 0x024F}; +inline constexpr Tuple COMBINING_DIACRITICAL_MARKS{0x0300, 0x036F}; +inline constexpr Tuple ARABIC{0x0600, 0x06FF}; +inline constexpr Tuple GENERAL_PUNCTUATION{0x2000, 0x206F}; +inline constexpr Tuple SUPERSCRIPTS_AND_SUBSCRIPTS{0x2070, 0x209F}; +inline constexpr Tuple CURRENCY_SYMBOLS{0x20A0, 0x20CF}; +inline constexpr Tuple NUMBER_FORMS{0x2150, 0x218F}; +inline constexpr Tuple ARROWS{0x2190, 0x21FF}; +inline constexpr Tuple MATHEMATICAL_OPERATORS{0x2200, 0x22FF}; +inline constexpr Tuple HIRAGANA{0x3040, 0x309F}; +inline constexpr Tuple KATAKANA{0x30A0, 0x30FF}; +} // namespace utf } // namespace ash diff --git a/ashura/std/traits.h b/ashura/std/traits.h index 6cc79eae6..31f461eb6 100644 --- a/ashura/std/traits.h +++ b/ashura/std/traits.h @@ -158,11 +158,6 @@ struct is_pfn_impl template concept AnyPFn = is_pfn_impl::value; -template -concept AnyFunctor = requires () { - { &F::operator() }; -}; - template concept Predicate = requires (Fn fn, Args... args) { { fn(static_cast(args)...) && true }; diff --git a/ashura/std/tuple.gen.h b/ashura/std/tuple.gen.h index 8f84d499d..cfb12efa7 100644 --- a/ashura/std/tuple.gen.h +++ b/ashura/std/tuple.gen.h @@ -4,10 +4,11 @@ #pragma once #include "ashura/std/types.h" #include "ashura/std/v.h" +#include "ashura/std/index_pack.h" namespace ash{ -static constexpr usize MAX_TUPLE_SIZE = 16; +inline constexpr usize MAX_TUPLE_SIZE = 16; namespace intr @@ -99,13 +100,11 @@ if constexpr(I == 15) }; -} +} // namespace intr template -struct Tuple -{ -static_assert("Tuple size exceeds MAX_TUPLE_SIZE"); -}; +requires(sizeof...(T) <= MAX_TUPLE_SIZE) +struct Tuple; template<> struct Tuple<> @@ -113,6 +112,8 @@ struct Tuple<> + + static constexpr usize SIZE = 0; static constexpr usize size() @@ -143,6 +144,10 @@ struct Tuple typedef T0 E0; +template +using E = index_pack; + + static constexpr usize SIZE = 1; static constexpr usize size() @@ -178,6 +183,10 @@ struct Tuple typedef T0 E0; typedef T1 E1; +template +using E = index_pack; + + static constexpr usize SIZE = 2; static constexpr usize size() @@ -215,6 +224,10 @@ typedef T0 E0; typedef T1 E1; typedef T2 E2; +template +using E = index_pack; + + static constexpr usize SIZE = 3; static constexpr usize size() @@ -254,6 +267,10 @@ typedef T1 E1; typedef T2 E2; typedef T3 E3; +template +using E = index_pack; + + static constexpr usize SIZE = 4; static constexpr usize size() @@ -295,6 +312,10 @@ typedef T2 E2; typedef T3 E3; typedef T4 E4; +template +using E = index_pack; + + static constexpr usize SIZE = 5; static constexpr usize size() @@ -338,6 +359,10 @@ typedef T3 E3; typedef T4 E4; typedef T5 E5; +template +using E = index_pack; + + static constexpr usize SIZE = 6; static constexpr usize size() @@ -383,6 +408,10 @@ typedef T4 E4; typedef T5 E5; typedef T6 E6; +template +using E = index_pack; + + static constexpr usize SIZE = 7; static constexpr usize size() @@ -430,6 +459,10 @@ typedef T5 E5; typedef T6 E6; typedef T7 E7; +template +using E = index_pack; + + static constexpr usize SIZE = 8; static constexpr usize size() @@ -479,6 +512,10 @@ typedef T6 E6; typedef T7 E7; typedef T8 E8; +template +using E = index_pack; + + static constexpr usize SIZE = 9; static constexpr usize size() @@ -530,6 +567,10 @@ typedef T7 E7; typedef T8 E8; typedef T9 E9; +template +using E = index_pack; + + static constexpr usize SIZE = 10; static constexpr usize size() @@ -583,6 +624,10 @@ typedef T8 E8; typedef T9 E9; typedef T10 E10; +template +using E = index_pack; + + static constexpr usize SIZE = 11; static constexpr usize size() @@ -638,6 +683,10 @@ typedef T9 E9; typedef T10 E10; typedef T11 E11; +template +using E = index_pack; + + static constexpr usize SIZE = 12; static constexpr usize size() @@ -695,6 +744,10 @@ typedef T10 E10; typedef T11 E11; typedef T12 E12; +template +using E = index_pack; + + static constexpr usize SIZE = 13; static constexpr usize size() @@ -754,6 +807,10 @@ typedef T11 E11; typedef T12 E12; typedef T13 E13; +template +using E = index_pack; + + static constexpr usize SIZE = 14; static constexpr usize size() @@ -815,6 +872,10 @@ typedef T12 E12; typedef T13 E13; typedef T14 E14; +template +using E = index_pack; + + static constexpr usize SIZE = 15; static constexpr usize size() @@ -878,6 +939,10 @@ typedef T13 E13; typedef T14 E14; typedef T15 E15; +template +using E = index_pack; + + static constexpr usize SIZE = 16; static constexpr usize size() diff --git a/ashura/std/tuple.h b/ashura/std/tuple.h index 8eae6f1d8..4e2553592 100644 --- a/ashura/std/tuple.h +++ b/ashura/std/tuple.h @@ -61,25 +61,6 @@ constexpr decltype(auto) apply(F && f, Tuple && t) std::make_index_sequence::SIZE>{}); } -template -constexpr decltype(auto) impl_index_apply(F && f, std::index_sequence) -{ - return f.template operator()(); -} - -template -constexpr decltype(auto) index_apply(F && f) -{ - return impl_index_apply(static_cast(f), std::make_index_sequence{}); -} - -template -constexpr decltype(auto) zip_apply(F && f, Tuples &&... tuples) -{ - // [ ] impl - // apply over Index -} - template constexpr decltype(auto) impl_fold_reduce(Tuple & fns, In &&... in) { diff --git a/ashura/std/tuple.py b/ashura/std/tuple.py index 70a562af9..bfccfb829 100644 --- a/ashura/std/tuple.py +++ b/ashura/std/tuple.py @@ -15,10 +15,11 @@ def out(code): return file.write(code) #pragma once #include "ashura/std/types.h" #include "ashura/std/v.h" +#include "ashura/std/index_pack.h" namespace ash{{ -static constexpr usize MAX_TUPLE_SIZE = {MAX_TUPLE_SIZE}; +inline constexpr usize MAX_TUPLE_SIZE = {MAX_TUPLE_SIZE}; """) @@ -41,17 +42,15 @@ def out(code): return file.write(code) {"else".join(tuple_cases)} }}; -}} +}} // namespace intr """) out( f""" template -struct Tuple -{{ -static_assert("Tuple size exceeds MAX_TUPLE_SIZE"); -}}; +requires(sizeof...(T) <= MAX_TUPLE_SIZE) +struct Tuple; """ ) @@ -72,6 +71,11 @@ def out(code): return file.write(code) {"\n".join(alias_decls)} +{"" if size == 0 else +f"""template +using E = index_pack; +"""} + static constexpr usize SIZE = {size}; static constexpr usize size() diff --git a/ashura/std/types.h b/ashura/std/types.h index 801901b02..20f46891f 100644 --- a/ashura/std/types.h +++ b/ashura/std/types.h @@ -34,49 +34,49 @@ typedef uintptr_t uptr; typedef intptr_t iptr; typedef u64 hash64; -constexpr u8 U8_MIN = 0; -constexpr u8 U8_MAX = 0xFF; +inline constexpr u8 U8_MIN = 0; +inline constexpr u8 U8_MAX = 0xFF; -constexpr i8 I8_MIN = -0x7F - 1; -constexpr i8 I8_MAX = 0x7F; +inline constexpr i8 I8_MIN = -0x7F - 1; +inline constexpr i8 I8_MAX = 0x7F; -constexpr u16 U16_MIN = 0; -constexpr u16 U16_MAX = 0xFFFF; +inline constexpr u16 U16_MIN = 0; +inline constexpr u16 U16_MAX = 0xFFFF; -constexpr i16 I16_MIN = -0x7FFF - 1; -constexpr i16 I16_MAX = 0x7FFF; +inline constexpr i16 I16_MIN = -0x7FFF - 1; +inline constexpr i16 I16_MAX = 0x7FFF; -constexpr u32 U32_MIN = 0; -constexpr u32 U32_MAX = 0xFFFF'FFFFU; +inline constexpr u32 U32_MIN = 0; +inline constexpr u32 U32_MAX = 0xFFFF'FFFFU; -constexpr i32 I32_MIN = -0x7FFF'FFFF - 1; -constexpr i32 I32_MAX = 0x7FFF'FFFF; +inline constexpr i32 I32_MIN = -0x7FFF'FFFF - 1; +inline constexpr i32 I32_MAX = 0x7FFF'FFFF; -constexpr u64 U64_MIN = 0; -constexpr u64 U64_MAX = 0xFFFF'FFFF'FFFF'FFFFULL; +inline constexpr u64 U64_MIN = 0; +inline constexpr u64 U64_MAX = 0xFFFF'FFFF'FFFF'FFFFULL; -constexpr i64 I64_MIN = -0x7FFF'FFFF'FFFF'FFFFLL - 1; -constexpr i64 I64_MAX = 0x7FFF'FFFF'FFFF'FFFFLL; +inline constexpr i64 I64_MIN = -0x7FFF'FFFF'FFFF'FFFFLL - 1; +inline constexpr i64 I64_MAX = 0x7FFF'FFFF'FFFF'FFFFLL; -constexpr usize USIZE_MIN = 0; -constexpr usize USIZE_MAX = SIZE_MAX; +inline constexpr usize USIZE_MIN = 0; +inline constexpr usize USIZE_MAX = SIZE_MAX; -constexpr isize ISIZE_MIN = PTRDIFF_MIN; -constexpr isize ISIZE_MAX = PTRDIFF_MAX; +inline constexpr isize ISIZE_MIN = PTRDIFF_MIN; +inline constexpr isize ISIZE_MAX = PTRDIFF_MAX; -constexpr f32 F32_MIN = -FLT_MAX; -constexpr f32 F32_MIN_POSITIVE = FLT_MIN; -constexpr f32 F32_MAX = FLT_MAX; -constexpr f32 F32_EPS = FLT_EPSILON; -constexpr f32 F32_INF = INFINITY; +inline constexpr f32 F32_MIN = -FLT_MAX; +inline constexpr f32 F32_MIN_POSITIVE = FLT_MIN; +inline constexpr f32 F32_MAX = FLT_MAX; +inline constexpr f32 F32_EPS = FLT_EPSILON; +inline constexpr f32 F32_INF = INFINITY; -constexpr f64 F64_MIN = -DBL_MAX; -constexpr f64 F64_MIN_POSITIVE = DBL_MIN; -constexpr f64 F64_MAX = DBL_MAX; -constexpr f64 F64_EPS = DBL_EPSILON; -constexpr f64 F64_INF = INFINITY; +inline constexpr f64 F64_MIN = -DBL_MAX; +inline constexpr f64 F64_MIN_POSITIVE = DBL_MIN; +inline constexpr f64 F64_MAX = DBL_MAX; +inline constexpr f64 F64_EPS = DBL_EPSILON; +inline constexpr f64 F64_INF = INFINITY; -constexpr f32 PI = 3.14159265358979323846F; +inline constexpr f32 PI = 3.14159265358979323846F; struct Add { @@ -181,6 +181,14 @@ struct Min { return a < b ? a : b; } + + template + constexpr T operator()(T const & a, T const & b, T1 const &... cs) const + { + T m = this->template operator()(a, b); + ((m = this->template operator()(static_cast(m), cs)), ...); + return m; + } }; struct Max @@ -190,6 +198,14 @@ struct Max { return a > b ? a : b; } + + template + constexpr T operator()(T const & a, T const & b, T1 const &... cs) const + { + T m = this->template operator()(a, b); + ((m = this->template operator()(static_cast(m), cs)), ...); + return m; + } }; struct Swap @@ -343,6 +359,8 @@ constexpr i32 sat_mul(i32 a, i32 b) // [ ] sat_cast +using std::bit_cast; + template constexpr bool has_bits(T src, T cmp) { @@ -846,7 +864,7 @@ struct Slice64 constexpr operator Slice() const { - return Slice{offset, span}; + return Slice{static_cast(offset), static_cast(span)}; } }; @@ -855,14 +873,14 @@ struct IterEnd }; template -struct SpanIterator +struct SpanIter { T * iter_ = nullptr; T * end_ = nullptr; - constexpr SpanIterator & operator++() + constexpr SpanIter & operator++() { - iter_++; + ++iter_; return *this; } @@ -871,16 +889,16 @@ struct SpanIterator return *iter_; } - constexpr bool operator!=(IterEnd const &) const + constexpr bool operator!=(IterEnd) const { return iter_ != end_; } }; template -constexpr SpanIterator begin(T (&a)[N]) +constexpr SpanIter begin(T (&a)[N]) { - return SpanIterator{.iter_ = a, .end_ = a + N}; + return SpanIter{.iter_ = a, .end_ = a + N}; } template @@ -890,7 +908,7 @@ constexpr auto begin(T && a) -> decltype(a.begin()) } template -constexpr IterEnd end(T (&)[N]) +constexpr auto end(T (&)[N]) { return IterEnd{}; } @@ -946,7 +964,7 @@ constexpr usize size_bits(T (&)[N]) template constexpr auto size_bits(T && a) -> decltype(a.size()) { - return sizeof(T) * 8 * a.size(); + return sizeof(T) * a.size() * 8; } template @@ -955,6 +973,9 @@ constexpr auto is_empty(T && a) return size(a) == 0; } +/// @brief Iterator Model. Iterators are only required to +/// produce values, they are not required to provide +/// references to the values template concept Iter = requires (T it) { { @@ -962,497 +983,271 @@ concept Iter = requires (T it) { *it }; { - // pre-fix advancement + // in-place (pre-fix) advancement ++it }; }; +/// @brief Range Model. Ranges are read-only by default. template concept Range = requires (R r) { - { begin(r) } -> Iter; - { !(begin(r) != end(r)) }; + { + // can get an iterator to its beginning element + begin(r) + } -> Iter; + { + // returns boolean when asked if it has ended + !(begin(r) != end(r)) + }; }; +// [ ] struct ExampleRange +// { +// [ ] nth(); +// }; + +// [ ] change to range set using iter template constexpr void iter_set(T * iterator, Arg && arg) { *iterator = static_cast(arg); } -template -constexpr void iter_set(Uninitialized, T * iterator, Arg && arg) -{ - new (iterator) T{static_cast(arg)}; -} - // [ ] output iterator - base: set to intial value template -concept OutputIter = Iter; +concept OutIter = Iter; template -concept OutputRange = Range; - -template -struct Array -{ - using Type = T; - static constexpr usize SIZE = N; - - T data_[SIZE]{}; - - static constexpr bool is_empty() - { - return false; - } - - constexpr T * data() - { - return data_; - } +concept OutRange = Range; - constexpr T const * data() const - { - return data_; - } - - static constexpr usize size() - { - return SIZE; - } +template +concept SpanCompatible = Convertible; - static constexpr u32 size32() - { - return (u32) SIZE; - } +template +using ContainerDataType = + std::remove_pointer_t()))>; - static constexpr u64 size64() - { - return (u64) SIZE; - } +template +concept SpanContainer = requires (Container cont) { + { data(cont) }; + { size(cont) }; +}; - static constexpr usize capacity() - { - return SIZE; - } +template +concept SpanCompatibleContainer = + SpanContainer && SpanCompatible, T>; - static constexpr usize size_bytes() - { - return sizeof(T) * SIZE; - } +template +struct Span +{ + using Type = T; + using Repr = T; + using Iter = SpanIter; - constexpr T * begin() - { - return data_; - } + T * data_ = nullptr; + usize size_ = 0; - constexpr T const * begin() const - { - return data_; - } + constexpr Span() = default; - constexpr T * end() + constexpr Span(T * data, usize size) : data_{data}, size_{size} { - return data_ + SIZE; } - constexpr T const * end() const + constexpr Span(T * begin, T const * end) : + data_{begin}, + size_{static_cast(end - begin)} { - return data_ + SIZE; } - constexpr T & first() + constexpr Span(Iter iter, IterEnd = {}) : Span{iter.iter_, iter.end_} { - return get(0); } - constexpr T const & first() const + template + constexpr Span(T (&data)[N]) : data_{data}, size_{N} { - return get(0); } - constexpr T & last() + template C> + constexpr Span(C & cont) : data_{ash::data(cont)}, size_{ash::size(cont)} { - return get(SIZE - 1); } - constexpr T const & last() const + template U> + constexpr Span(Span span) : data_{span.data_}, size_{span.size_} { - return get(SIZE - 1); } - constexpr T & get(usize index) - { - return data_[index]; - } + constexpr Span(Span const &) = default; - constexpr T const & get(usize index) const - { - return data_[index]; - } + constexpr Span(Span &&) = default; - template - constexpr void set(usize index, Args &&... args) - { - data_[index] = T{static_cast(args)...}; - } + constexpr Span & operator=(Span const &) = default; - constexpr T & operator[](usize index) - { - return data_[index]; - } + constexpr Span & operator=(Span &&) = default; - constexpr T const & operator[](usize index) const - { - return data_[index]; - } + constexpr ~Span() = default; - constexpr operator T *() + constexpr bool is_empty() const { - return data_; + return size_ == 0; } - constexpr operator T const *() const + constexpr T * data() const { return data_; } -}; - -template -struct Array -{ - using Type = T; - static constexpr usize SIZE = 0; - - static constexpr bool is_empty() - { - return true; - } - constexpr T * data() + constexpr usize size() const { - return nullptr; + return size_; } - constexpr T const * data() const + constexpr u32 size32() const { - return nullptr; + return (u32) size_; } - static constexpr usize size() + constexpr u64 size64() const { - return SIZE; + return (u64) size_; } - static constexpr u32 size32() + constexpr usize size_bytes() const { - return (u32) SIZE; + return sizeof(T) * size_; } - static constexpr u64 size64() + constexpr Iter begin() const { - return (u64) SIZE; + return Iter{.iter_ = data_, .end_ = data_ + size_}; } - static constexpr usize capacity() + constexpr auto end() const { - return SIZE; + return IterEnd{}; } - static constexpr usize size_bytes() + constexpr T * pbegin() const { - return sizeof(T) * SIZE; + return data_; } - constexpr T * begin() + constexpr T * pend() const { - return nullptr; + return data_ + size_; } - constexpr T const * begin() const + constexpr T & first() const { - return nullptr; + return get(0); } - constexpr T * end() + constexpr T & last() const { - return nullptr; + return get(size_ - 1); } - constexpr T const * end() const + constexpr T & operator[](usize index) const { - return nullptr; + return data_[index]; } - constexpr T & first() requires (SIZE > 1) + constexpr T & get(usize index) const { - return get(0); + return data_[index]; } - constexpr T const & first() const requires (SIZE > 1) + template + constexpr void set(usize index, Args &&... args) const requires (NonConst) { - return get(0); + data_[index] = T{static_cast(args)...}; } - constexpr T & last() requires (SIZE > 1) + constexpr Span as_const() const { - return get(SIZE - 1); + return Span{data_, size_}; } - constexpr T const & last() const requires (SIZE > 1) + constexpr Span as_u8() const requires (NonConst) { - return get(SIZE - 1); + return Span{reinterpret_cast(data_), size_bytes()}; } - constexpr T & get(usize index) requires (SIZE > 1) + constexpr Span as_u8() const requires (Const) { - return data()[index]; + return Span{reinterpret_cast(data_), size_bytes()}; } - constexpr T const & get(usize index) const requires (SIZE > 1) + constexpr Span as_char() const requires (NonConst) { - return data()[index]; + return Span{reinterpret_cast(data_), size_bytes()}; } - template - constexpr void set(usize index, Args &&... args) requires (SIZE > 1) + constexpr Span as_char() const requires (Const) { - data()[index] = T{static_cast(args)...}; + return Span{reinterpret_cast(data_), + size_bytes()}; } - constexpr T & operator[](usize index) requires (SIZE > 1) + constexpr Span slice(usize offset, usize span) const { - return data()[index]; + return slice(Slice{offset, span}); } - constexpr T const & operator[](usize index) const + constexpr Span slice(Slice s) const { - return data()[index]; + s = s(size_); + return Span{data_ + s.offset, s.span}; } - constexpr operator T *() + constexpr Span slice(usize offset) const { - return nullptr; + return slice(offset, USIZE_MAX); } - constexpr operator T const *() const + template + Span reinterpret() const { - return nullptr; + return Span{reinterpret_cast(data_), + (sizeof(T) * size_) / sizeof(U)}; } }; template -struct IsTriviallyRelocatable> -{ - static constexpr bool value = TriviallyRelocatable; -}; +Span(T (&)[N]) -> Span; -template -using Bits = Repr[BIT_PACKS]; +template +Span(C & container) -> Span>; -template -using BitArray = Array>; - -template -concept SpanCompatible = Convertible; - -template -using ContainerDataType = - std::remove_pointer_t()))>; - -template -concept SpanContainer = requires (Container cont) { - { data(cont) }; - { size(cont) }; -}; - -template -concept SpanCompatibleContainer = - SpanContainer && SpanCompatible, T>; - -template -struct Span -{ - using Type = T; - using Repr = T; - - T * data_ = nullptr; - usize size_ = 0; - - constexpr Span() = default; - - constexpr Span(T * data, usize size) : data_{data}, size_{size} - { - } - - constexpr Span(T * begin, T const * end) : - data_{begin}, - size_{static_cast(end - begin)} - { - } - - template - constexpr Span(T (&data)[N]) : data_{data}, size_{N} - { - } - - template C> - constexpr Span(C & cont) : data_{ash::data(cont)}, size_{ash::size(cont)} - { - } - - template U> - constexpr Span(Span span) : data_{span.data_}, size_{span.size_} - { - } - - constexpr Span(Span const &) = default; - - constexpr Span(Span &&) = default; - - constexpr Span & operator=(Span const &) = default; - - constexpr Span & operator=(Span &&) = default; - - constexpr ~Span() = default; - - constexpr bool is_empty() const - { - return size_ == 0; - } - - constexpr T * data() const - { - return data_; - } - - constexpr usize size() const - { - return size_; - } - - constexpr u32 size32() const - { - return (u32) size_; - } - - constexpr u64 size64() const - { - return (u64) size_; - } - - constexpr usize size_bytes() const - { - return sizeof(T) * size_; - } - - constexpr T * begin() const - { - return data_; - } - - constexpr T * end() const - { - return data_ + size_; - } - - constexpr T & first() const - { - return get(0); - } - - constexpr T & last() const - { - return get(size_ - 1); - } - - constexpr T & operator[](usize index) const - { - return data_[index]; - } - - constexpr T & get(usize index) const - { - return data_[index]; - } - - template - constexpr void set(usize index, Args &&... args) const requires (NonConst) - { - data_[index] = T{static_cast(args)...}; - } - - constexpr Span as_const() const - { - return Span{data_, size_}; - } - - constexpr Span as_u8() const requires (NonConst) - { - return Span{reinterpret_cast(data_), size_bytes()}; - } - - constexpr Span as_u8() const requires (Const) - { - return Span{reinterpret_cast(data_), size_bytes()}; - } - - constexpr Span as_char() const requires (NonConst) - { - return Span{reinterpret_cast(data_), size_bytes()}; - } - - constexpr Span as_char() const requires (Const) - { - return Span{reinterpret_cast(data_), - size_bytes()}; - } - - constexpr Span slice(usize offset, usize span) const - { - return slice(Slice{offset, span}); - } - - constexpr Span slice(Slice s) const - { - s = s(size_); - return Span{data_ + s.offset, s.span}; - } - - constexpr Span slice(usize offset) const - { - return slice(offset, USIZE_MAX); - } - - template - Span reinterpret() const - { - return Span{reinterpret_cast(data_), - (sizeof(T) * size_) / sizeof(U)}; - } -}; +template +constexpr Span span(std::initializer_list list) +{ + return Span{list.begin(), list.size()}; +} template -Span(T (&)[N]) -> Span; +constexpr Span span(T (&array)[N]) +{ + return Span{array, N}; +} template -Span(C & container) -> Span>; - -template -constexpr Span span(std::initializer_list list) +constexpr auto span(C & c) { - return Span{list.begin(), list.size()}; + return Span{data(c), size(c)}; } template -constexpr Span span(T (&array)[N]) +constexpr Span view(T (&array)[N]) { - return Span{array, N}; + return span(array); } -template -constexpr auto span(C & c) +template +constexpr auto view(R & range) -> decltype(range.view()) { - return Span{data(c), size(c)}; + return range.view(); } constexpr Span operator""_str(char const * lit, usize n) @@ -1643,11 +1438,36 @@ constexpr usize find_clear_bit(Span s) return impl_find_clear_bit(s); } +template +struct BitSpanIter +{ + Span repr_{}; + usize bit_pos_ = 0; + usize bit_size_ = 0; + + constexpr bool operator*() const + { + return get_bit(repr_, bit_pos_); + } + + constexpr BitSpanIter & operator++() + { + ++bit_pos_; + return *this; + } + + constexpr bool operator!=(IterEnd) const + { + return bit_pos_ != bit_size_; + } +}; + template struct BitSpan { using Type = bool; using Repr = R; + using Iter = BitSpanIter; Span repr_ = {}; usize bit_size_ = 0; @@ -1690,6 +1510,16 @@ struct BitSpan return bit_size_ == 0; } + constexpr auto begin() const + { + return Iter{.repr_ = repr_, .bit_pos_ = 0, .bit_size_ = bit_size_}; + } + + constexpr auto end() const + { + return IterEnd{}; + } + constexpr bool has_trailing() const { return bit_size_ != (repr_.size_bytes() * 8); @@ -1705,7 +1535,7 @@ struct BitSpan return ash::get_bit(repr_, index); } - constexpr void set(usize index, bool value) const + constexpr void set(usize index, bool value) const requires (NonConst) { ash::assign_bit(repr_, index, value); } @@ -1715,17 +1545,17 @@ struct BitSpan return ash::get_bit(repr_, index); } - constexpr bool set_bit(usize index) const + constexpr bool set_bit(usize index) const requires (NonConst) { return ash::set_bit(repr_, index); } - constexpr bool clear_bit(usize index) const + constexpr bool clear_bit(usize index) const requires (NonConst) { return ash::clear_bit(repr_, index); } - constexpr void flip_bit(usize index) const + constexpr void flip_bit(usize index) const requires (NonConst) { ash::flip_bit(repr_, index); } @@ -1751,6 +1581,296 @@ struct BitSpan } }; +template +struct Array +{ + using Type = T; + using View = Span; + using ConstView = Span; + using Iter = SpanIter; + using ConstIter = SpanIter; + + static constexpr usize SIZE = N; + + T data_[SIZE]{}; + + static constexpr bool is_empty() + { + return false; + } + + constexpr T * data() + { + return data_; + } + + constexpr T const * data() const + { + return data_; + } + + static constexpr usize size() + { + return SIZE; + } + + static constexpr u32 size32() + { + return (u32) SIZE; + } + + static constexpr u64 size64() + { + return (u64) SIZE; + } + + static constexpr usize capacity() + { + return SIZE; + } + + static constexpr usize size_bytes() + { + return sizeof(T) * SIZE; + } + + constexpr T * begin() + { + return data_; + } + + constexpr T const * begin() const + { + return data_; + } + + constexpr T * end() + { + return data_ + SIZE; + } + + constexpr T const * end() const + { + return data_ + SIZE; + } + + constexpr T & first() + { + return get(0); + } + + constexpr T const & first() const + { + return get(0); + } + + constexpr T & last() + { + return get(SIZE - 1); + } + + constexpr T const & last() const + { + return get(SIZE - 1); + } + + constexpr T & get(usize index) + { + return data_[index]; + } + + constexpr T const & get(usize index) const + { + return data_[index]; + } + + template + constexpr void set(usize index, Args &&... args) + { + data_[index] = T{static_cast(args)...}; + } + + constexpr T & operator[](usize index) + { + return data_[index]; + } + + constexpr T const & operator[](usize index) const + { + return data_[index]; + } + + constexpr operator T *() + { + return data_; + } + + constexpr operator T const *() const + { + return data_; + } + + constexpr ConstView view() const + { + return ConstView{data(), size()}; + } + + constexpr View view() + { + return View{data(), size()}; + } +}; + +template +struct Array +{ + using Type = T; + using View = Span; + using ConstView = Span; + using Iter = SpanIter; + using ConstIter = SpanIter; + + static constexpr usize SIZE = 0; + + static constexpr bool is_empty() + { + return true; + } + + constexpr T * data() + { + return nullptr; + } + + constexpr T const * data() const + { + return nullptr; + } + + static constexpr usize size() + { + return SIZE; + } + + static constexpr u32 size32() + { + return (u32) SIZE; + } + + static constexpr u64 size64() + { + return (u64) SIZE; + } + + static constexpr usize capacity() + { + return SIZE; + } + + static constexpr usize size_bytes() + { + return sizeof(T) * SIZE; + } + + constexpr T * begin() + { + return nullptr; + } + + constexpr T const * begin() const + { + return nullptr; + } + + constexpr T * end() + { + return nullptr; + } + + constexpr T const * end() const + { + return nullptr; + } + + constexpr T & first() requires (SIZE > 1) + { + return get(0); + } + + constexpr T const & first() const requires (SIZE > 1) + { + return get(0); + } + + constexpr T & last() requires (SIZE > 1) + { + return get(SIZE - 1); + } + + constexpr T const & last() const requires (SIZE > 1) + { + return get(SIZE - 1); + } + + constexpr T & get(usize index) requires (SIZE > 1) + { + return data()[index]; + } + + constexpr T const & get(usize index) const requires (SIZE > 1) + { + return data()[index]; + } + + template + constexpr void set(usize index, Args &&... args) requires (SIZE > 1) + { + data()[index] = T{static_cast(args)...}; + } + + constexpr T & operator[](usize index) requires (SIZE > 1) + { + return data()[index]; + } + + constexpr T const & operator[](usize index) const + { + return data()[index]; + } + + constexpr operator T *() + { + return nullptr; + } + + constexpr operator T const *() const + { + return nullptr; + } + + constexpr ConstView view() const + { + return ConstView{data(), size()}; + } + + constexpr View view() + { + return View{data(), size()}; + } +}; + +template +struct IsTriviallyRelocatable> +{ + static constexpr bool value = TriviallyRelocatable; +}; + +template +using Bits = Repr[BIT_PACKS]; + +template +using BitArray = Array>; + template struct defer { @@ -1815,8 +1935,9 @@ struct Fn { using Thunk = R (*)(void *, Args...); - void * data = nullptr; - Thunk thunk = nullptr; + void * data = nullptr; + + Thunk thunk = nullptr; explicit constexpr Fn() = default; @@ -1923,7 +2044,7 @@ auto fn(R (*pfn)(Args...)) /// @brief make a function view from a functor reference. Functor should outlive /// the Fn -template +template auto fn(F & functor) { using Traits = FunctorTraits; @@ -2047,4 +2168,17 @@ struct Pin constexpr ~Pin() = default; }; +/// @brief uninitialized storage +template +struct InplaceStorage +{ + alignas(Alignment) mutable u8 storage_[Capacity]; +}; + +template +struct InplaceStorage +{ + static constexpr u8 * storage_ = nullptr; +}; + } // namespace ash diff --git a/ashura/std/v.gen.h b/ashura/std/v.gen.h index 0fcd49bb4..19467fea9 100644 --- a/ashura/std/v.gen.h +++ b/ashura/std/v.gen.h @@ -18,22 +18,22 @@ struct V } }; -constexpr V<0> v0; -constexpr V<1> v1; -constexpr V<2> v2; -constexpr V<3> v3; -constexpr V<4> v4; -constexpr V<5> v5; -constexpr V<6> v6; -constexpr V<7> v7; -constexpr V<8> v8; -constexpr V<9> v9; -constexpr V<10> v10; -constexpr V<11> v11; -constexpr V<12> v12; -constexpr V<13> v13; -constexpr V<14> v14; -constexpr V<15> v15; +inline constexpr V<0> v0; +inline constexpr V<1> v1; +inline constexpr V<2> v2; +inline constexpr V<3> v3; +inline constexpr V<4> v4; +inline constexpr V<5> v5; +inline constexpr V<6> v6; +inline constexpr V<7> v7; +inline constexpr V<8> v8; +inline constexpr V<9> v9; +inline constexpr V<10> v10; +inline constexpr V<11> v11; +inline constexpr V<12> v12; +inline constexpr V<13> v13; +inline constexpr V<14> v14; +inline constexpr V<15> v15; } // namespace ash diff --git a/ashura/std/v.py b/ashura/std/v.py index c262de72f..eb4f85847 100644 --- a/ashura/std/v.py +++ b/ashura/std/v.py @@ -32,7 +32,7 @@ def out(code): return file.write(code) """) -value_defs = [f"constexpr V<{i}> v{i};" for i in range(MAX_SIZE)] +value_defs = [f"inline constexpr V<{i}> v{i};" for i in range(MAX_SIZE)] out("\n".join(value_defs)) diff --git a/ashura/std/vec.h b/ashura/std/vec.h index 7af5e4ec3..ba2c96239 100644 --- a/ashura/std/vec.h +++ b/ashura/std/vec.h @@ -17,6 +17,8 @@ struct [[nodiscard]] Vec { using Type = T; using Repr = T; + using Iter = SpanIter; + using View = Span; T * storage_ = nullptr; usize size_ = 0; @@ -142,14 +144,14 @@ struct [[nodiscard]] Vec return capacity_; } - constexpr T * begin() const + constexpr auto begin() const { - return data(); + return Iter{.iter_ = data(), .end_ = data() + size_}; } - constexpr T * end() const + constexpr auto end() const { - return data() + size_; + return IterEnd{}; } constexpr T & first() const @@ -402,7 +404,7 @@ struct [[nodiscard]] Vec } else { - obj::copy_assign(span, data() + pos); + obj::copy_construct(span, data() + pos); } return Ok{}; @@ -423,7 +425,7 @@ struct [[nodiscard]] Vec } else { - obj::move_assign(span, data() + pos); + obj::move_construct(span, data() + pos); } return Ok{}; @@ -441,7 +443,7 @@ struct [[nodiscard]] Vec return Ok{}; } - constexpr Result<> extend_defaulted(usize extension) + constexpr Result<> extend(usize extension) { usize const pos = size_; @@ -472,7 +474,7 @@ struct [[nodiscard]] Vec } else { - obj::copy_assign(span, data() + pos); + obj::copy_construct(span, data() + pos); } return Ok{}; @@ -494,7 +496,7 @@ struct [[nodiscard]] Vec } else { - obj::move_assign(span, data() + pos); + obj::move_construct(span, data() + pos); } return Ok{}; @@ -516,7 +518,7 @@ struct [[nodiscard]] Vec return extend_uninit(new_size - size_); } - constexpr Result<> resize_defaulted(usize new_size) + constexpr Result<> resize(usize new_size) { if (new_size <= size_) { @@ -524,36 +526,15 @@ struct [[nodiscard]] Vec return Ok{}; } - return extend_defaulted(new_size - size_); + return extend(new_size - size_); } - constexpr Span span() const + constexpr View view() const { - return Span{data(), size()}; + return View{data(), size()}; } }; -template -constexpr Result> vec(usize capacity, AllocatorImpl allocator = {}) -{ - return Vec::make(capacity, allocator); -} - -template -constexpr Result> vec(T (&data)[N], AllocatorImpl allocator = {}) -{ - Result out = Vec::make(N, allocator); - - if (!out) - { - return out; - } - - out.value().extend(data).unwrap(); - - return out; -} - template constexpr Result> vec(Span data, AllocatorImpl allocator = {}) { @@ -569,21 +550,6 @@ constexpr Result> vec(Span data, AllocatorImpl allocator = {}) return out; } -template -constexpr Result> vec_move(T (&&data)[N], AllocatorImpl allocator = {}) -{ - Result out = Vec::make(N, allocator); - - if (!out) - { - return out; - } - - out.value().extend_move(data).unwrap(); - - return out; -} - template constexpr Result> vec_move(Span data, AllocatorImpl allocator = {}) { @@ -608,6 +574,11 @@ template requires (NonConst) struct [[nodiscard]] PinVec { + using Type = T; + using Repr = T; + using Iter = SpanIter; + using View = Span; + T * storage_; usize size_; usize capacity_; @@ -702,7 +673,7 @@ struct [[nodiscard]] PinVec return out; } - obj::copy_construct(span(), out.value().span()); + obj::copy_construct(view(), out.value().view()); return out; } @@ -747,14 +718,14 @@ struct [[nodiscard]] PinVec return capacity_; } - constexpr T * begin() const + constexpr auto begin() const { - return data(); + return Iter{.iter_ = data(), .end_ = data() + size_}; } - constexpr T * end() const + constexpr auto end() const { - return data() + size_; + return IterEnd{}; } constexpr T & first() const @@ -829,7 +800,7 @@ struct [[nodiscard]] PinVec return Ok{}; } - constexpr Result<> extend_defaulted(usize extension) + constexpr Result<> extend(usize extension) { usize const pos = size_; @@ -860,7 +831,7 @@ struct [[nodiscard]] PinVec } else { - obj::copy_assign(span, data() + pos); + obj::copy_construct(span, data() + pos); } return Ok{}; @@ -882,31 +853,26 @@ struct [[nodiscard]] PinVec } else { - obj::move_assign(span, data() + pos); + obj::move_construct(span, data() + pos); } return Ok{}; } - constexpr Span span() const + constexpr View view() const { - return Span{data(), size()}; + return View{data(), size()}; } }; -template -constexpr Result> pin_vec(usize capacity, - AllocatorImpl allocator = {}) -{ - return PinVec::make(capacity, allocator); -} - template requires (NonConst) struct [[nodiscard]] BitVec { using Type = bool; using Repr = R; + using Iter = BitSpanIter; + using View = BitSpan; Vec repr_ = {}; usize bit_size_ = 0; @@ -963,6 +929,16 @@ struct [[nodiscard]] BitVec return bit_size_ == 0; } + constexpr auto begin() const + { + return Iter{.repr_ = repr_, .bit_pos_ = 0, .bit_size_ = bit_size_}; + } + + constexpr auto end() const + { + return IterEnd{}; + } + constexpr bool has_trailing() const { return bit_size_ != (repr_.size_ * sizeof(R) * 8); @@ -1007,12 +983,12 @@ struct [[nodiscard]] BitVec constexpr bool get(usize index) const { - return ash::get_bit(repr_.span(), index); + return ash::get_bit(repr_.view(), index); } constexpr void set(usize index, bool value) const { - ash::assign_bit(repr_.span(), index, value); + ash::assign_bit(repr_.view(), index, value); } constexpr bool get_bit(usize index) const @@ -1022,17 +998,17 @@ struct [[nodiscard]] BitVec constexpr bool set_bit(usize index) const { - return ash::set_bit(repr_.span(), index); + return ash::set_bit(repr_.view(), index); } constexpr bool clear_bit(usize index) const { - return ash::clear_bit(repr_.span(), index); + return ash::clear_bit(repr_.view(), index); } constexpr void flip_bit(usize index) const { - ash::flip_bit(repr_.span(), index); + ash::flip_bit(repr_.view(), index); } constexpr Result<> reserve(usize target_capacity) @@ -1106,7 +1082,7 @@ struct [[nodiscard]] BitVec { slice = slice(bit_size_); for (usize dst = slice.begin(), src = slice.end(); src != bit_size_; - dst++, src++) + ++dst, ++src) { set(dst, get(src)); } @@ -1126,7 +1102,7 @@ struct [[nodiscard]] BitVec return Ok{}; } - constexpr Result<> extend_defaulted(usize extension) + constexpr Result<> extend(usize extension) { usize const pos = bit_size_; @@ -1154,7 +1130,7 @@ struct [[nodiscard]] BitVec return extend_uninit(new_size - bit_size_); } - constexpr Result<> resize_defaulted(usize new_size) + constexpr Result<> resize(usize new_size) { if (new_size <= bit_size_) { @@ -1162,7 +1138,7 @@ struct [[nodiscard]] BitVec return Ok{}; } - return extend_defaulted(new_size - bit_size_); + return extend(new_size - bit_size_); } constexpr void swap(usize a, usize b) const @@ -1173,23 +1149,23 @@ struct [[nodiscard]] BitVec set(b, av); } - constexpr BitSpan span() const + constexpr auto view() const { - return BitSpan{repr_, bit_size_}; + return View{repr_, bit_size_}; } }; template -requires (NonConst && C > 0) -struct [[nodiscard]] InplaceVec +requires (NonConst) +struct [[nodiscard]] InplaceVec : InplaceStorage { using Type = T; using Repr = T; + using Iter = SpanIter; + using View = Span; static constexpr usize Capacity = C; - // uninitialized storage - alignas(T) u8 storage_[C * sizeof(T)]; usize size_ = 0; constexpr InplaceVec() = default; @@ -1239,14 +1215,9 @@ struct [[nodiscard]] InplaceVec return size_ == 0; } - constexpr T * data() - { - return reinterpret_cast(storage_); - } - - constexpr T const * data() const + constexpr T * data() const { - return reinterpret_cast(storage_); + return reinterpret_cast(this->storage_); } constexpr usize size() const @@ -1274,77 +1245,37 @@ struct [[nodiscard]] InplaceVec return Capacity; } - constexpr T * begin() - { - return data(); - } - - constexpr T const * begin() const + constexpr auto begin() const { - return data(); + return Iter{.iter_ = data(), .end_ = data() + size_}; } - constexpr T * end() + constexpr auto end() const { - return data() + size_; + return IterEnd{}; } - constexpr T const * end() const - { - return data() + size_; - } - - constexpr T & first() - { - return get(0); - } - - constexpr T const & first() const + constexpr T & first() const { return get(0); } - constexpr T & last() - { - return get(size_ - 1); - } - - constexpr T const & last() const + constexpr T & last() const { return get(size_ - 1); } - constexpr T & operator[](usize index) - { - return get(index); - } - - constexpr T const & operator[](usize index) const + constexpr T & operator[](usize index) const { return get(index); } - constexpr T & get(usize index) - { - return data()[index]; - } - - constexpr T const & get(usize index) const + constexpr T & get(usize index) const { return data()[index]; } - constexpr T * try_get(usize index) - { - if (index >= size_) [[unlikely]] - { - return nullptr; - } - - return data() + index; - } - - constexpr T const * try_get(usize index) const + constexpr T * try_get(usize index) const { if (index >= size_) [[unlikely]] { @@ -1355,7 +1286,7 @@ struct [[nodiscard]] InplaceVec } template - constexpr void set(usize index, Args &&... args) + constexpr void set(usize index, Args &&... args) const { data()[index] = T{static_cast(args)...}; } @@ -1501,7 +1432,7 @@ struct [[nodiscard]] InplaceVec } else { - obj::copy_assign(span, data() + pos); + obj::copy_construct(span, data() + pos); } return Ok{}; @@ -1523,7 +1454,7 @@ struct [[nodiscard]] InplaceVec } else { - obj::move_assign(span, data() + pos); + obj::move_construct(span, data() + pos); } return Ok{}; @@ -1541,7 +1472,7 @@ struct [[nodiscard]] InplaceVec return Ok{}; } - constexpr Result<> extend_defaulted(usize extension) + constexpr Result<> extend(usize extension) { usize const pos = size_; @@ -1571,7 +1502,7 @@ struct [[nodiscard]] InplaceVec } else { - obj::copy_assign(span, data() + pos); + obj::move_construct(span, data() + pos); } return Ok{}; @@ -1593,7 +1524,7 @@ struct [[nodiscard]] InplaceVec } else { - obj::move_assign(span, data() + pos); + obj::move_construct(span, data() + pos); } return Ok{}; @@ -1615,7 +1546,7 @@ struct [[nodiscard]] InplaceVec return extend_uninit(new_size - size_); } - constexpr Result<> resize_defaulted(usize new_size) + constexpr Result<> resize(usize new_size) { if (new_size <= size_) { @@ -1623,17 +1554,12 @@ struct [[nodiscard]] InplaceVec return Ok{}; } - return extend_defaulted(new_size - size_); - } - - constexpr Span span() - { - return Span{data(), size()}; + return extend(new_size - size_); } - constexpr Span span() const + constexpr auto view() const { - return Span{data(), size()}; + return View{data(), size()}; } }; @@ -1669,6 +1595,53 @@ struct SparseVec using Id = u64; using Ids = Vec; + struct Iter + { + Tuple iters_; + + constexpr auto operator*() const + { + return apply( + [](auto &... iters) { return Tuple{*iters...}; }, + iters_); + } + + constexpr Iter & operator++() + { + apply([](auto &... iters) { (++iters, ...); }, iters_); + return *this; + } + + constexpr bool operator!=(IterEnd) const + { + return apply( + [](auto &... iters) { + bool const proceed = (sizeof...(iters) != 0); + return (proceed && ... && (iters != IterEnd{})); + }, + iters_); + } + }; + + struct View + { + Tuple views_; + + constexpr auto begin() const + { + return apply( + [](auto &&... views) { + return Tuple{ash::begin(views)...}; + }, + views_); + } + + constexpr auto end() const + { + return IterEnd{}; + } + }; + Ids index_to_id = {}; Ids id_to_index = {}; Dense dense = {}; @@ -1733,6 +1706,27 @@ struct SparseVec return static_cast(index_to_id.size()); } + constexpr auto begin() const + { + return Iter{.iters_ = apply( + [](auto &... vecs) { + return Tuple{ + ash::begin(vecs)...}; + }, + dense)}; + } + + constexpr auto end() const + { + return IterEnd{}; + } + + constexpr auto view() const + { + return apply([](auto &... dense) { return View{ash::view(dense)...}; }, + dense); + } + constexpr void clear() { apply([](auto &... d) { (d.clear(), ...); }, dense); @@ -1766,9 +1760,14 @@ struct SparseVec return index < size(); } - constexpr u64 operator[](u64 id) const + constexpr auto operator[](u64 id) const { - return id_to_index[id]; + u64 const index = id_to_index[id]; + return apply( + [index](auto &... dense) { + return Tuple{dense[index]...}; + }, + dense); } constexpr u64 to_index(u64 id) const @@ -1900,26 +1899,14 @@ struct SparseVec } } - template - struct Pusher - { - template - static constexpr void push(Tuple & t, Head && head, Tail &&... tail) - { - get(t).push(static_cast(head)).unwrap(); - if constexpr (sizeof...(tail) != 0) - { - Pusher::push(t, static_cast(tail)...); - } - } - }; - template + requires (sizeof...(Args) == sizeof...(V)) constexpr Result push(Args &&... args) - requires (sizeof...(Args) == sizeof...(V)) { u64 const index = size(); + // grow here so we can handle all memory allocation + // failures at once. the proceeding unwrap calls will not fail if (!grow(size() + 1)) [[unlikely]] { return Err{}; @@ -1937,7 +1924,12 @@ struct SparseVec return Err{}; } - Pusher<0>::push(dense, static_cast(args)...); + Tuple args_tuple{static_cast(args)...}; + + index_apply([&]() { + (get(dense).push(get(args_tuple)).unwrap(), ...); + }); + return id; } }; @@ -1976,20 +1968,20 @@ namespace fmt { inline bool push(Context const & ctx, Spec const & spec, Vec const & str) { - return push(ctx, spec, str.span()); + return push(ctx, spec, str.view()); } inline bool push(Context const & ctx, Spec const & spec, PinVec const & str) { - return push(ctx, spec, str.span()); + return push(ctx, spec, str.view()); } template inline bool push(Context const & ctx, Spec const & spec, InplaceVec const & str) { - return push(ctx, spec, str.span()); + return push(ctx, spec, str.view()); } } // namespace fmt