diff --git a/.bazelrc b/.bazelrc index d16d3bb8..0c1b43a2 100644 --- a/.bazelrc +++ b/.bazelrc @@ -20,7 +20,7 @@ common:tidy_format_error --aspects_parameters=enable_error=True # Winlibs common:winlibs-gcc --extra_toolchains=@winlibs//:gcc-toolchain -common:winlibs-clang --extra_toolchains=@pthread-winlibs//:clang-toolchain +common:winlibs-clang --extra_toolchains=@winlibs//:clang-toolchain # BuildBuddy common:linux --workspace_status_command=$(pwd)/.buildbuddy/workspace_status.sh diff --git a/.buildkite/linux_amd64.yml b/.buildkite/linux_amd64.yml index d22b09cd..a3563f8b 100644 --- a/.buildkite/linux_amd64.yml +++ b/.buildkite/linux_amd64.yml @@ -4,10 +4,10 @@ agents: steps: - label: ":bazel: Build and Test on gcc (W asan)" commands: - - CC=gcc bazelisk build --features=asan //:StreamFormatTests - - CC=gcc bazelisk test --features=asan //:StreamFormatTests + - CC=gcc bazelisk build --features=asan //tests:units + - CC=gcc bazelisk test --features=asan //tests:units - label: ":bazel: Build and Test on Clang (W asan)" commands: - - CC=clang bazelisk build --features=asan //:StreamFormatTests - - CC=clang bazelisk test --features=asan //:StreamFormatTests + - CC=clang-20 bazelisk build --features=asan //tests:units + - CC=clang-20 bazelisk test --features=asan //tests:units diff --git a/.buildkite/template.yml b/.buildkite/template.yml index f9554e65..93406276 100644 --- a/.buildkite/template.yml +++ b/.buildkite/template.yml @@ -1,4 +1,4 @@ -name: "StreamFormat" +name: "stream" steps: - label: ":pipeline: Launch Embbeded Pipeline" command: "buildkite-agent pipeline upload .builkite/pipeline.yml" diff --git a/.buildkite/windows_amd64.yml b/.buildkite/windows_amd64.yml index 00e4841b..71f111bf 100644 --- a/.buildkite/windows_amd64.yml +++ b/.buildkite/windows_amd64.yml @@ -2,13 +2,9 @@ agents: queue: "agent-runners-windows-amd64" steps: - - label: ":bazel: Build And Test MSVC" - commands: - - bazelisk test //:StreamFormatTests - - label: ":bazel: Build And Test Winlibs/clang" commands: - - bazelisk build --config=winlibs-clang //:StreamFormatTests + - bazelisk build --config=winlibs-clang //tests:units - label: ":bazel: Build And Test Winlibs/gcc" commands: - - bazelisk build --config=winlibs-gcc //:StreamFormatTests + - bazelisk build --config=winlibs-gcc //tests:units diff --git a/.github/workflows/CodeChecker.yml.nop b/.github/workflows/CodeChecker.yml.nop deleted file mode 100644 index 2c679d7d..00000000 --- a/.github/workflows/CodeChecker.yml.nop +++ /dev/null @@ -1,37 +0,0 @@ -name: CodeChecker - -on: - push: - branches: - - '**' - pull_request: - branches: - - '**' - -jobs: - codechecker-ubuntu-latest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: bazelbuild/setup-bazelisk@v3 - - name: Mount bazel cache - uses: actions/cache@v4 - with: - path: "~/.cache/bazel" - key: bazel - - - name: build & retreive compile_commands.json - run: | - bazelisk clean - bazelisk build //:StreamFormatTests - bazelisk run //conf:compile_commands - - - uses: whisperity/CodeChecker-Action@v1.0.4 - id: codechecker - with: - logfile: ${{ github.workspace }}/compile_commands.json - - - uses: actions/upload-artifact@v4 - with: - name: "CodeChecker Bug Reports" - path: ${{ steps.codechecker.outputs.result-html-dir }} diff --git a/.github/workflows/StreamFormat.yml b/.github/workflows/StreamFormat.yml deleted file mode 100644 index 715a01ae..00000000 --- a/.github/workflows/StreamFormat.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: StreamFormat - -on: - push: - branches: - - '**' - pull_request: - branches: - - '**' - -jobs: - windows-latest-msvc: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: bazelbuild/setup-bazelisk@v3 - - name: Mount bazel cache - uses: actions/cache@v4 - with: - path: "~/.cache/bazel" - key: bazel - - name: Building... - run: bazelisk build //:StreamFormatTests - - name: Testing... - run: bazelisk test //:StreamFormatTests - - windows-latest-winlibs: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: bazelbuild/setup-bazelisk@v3 - - name: Mount bazel cache - uses: actions/cache@v4 - with: - path: "~/.cache/bazel" - key: bazel - - name: Build Winlibs/clang... - run: bazelisk build --config=winlibs-clang //:StreamFormatTests - - name: Build Winlibs/gcc... - run: bazelisk build --config=winlibs-gcc //:StreamFormatTests - - ubuntu-latest-gcc: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: bazelbuild/setup-bazelisk@v3 - - name: Mount bazel cache - uses: actions/cache@v4 - with: - path: "~/.cache/bazel" - key: bazel - - name: Version - run: gcc --version - - name: Building... - run: CC=gcc bazelisk build //:StreamFormatTests - - name: Testing... (W asan) - run: CC=gcc bazelisk test --features=asan //:StreamFormatTests - - ubuntu-latest-clang: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: bazelbuild/setup-bazelisk@v3 - - name: Mount bazel cache - uses: actions/cache@v4 - with: - path: "~/.cache/bazel" - key: bazel - - name: Install clang - run: | - wget https://apt.llvm.org/llvm.sh - chmod +x ./llvm.sh - sudo ./llvm.sh 17 - - name: Version - run: clang++-17 --version - - name: Building... - run: CC=clang++-17 bazelisk build //:StreamFormatTests - - name: Testing... (W asan) - run: CC=clang++-17 bazelisk test --features=asan //:StreamFormatTests diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 00000000..78c922df --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,37 @@ +name: linter + +on: + push: + branches: + - '**' + +jobs: + clang-format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install clang-format... + run: sudo apt install clang-format + - name: Version + run: clang-format --version + - run: ./conf/scripts/clang-format.py + + clang-tidy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - uses: bazelbuild/setup-bazelisk@v3 + - uses: actions/cache@v4 + with: + path: "~/.cache/bazel" + key: bazel + - name: Install clang-tidy... + run: sudo apt install clang-tidy + - name: Version + run: clang-tidy --version + - name: Running clang-tidy... + run: ./scripts/clang-tidy.sh diff --git a/.github/workflows/tests_linux.yml b/.github/workflows/tests_linux.yml new file mode 100644 index 00000000..0f13c96b --- /dev/null +++ b/.github/workflows/tests_linux.yml @@ -0,0 +1,48 @@ +name: Tests Linux + +on: + push: + branches: + - '**' + +jobs: + ubuntu-latest-gcc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: bazelbuild/setup-bazelisk@v3 + - uses: actions/cache@v4 + with: + path: "~/.cache/bazel" + key: bazel + - name: Version + run: gcc --version + - name: Building... + run: CC=gcc bazelisk build //tests:units + - name: Testing (asan)... + run: CC=gcc bazelisk test //tests:units + - name: Testing (asan)... + run: CC=gcc bazelisk test --features=asan //tests:units + + ubuntu-latest-clang: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: bazelbuild/setup-bazelisk@v3 + - uses: actions/cache@v4 + with: + path: "~/.cache/bazel" + key: bazel + - name: Install clang + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x ./llvm.sh + sudo ./llvm.sh 20 + - name: Version + run: clang --version + - name: Building... + run: CC=clang++-20 bazelisk build //tests:units + - name: Testing... + run: CC=clang++-20 bazelisk test //tests:units + - name: Testing (asan)... + run: CC=clang++-20 bazelisk test --features=asan //tests:units diff --git a/.github/workflows/tests_windows.yml b/.github/workflows/tests_windows.yml new file mode 100644 index 00000000..48fbcdf1 --- /dev/null +++ b/.github/workflows/tests_windows.yml @@ -0,0 +1,35 @@ +name: Tests Windows + +on: + push: + branches: + - '**' + +jobs: + windows-latest-msvc: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: bazelbuild/setup-bazelisk@v3 + - uses: actions/cache@v4 + with: + path: "~/.cache/bazel" + key: bazel + - name: Building... + run: bazelisk build //tests:units + - name: Testing... + run: bazelisk test //tests:units + + windows-latest-winlibs: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: bazelbuild/setup-bazelisk@v3 + - uses: actions/cache@v4 + with: + path: "~/.cache/bazel" + key: bazel + - name: Build winlibs/clang... + run: bazelisk build --config=winlibs-clang //tests:units + - name: Build winlibs/gcc... + run: bazelisk build --config=winlibs-gcc //tests:units diff --git a/.gitignore b/.gitignore index 60a935ff..431b3530 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,11 @@ # bazel -MODULE.bazel.lock -bazel-bin -bazel-out -bazel-streamformat -bazel-StreamFormat -bazel-examples -bazel-Examples -bazel-testlogs +*.lock +bazel-* + +.coverage +.codechecker +compile_commands.json # VS .vs diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..e5cd7320 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "conf"] + path = conf + url = git@github.com:0-Sacha/conf.git diff --git a/BUILD.bazel b/BUILD.bazel index 2d3733d6..6fd2d7ba 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -3,27 +3,16 @@ load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") cc_library( - name = "StreamFormat", - srcs = glob([ "src/**/*.h", "src/**/*.cpp" ]), - hdrs = glob([ "src/**/*.h" ]), + name = "stream", + srcs = glob([ "src/**/*.cxx" ]), + hdrs = glob([ "src/**/*.hxx" ]), includes = [ "src/" ], copts = select({ - "@rules_cc//cc/compiler:msvc-cl": ["/std:c++20"], + "@rules_cc//cc/compiler:msvc-cl": ["/std:c++latest"], "//conditions:default": ["-std=c++20"], }), strip_include_prefix = "src", - include_prefix = "StreamFormat", + include_prefix = "stream", linkstatic = True, visibility = ["//visibility:public"], ) - -cc_test( - name = "StreamFormatTests", - srcs = glob([ "Tests/**/*.h", "Tests/**/*.cpp" ]), - copts = select({ - "@rules_cc//cc/compiler:msvc-cl": ["/std:c++20"], - "//conditions:default": ["-std=c++20"], - }), - deps = [ ":StreamFormat" ], - visibility = ["//visibility:public"], -) diff --git a/Examples/CompilerInfo/BUILD.bazel b/Examples/CompilerInfo/BUILD.bazel deleted file mode 100644 index 13f19c6d..00000000 --- a/Examples/CompilerInfo/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -"" - -load("@rules_cc//cc:defs.bzl", "cc_binary") - -cc_binary( - name = "CompilerInfo", - srcs = glob([ "*.h", "*.cpp" ]), - includes = [ "" ], - copts = select({ - "@rules_cc//cc/compiler:msvc-cl": ["/std:c++20"], - "//conditions:default": ["-std=c++20"], - }), - deps = [ "@streamformat//:StreamFormat" ], - visibility = ["//visibility:public"], -) diff --git a/Examples/CompilerInfo/main.cpp b/Examples/CompilerInfo/main.cpp deleted file mode 100644 index 5eab2cff..00000000 --- a/Examples/CompilerInfo/main.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "StreamFormat/FLog.h" -#include "StreamFormat/FLog/DefaultLogger.h" - -#define COMPILER "Not Detected !" -#if defined(STREAMFORMAT_COMPILER_CLANG) - #undef COMPILER - #define COMPILER "clang" -#elif defined(STREAMFORMAT_COMPILER_GCC) - #undef COMPILER - #define COMPILER "gcc" -#elif defined(STREAMFORMAT_COMPILER_MSVC) - #undef COMPILER - #define COMPILER "msvc" -#endif - -#define MODE "RELEASE" -#ifdef STREAMFORMAT_DEBUG - #undef MODE - #define MODE "DEBUG" -#endif - -int main() -{ - StreamFormat::FLog::DefaultLogger::Core().Info("COMPILER : {}", COMPILER); - StreamFormat::FLog::DefaultLogger::Core().Info("MODE : {}", MODE); -} diff --git a/Examples/HelloWorld/BUILD.bazel b/Examples/HelloWorld/BUILD.bazel deleted file mode 100644 index a95eb0d8..00000000 --- a/Examples/HelloWorld/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -"" - -load("@rules_cc//cc:defs.bzl", "cc_binary") - -cc_binary( - name = "HelloWorld", - srcs = glob([ "*.h", "*.cpp" ]), - includes = [ "" ], - copts = select({ - "@rules_cc//cc/compiler:msvc-cl": ["/std:c++20"], - "//conditions:default": ["-std=c++20"], - }), - deps = [ "@streamformat//:StreamFormat" ], - visibility = ["//visibility:public"], -) diff --git a/Examples/HelloWorld/main.cpp b/Examples/HelloWorld/main.cpp deleted file mode 100644 index e7b9c592..00000000 --- a/Examples/HelloWorld/main.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "StreamFormat/FLog.h" -#include "StreamFormat/FLog/DefaultLogger.h" - -#include - -int main() -{ - StreamFormat::FLog::DefaultLogger::Core().Info("HelloWorld !"); - - using namespace std::chrono_literals; - std::this_thread::sleep_for(100ms); - - StreamFormat::FLog::DefaultLogger::Core().Warn("After 100ms !"); -} diff --git a/Examples/MODULE.bazel b/Examples/MODULE.bazel deleted file mode 100644 index 53473ca6..00000000 --- a/Examples/MODULE.bazel +++ /dev/null @@ -1,26 +0,0 @@ -"" - -# buildifier: disable=module-docstring -module( - name = "streamformat_examples", - version = "0.1", -) - - -git_override(module_name="bazel_utilities", remote="https://github.com/0-Sacha/bazel_utilities.git", commit="7f6c3585c41278918428ed48d45b12413c197fc0") -git_override(module_name="bazel_buildbuddy", remote="https://github.com/0-Sacha/bazel_buildbuddy.git", commit="b60314cac7826edb87efe285b032b877ad725f84") -git_override(module_name="bazel_winlibs", remote="https://github.com/0-Sacha/bazel_winlibs.git", commit="e2cc97b61cb9115fbc2b7169dc9d1cb36b351935") -local_path_override(module_name = "streamformat", path = "../") - -bazel_dep(name = "rules_cc", version = "0.0.10") -bazel_dep(name = "platforms", version = "0.0.10") -bazel_dep(name = "bazel_utilities", version = "0.0.1") -bazel_dep(name = "bazel_winlibs", version = "0.0.1") -bazel_dep(name = "streamformat") - -winlibs_toolchain_extension = use_extension("@bazel_winlibs//:rules.bzl", "winlibs_toolchain_extension") -inject_repo(winlibs_toolchain_extension, "platforms", "bazel_utilities") -winlibs_toolchain_extension.winlibs_toolchain(name = "ex_winlibs") -winlibs_toolchain_extension.winlibs_toolchain(name = "pthread-ex_winlibs", linklibs = [ "pthread" ]) -use_repo(winlibs_toolchain_extension, "ex_winlibs") -use_repo(winlibs_toolchain_extension, "pthread-ex_winlibs") \ No newline at end of file diff --git a/Examples/README.md b/Examples/README.md deleted file mode 100644 index 017bf429..00000000 --- a/Examples/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Example of StreamFormat - -### Try thoses examples ! - -##### Build and Run examples one by one (Recommended) -Example with `//HelloWorld:HelloWorld` (see below for the list of example) -``` -bazelisk run //HelloWorld:HelloWorld - -[00:00:00:000] APP-Core >> HelloWorld ! -[00:00:00:105] APP-Core >> After 100ms ! -``` - -##### Compile all examples, then run binaries -To compile every example: -``` -bazelisk build //... -``` - -Then you can run a program with (example with `//HelloWorld:HelloWorld`, see below for the list of example) -``` -.\bazel-bin\HelloWorld\HelloWorld - -[00:00:00:000] APP-Core >> HelloWorld ! -[00:00:00:105] APP-Core >> After 100ms ! -``` - -### List Of Examples - -- `//HelloWorld:HelloWorld`: HelloWorld using the Internal Logger diff --git a/MODULE.bazel b/MODULE.bazel index 25f5dbb0..443d565e 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,38 +1,40 @@ -"" - -# buildifier: disable=module-docstring -module( - name = "streamformat", - version = "0.1", -) - -git_override(module_name="bazel_utilities", remote="https://github.com/0-Sacha/bazel_utilities.git", commit="aa399bb2599e2cd64a35a2275ce0f73a539524a5") -git_override(module_name="bazel_buildbuddy", remote="https://github.com/0-Sacha/bazel_buildbuddy.git", commit="b96ebe6a8dbe7a6c82bd91d6e0cb79e53f11fa8f") -git_override(module_name="bazel_winlibs", remote="https://github.com/0-Sacha/bazel_winlibs.git", commit="0f9fcc1b821b48e0bfa216f876a1df2a27b0522f") - -bazel_dep(name = "rules_cc", version = "0.0.10") -bazel_dep(name = "platforms", version = "0.0.10") -bazel_dep(name = "bazel_utilities", version = "0.0.1") -bazel_dep(name = "bazel_buildbuddy", version = "0.0.1") -bazel_dep(name = "bazel_winlibs", version = "0.0.1") - -bazel_dep(name = "hedron_compile_commands", dev_dependency = True) -git_override( - module_name = "hedron_compile_commands", - remote = "https://github.com/hedronvision/bazel-compile-commands-extractor.git", - commit = "1e08f8e0507b6b6b1f4416a9a22cf5c28beaba93", -) - -winlibs_toolchain_extension = use_extension("@bazel_winlibs//:rules.bzl", "winlibs_toolchain_extension") -inject_repo(winlibs_toolchain_extension, "platforms", "bazel_utilities") -winlibs_toolchain_extension.winlibs_toolchain(name = "winlibs") -winlibs_toolchain_extension.winlibs_toolchain(name = "pthread-winlibs", linklibs = [ "pthread" ]) -use_repo(winlibs_toolchain_extension, "winlibs") -use_repo(winlibs_toolchain_extension, "pthread-winlibs") -# register_toolchains("@winlibs//:clang-toolchain") - -buildbuddy_toolchain_extension = use_extension("@bazel_buildbuddy//:rules.bzl", "buildbuddy_toolchain_extension") -inject_repo(buildbuddy_toolchain_extension, "platforms", "bazel_utilities") -buildbuddy_toolchain_extension.buildbuddy_toolchain(name = "buildbuddy") -use_repo(buildbuddy_toolchain_extension, "buildbuddy") -# register_toolchains("@buildbuddy//:gcc-toolchain") +"" + +# buildifier: disable=module-docstring +module( + name = "streamformat", + version = "0.1", +) + +# libs-deps +# +bazel_dep(name = "platforms", version = "0.0.11") +bazel_dep(name = "rules_cc", version = "0.0.17") + +# toolchains-deps +git_override(module_name="bazel_utilities", remote="https://github.com/0-Sacha/bazel_utilities.git", commit="1c3c6c01dcccc6c922c4955c92aa7c3c015a9d1c") +git_override(module_name="bazel_buildbuddy", remote="https://github.com/0-Sacha/bazel_buildbuddy.git", commit="cbcefed87e2baf56a6f74ad3e0613ce8ab0fdcf3") +git_override(module_name="bazel_winlibs", remote="https://github.com/0-Sacha/bazel_winlibs.git", commit="8c6a667fcb08c1b479db28562fa724c7f666504c") +# +bazel_dep(name = "bazel_utilities", version = "0.0.1", dev_dependency = True) +bazel_dep(name = "bazel_buildbuddy", version = "0.0.1", dev_dependency = True) +bazel_dep(name = "bazel_winlibs", version = "0.0.1", dev_dependency = True) + +# tools-deps +git_override(module_name = "hedron_compile_commands", remote = "https://github.com/hedronvision/bazel-compile-commands-extractor.git", commit = "1e08f8e0507b6b6b1f4416a9a22cf5c28beaba93") +# +bazel_dep(name = "hedron_compile_commands", dev_dependency = True) + +# toolchains +winlibs_toolchain_extension = use_extension("@bazel_winlibs//:rules.bzl", "winlibs_toolchain_extension", dev_dependency = True) +inject_repo(winlibs_toolchain_extension, "platforms", "bazel_utilities") +winlibs_toolchain_extension.winlibs_toolchain(name = "winlibs", dbg_copts = [ "-g3", "-O0" ]) +use_repo(winlibs_toolchain_extension, "winlibs") +# register_toolchains("@winlibs//:gcc-toolchain") +# register_toolchains("@winlibs//:clang-toolchain") + +buildbuddy_toolchain_extension = use_extension("@bazel_buildbuddy//:rules.bzl", "buildbuddy_toolchain_extension", dev_dependency = True) +inject_repo(buildbuddy_toolchain_extension, "platforms", "bazel_utilities") +buildbuddy_toolchain_extension.buildbuddy_toolchain(name = "buildbuddy") +use_repo(buildbuddy_toolchain_extension, "buildbuddy") +# register_toolchains("@buildbuddy//:gcc-toolchain") diff --git a/README.md b/README.md index 93925ca3..9cf86239 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ [![Build status](https://badge.buildkite.com/c74bfd00e5543dcb5645acecbfd9d1fc3a0487bc5de13db0b9.svg)](https://buildkite.com/sacha/streamformat) -[![StreamFormat](https://github.com/0-Sacha/StreamFormat/actions/workflows/StreamFormat.yml/badge.svg)](https://github.com/0-Sacha/StreamFormat/actions/workflows/StreamFormat.yml) +[![stream](https://github.com/0-Sacha/stream/actions/workflows/stream.yml/badge.svg)](https://github.com/0-Sacha/stream/actions/workflows/stream.yml) -# StreamFormat +# stream -StreamFormat is a C++20 String Formatter, like [<fmt>](https://github.com/fmtlib/fmt) +stream is a C++20 String Formatter, like [<fmt>](https://github.com/fmtlib/fmt) Using this formatter, it define others functionalities: - Logger like [spdlog](https://github.com/gabime/spdlog) - Json Serializer @@ -21,17 +21,13 @@ For now, at least, you have the [Examples](Examples/README.md) (and maybe the Te ## Download ``` -git clone git@github.com:0-Sacha/StreamFormat.git +git clone git@github.com:0-Sacha/stream.git ``` ## Using the Lib It can be used using [Bazel](https://bazel.build/). -A `cc_library` rule has been created: `@StreamFormat//:StreamFormat`. +A `cc_library` rule has been created: `@stream//:stream`. You need to add the module `streamformat` to your dependencies. -You will need at least to give an c++ standard to use (at least c++20) since no one have been forced. You can check the [bazelrc](.bazelrc) to see how you can add one. - -Not Recommended: There is also a [Premake](https://premake.github.io/docs/using-premake) configuration, thought it is deprecated (and run on a wrapper of mine: [PremakeUtilities](https://github.com/0-Sacha/PremakeUtilities)). I keep it for my Game Engine [Blackbird](https://github.com/0-Sacha/Blackbird) which is using `Premake` as Build system. - ## Examples You can check the [Examples](Examples/README.md) to see what you can do with this. diff --git a/Tests/FMT/BaseFMTTests.h b/Tests/FMT/BaseFMTTests.h deleted file mode 100644 index bf3eb36f..00000000 --- a/Tests/FMT/BaseFMTTests.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "StreamFormat/Tester/TestSuite/AllTestSuite.h" - -inline PCT_TEST_SUITE(FMT); diff --git a/Tests/FMT/ComplexPattern.cpp b/Tests/FMT/ComplexPattern.cpp deleted file mode 100644 index 6a1078c0..00000000 --- a/Tests/FMT/ComplexPattern.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "StreamFormat/FMT.h" -#include "StreamFormat/Tester/TestSuite/AllTestSuite.h" - -#include "BaseFMTTests.h" - -PCT_TEST_GROUP(FMT, COMPLEX_PATTERN); - -#define TEST_FMT(fmt_test, expected, ...) PCT_EQ(StreamFormat::FMT::FormatString(fmt_test, __VA_ARGS__), std::string(expected)) - -PCT_TEST_FUNC(COMPLEX_PATTERN, UNESCAPED_ESCAPE_PATTERN) -{ - TEST_FMT("{0}", "9", 9); - TEST_FMT("{{0}|", "{9|", 9); - TEST_FMT("{{0},", "{9,", 9); -} diff --git a/Tests/FMT/Globber.cpp b/Tests/FMT/Globber.cpp deleted file mode 100644 index 32171173..00000000 --- a/Tests/FMT/Globber.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "BaseFMTTests.h" - -#include "StreamFormat/FMT/Context/ParserExecutor/UtilityFunctions.h" - -#include "StreamFormat/FMT/Buffer/Utils/BufferGlobberManip.h" - -PCT_TEST_GROUP(FMT, GLOBBER); -#define TEST_GLOBBER(data, glob) \ - { \ - StreamFormat::FMT::Detail::BufferInfoView p_buffer(data); \ - StreamFormat::FMT::Detail::BufferInfoView p_glob(glob); \ - StreamFormat::FMT::Detail::Globber::BufferInExecGlob(p_buffer, \ - p_glob); \ - PCT_ASSERT( \ - StreamFormat::FMT::Detail::BufferAccess(p_buffer).IsEndOfString()); \ - } - -PCT_TEST_FUNC(GLOBBER, BASIC_WILDCARD){ - TEST_GLOBBER("qwerty", "qwerty") TEST_GLOBBER("qwerty", "q?erty") - TEST_GLOBBER("qwerty", "q?????") TEST_GLOBBER("qwerty", "qwer?y") - TEST_GLOBBER("qwerty", "qwert?") TEST_GLOBBER("qwerty", "??????") - TEST_GLOBBER("qwerty", "*") TEST_GLOBBER("qwerty", "******") - TEST_GLOBBER("qwerty", "*?**?*")} - -PCT_TEST_GROUP(FMT, PARSE_GLOBBER); -PCT_TEST_FUNC(PARSE_GLOBBER, PG_BASIC_WILDCARD) { - int k = 0; - StreamFormat::FMT::Parse("|123|", "|{}|", k); - PCT_EQ(k, 123); - - { - char test[5]; - StreamFormat::FMT::Parse("|test|", "|{}|", test); - // PCT_EQ(std::string(test), std::string("test")); - } - - { - char test[4]; - StreamFormat::FMT::Parse("|test|", "|{:no-zero-end}|", test); - // PCT_EQ(std::string(test, 4), std::string("test")); - } - - { - char test[4]; - StreamFormat::FMT::Parse("|test|", "|{}t|", test); - // PCT_EQ(std::string(test), std::string("tes")); - } - - { - char test[11]; - StreamFormat::FMT::Parse("|test123456|", "|{}|", test); - // PCT_EQ(std::string(test), std::string("test123456")); - } - - { - char test[11]; - StreamFormat::FMT::Parse("|test123456|", "|{:glob='*1'}23456|", test); - // PCT_EQ(std::string(test), std::string("test1")); - } - - { - char test[11]; - // just glob = '????' but compiler are anrgy about trigraph on '??' - StreamFormat::FMT::Parse("|test123456|", - "|{:glob='?" - "?" - "?" - "?'}123456|", - test); - // PCT_EQ(std::string(test), std::string("test")); - } -} diff --git a/Tests/FMT/Index.cpp b/Tests/FMT/Index.cpp deleted file mode 100644 index e0a4e6bc..00000000 --- a/Tests/FMT/Index.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "StreamFormat/FMT.h" -#include "StreamFormat/Tester/TestSuite/AllTestSuite.h" - -#include "BaseFMTTests.h" - -/* -PCT_TEST_GROUP(FMT, INDEX); - -PCT_TEST_FUNC(INDEX, ReIndexing) -{ -} -*/ diff --git a/Tests/FMT/Limits.cpp b/Tests/FMT/Limits.cpp deleted file mode 100644 index 2ce24103..00000000 --- a/Tests/FMT/Limits.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "StreamFormat/FMT.h" -#include "StreamFormat/Tester/TestSuite/AllTestSuite.h" - -#include "BaseFMTTests.h" - -PCT_TEST_GROUP(FMT, LIMITS); - -#define PCT_TEST_FUNC_LowBufferSize(k) \ - PCT_TEST_FUNC(LIMITS, LowBufferSize##k) { \ - char buffer[k] = {0}; \ - StreamFormat::FMT::FormatInChar(buffer, "0123456789"); \ - for (int i = 0; i < k; ++i) \ - PCT_EQ(buffer[i] - '0', i); \ - } - -PCT_TEST_FUNC_LowBufferSize(10); -PCT_TEST_FUNC_LowBufferSize(9); -PCT_TEST_FUNC_LowBufferSize(8); -PCT_TEST_FUNC_LowBufferSize(7); -PCT_TEST_FUNC_LowBufferSize(6); -PCT_TEST_FUNC_LowBufferSize(5); -PCT_TEST_FUNC_LowBufferSize(4); -PCT_TEST_FUNC_LowBufferSize(3); -PCT_TEST_FUNC_LowBufferSize(2); -PCT_TEST_FUNC_LowBufferSize(1); - -PCT_TEST_FUNC(LIMITS, PlainLowBufferSize10) { - char buffer[10] = {0}; - StreamFormat::FMT::FormatInChar(buffer, "0123456789"); - for (int i = 0; i < 10; ++i) - PCT_EQ(buffer[i] - '0', i); -} - -PCT_TEST_FUNC(LIMITS, PlainLowBufferSize1) { - char buffer[1] = {0}; - StreamFormat::FMT::FormatInChar(buffer, "0"); - for (int i = 0; i < 1; ++i) - PCT_EQ(buffer[i] - '0', i); -} - -#define PCT_TEST_FUNC_LowBufferSizeArray(k) \ - PCT_TEST_FUNC(LIMITS, LowBufferSizeArray##k) { \ - char buffer[k] = {0}; \ - const char fmtBuffer[] = { \ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; \ - StreamFormat::FMT::Detail::BufferInfoView format(fmtBuffer, k); \ - StreamFormat::FMT::Detail::GivenBufferOutManager manager(buffer, k); \ - StreamFormat::FMT::Detail::FormatInManager(manager, false, format); \ - for (int i = 0; i < k; ++i) \ - PCT_EQ(buffer[i] - '0', i); \ - } - -PCT_TEST_FUNC_LowBufferSizeArray(10); -PCT_TEST_FUNC_LowBufferSizeArray(9); -PCT_TEST_FUNC_LowBufferSizeArray(8); -PCT_TEST_FUNC_LowBufferSizeArray(7); -PCT_TEST_FUNC_LowBufferSizeArray(6); -PCT_TEST_FUNC_LowBufferSizeArray(5); -PCT_TEST_FUNC_LowBufferSizeArray(4); -PCT_TEST_FUNC_LowBufferSizeArray(3); -PCT_TEST_FUNC_LowBufferSizeArray(2); -PCT_TEST_FUNC_LowBufferSizeArray(1); - -PCT_TEST_FUNC(LIMITS, PlainLowBufferSizeArray10) { - char buffer[10] = {0}; - const char fmtBuffer[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; - StreamFormat::FMT::Detail::BufferInfoView fmt(fmtBuffer, 10); - StreamFormat::FMT::Detail::GivenBufferOutManager manager(buffer, 10); - StreamFormat::FMT::Detail::FormatInManager(manager, false, fmt); - for (int i = 0; i < 10; ++i) - PCT_EQ(buffer[i] - '0', i); -} - -PCT_TEST_FUNC(LIMITS, PlainLowBufferSizeArray1) { - char buffer[1] = {0}; - const char fmtBuffer[] = {'0'}; - StreamFormat::FMT::Detail::BufferInfoView fmt(fmtBuffer, 1); - StreamFormat::FMT::Detail::GivenBufferOutManager manager(buffer, 1); - StreamFormat::FMT::Detail::FormatInManager(manager, false, fmt); - for (int i = 0; i < 1; ++i) - PCT_EQ(buffer[i] - '0', i); -} - -PCT_TEST_FUNC(LIMITS, LowBufferSizeArray10FMT30) { - char buffer[10] = {0}; - const char fmtBuffer[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; - StreamFormat::FMT::Detail::BufferInfoView fmt(fmtBuffer, 30); - StreamFormat::FMT::Detail::GivenBufferOutManager manager(buffer, 10); - StreamFormat::FMT::Detail::FormatInManager(manager, false, fmt); - for (int k = 0; k < 10; ++k) - PCT_EQ(buffer[k] - '0', k); -} - -PCT_TEST_FUNC(LIMITS, LowBufferSizeArray5Number9) { - char buffer[10] = {0}; - StreamFormat::FMT::Detail::BufferInfoView fmt("{}"); - StreamFormat::FMT::Detail::GivenBufferOutManager manager(buffer, 10); - std::uint64_t i = 9'876'543'210; - StreamFormat::FMT::Detail::FormatInManager(manager, false, fmt, i); - for (int k = 0; k < 10; ++k) - PCT_EQ(buffer[k] - '0', 9 - k); -} diff --git a/Tests/FMT/Specifier.cpp b/Tests/FMT/Specifier.cpp deleted file mode 100644 index 43f76032..00000000 --- a/Tests/FMT/Specifier.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "StreamFormat/FMT.h" -#include "StreamFormat/Tester/TestSuite/AllTestSuite.h" - -#include "BaseFMTTests.h" - -PCT_TEST_GROUP(FMT, SPECIFIER); - -#define TEST_FMT_ARRAY_SPECIFIERS(fmt_test, test_data, expected) PCT_EQ(StreamFormat::FMT::FormatString(fmt_test, test_data), expected) - -PCT_TEST_FUNC(SPECIFIER, BEGIN_END) -{ - int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - TEST_FMT_ARRAY_SPECIFIERS("{}", data, "{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }"); - - TEST_FMT_ARRAY_SPECIFIERS("{:begin=6}", data, "{ 6, 7, 8, 9 }"); - TEST_FMT_ARRAY_SPECIFIERS("{:size=5}", data, "{ 0, 1, 2, 3, 4 }"); - TEST_FMT_ARRAY_SPECIFIERS("{:begin=3, size=5}", data, "{ 3, 4, 5, 6, 7 }"); - - TEST_FMT_ARRAY_SPECIFIERS("{:begin='{', begin=3, size=5}", data, "{3, 4, 5, 6, 7 }"); - TEST_FMT_ARRAY_SPECIFIERS("{:end='}', begin=3, size=5}", data, "{ 3, 4, 5, 6, 7}"); - TEST_FMT_ARRAY_SPECIFIERS("{:begin='{', end='}', begin=3, size=5}", data, "{3, 4, 5, 6, 7}"); - TEST_FMT_ARRAY_SPECIFIERS("{:begin='[', end='}', begin=3, size=5}", data, "[3, 4, 5, 6, 7}"); - TEST_FMT_ARRAY_SPECIFIERS("{:begin='[', end=']', begin=3, size=5}", data, "[3, 4, 5, 6, 7]"); - - TEST_FMT_ARRAY_SPECIFIERS("{:join=' ', begin='[', end=']', begin=3, size=5}", data, "[3 4 5 6 7]"); - - TEST_FMT_ARRAY_SPECIFIERS("{:join=' | ', begin='[', end=']', begin=3, size=5}", data, "[3 | 4 | 5 | 6 | 7]"); -} diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp deleted file mode 100644 index b5d3dd84..00000000 --- a/Tests/Tests.cpp +++ /dev/null @@ -1,9 +0,0 @@ - -#include "StreamFormat/Tester/TestSuite/AllTestSuite.h" -#include "StreamFormat/FLog/DefaultLogger.h" - -int main() -{ - StreamFormat::Tester::TestSuitesManager::Verbose = false; - return StreamFormat::Tester::TestSuitesManager::ExecAllTestSuites(); -} diff --git a/buildbuddy.yaml b/buildbuddy.yaml index eaae239f..14e75bb8 100644 --- a/buildbuddy.yaml +++ b/buildbuddy.yaml @@ -15,4 +15,4 @@ actions: branches: - "*" bazel_commands: - - "test -s --config=buildbuddy --remote_header=x-buildbuddy-api-key=${BUILDBUDDY_WINDOWS_WSL} //:StreamFormatTests" + - "test -s --config=buildbuddy --remote_header=x-buildbuddy-api-key=${BUILDBUDDY_WINDOWS_WSL} //tests:units" diff --git a/conf b/conf new file mode 160000 index 00000000..1645a278 --- /dev/null +++ b/conf @@ -0,0 +1 @@ +Subproject commit 1645a278316e6e8e410ecf1240fbf4b56cd508ad diff --git a/conf/BUILD.bazel b/custom/BUILD.bazel similarity index 77% rename from conf/BUILD.bazel rename to custom/BUILD.bazel index 1fd3760b..ccbe9270 100644 --- a/conf/BUILD.bazel +++ b/custom/BUILD.bazel @@ -4,10 +4,10 @@ load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands") refresh_compile_commands( - name = "compile_commands", + name = "compile_commands_tests", exclude_external_sources = True, exclude_headers = "external", targets = { - "//:StreamFormat": "", + "//tests:units": "", }, ) diff --git a/Examples/.bazelrc b/examples/.bazelrc similarity index 55% rename from Examples/.bazelrc rename to examples/.bazelrc index 0cd88d06..538a4b5d 100644 --- a/Examples/.bazelrc +++ b/examples/.bazelrc @@ -6,5 +6,5 @@ common --verbose_failures test --test_output=errors # Winlibs -common:winlibs-gcc --extra_toolchains=@ex_winlibs//:gcc-toolchain -common:winlibs-clang --extra_toolchains=@pthread-ex_winlibs//:clang-toolchain +common:winlibs-gcc --extra_toolchains=@winlibs//:gcc-toolchain +common:winlibs-clang --extra_toolchains=@winlibs//:clang-toolchain diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel new file mode 100644 index 00000000..bcf173e1 --- /dev/null +++ b/examples/MODULE.bazel @@ -0,0 +1,25 @@ +"" + +# buildifier: disable=module-docstring +module( + name = "streamformat_examples", + version = "0.1", +) + +bazel_dep(name = "rules_cc", version = "0.0.10") +bazel_dep(name = "platforms", version = "0.0.10") + +git_override(module_name="bazel_utilities", remote="https://github.com/0-Sacha/bazel_utilities.git", commit="fbb17685ac9ba78fef914a322e6c37839dc16d4f") +git_override(module_name="bazel_buildbuddy", remote="https://github.com/0-Sacha/bazel_buildbuddy.git", commit="f3e98389266ce759fc71e1186502fa40f3ed3049") +git_override(module_name="bazel_winlibs", remote="https://github.com/0-Sacha/bazel_winlibs.git", commit="86a2725fb26fb73bfe8dc535f8f46bd1190cdae8") +bazel_dep(name = "bazel_utilities", version = "0.0.1", dev_dependency = True) +bazel_dep(name = "bazel_winlibs", version = "0.0.1", dev_dependency = True) +bazel_dep(name = "bazel_buildbuddy", version = "0.0.1", dev_dependency = True) + +local_path_override(module_name = "streamformat", path = "../") +bazel_dep(name = "streamformat") + +winlibs_toolchain_extension = use_extension("@bazel_winlibs//:rules.bzl", "winlibs_toolchain_extension", dev_dependency = True) +inject_repo(winlibs_toolchain_extension, "platforms", "bazel_utilities") +winlibs_toolchain_extension.winlibs_toolchain(name = "winlibs", dbg_copts = [ "-g3", "-O0" ]) +use_repo(winlibs_toolchain_extension, "winlibs") \ No newline at end of file diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..5a46ec67 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,30 @@ +# Example of stream + +### Try thoses examples ! + +##### Build and Run examples one by one (Recommended) +Example with `//hello:hello` (see below for the list of example) +``` +bazelisk run //hello:hello + +[00:00:00:000] APP-Core >> hello ! +[00:00:00:105] APP-Core >> After 100ms ! +``` + +##### Compile all examples, then run binaries +To compile every example: +``` +bazelisk build //... +``` + +Then you can run a program with (example with `//hello:hello`, see below for the list of example) +``` +.\bazel-bin\hello\hello + +[00:00:00:000] APP-Core >> hello ! +[00:00:00:105] APP-Core >> After 100ms ! +``` + +### List Of Examples + +- `//hello:hello`: hello using the Internal Logger diff --git a/examples/hello/BUILD.bazel b/examples/hello/BUILD.bazel new file mode 100644 index 00000000..dbcd0d36 --- /dev/null +++ b/examples/hello/BUILD.bazel @@ -0,0 +1,19 @@ +"" + +load("@rules_cc//cc:defs.bzl", "cc_binary") + +cc_binary( + name = "hello", + srcs = [ "main.cxx" ], + includes = [ "" ], + copts = select({ + "@rules_cc//cc/compiler:msvc-cl": ["/std:c++latest"], + "//conditions:default": ["-std=c++20"], + }), + linkopts = select({ + "@rules_cc//cc/compiler:msvc-cl": [""], + "//conditions:default": ["-pthread"], + }), + deps = [ "@streamformat//:stream" ], + visibility = ["//visibility:public"], +) diff --git a/examples/hello/main.cxx b/examples/hello/main.cxx new file mode 100644 index 00000000..25610fbc --- /dev/null +++ b/examples/hello/main.cxx @@ -0,0 +1,16 @@ +#include "stream/flog.hxx" +#include "stream/fmt/context/formatter_executor/utility_functions.hxx" + +#include "stream/default_logger.hxx" + +#include + +int main() +{ + stream::flog::DefaultLogger::core().info("HelloWorld !"); + + using namespace std::chrono_literals; + std::this_thread::sleep_for(100ms); + + stream::flog::DefaultLogger::core().warn("after 100ms !"); +} diff --git a/premake5.lua b/premake5.lua deleted file mode 100644 index b8b071ae..00000000 --- a/premake5.lua +++ /dev/null @@ -1,61 +0,0 @@ - --- TODO:bazel remove Solution.Projects Infos: -Solution.Projects["StreamFormat"].PlatformDefineName = "STREAMFORMAT" -Solution.Projects["StreamFormat"].Type = "StaticLib" -Solution.Projects["StreamFormat"].IncludeDirs = { - "%{Solution.Projects.StreamFormat.Path}/src/" -} - -project "StreamFormat" - kind (Solution.Projects["StreamFormat"].Type) - language "C++" - cppdialect "C++20" - - Solution.HighWarnings() - - targetdir (Solution.Path.ProjectTargetDirectory) - objdir (Solution.Path.ProjectObjectDirectory) - - files { - "src/**.h", - "src/**.inl", - "src/**.cpp", - } - - Solution.Project("StreamFormat") - - defines { - "STREAMFORMAT_BASE_LOGGER_NAME=\"%{Solution.Name}\"" - } - -if (StreamFormatTestsEnable) -then - -Solution.AddProject("StreamFormatTests", Solution.Projects["StreamFormat"].Path) -Solution.Projects["StreamFormatTests"].ProjectDependencies = { - "StreamFormat" -} - -StreamFormatTestsLaunch = {} -StreamFormatTestsLaunch.Project = "StreamFormatTests" -Solution.Launch["StreamFormatTests"] = StreamFormatTestsLaunch - -project "StreamFormatTests" - kind (Solution.Projects["StreamFormatTests"].Type) - language "C++" - cppdialect "C++20" - - Solution.HighWarnings() - - targetdir (Solution.Path.ProjectTargetDirectory) - objdir (Solution.Path.ProjectObjectDirectory) - - files { - "Tests/**.h", - "Tests/**.hpp", - "Tests/**.inl", - "Tests/**.cpp", - } - - Solution.Project("StreamFormatTests") -end diff --git a/scripts/clang-tidy.sh b/scripts/clang-tidy.sh new file mode 100755 index 00000000..c0e3b159 --- /dev/null +++ b/scripts/clang-tidy.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./conf/scripts/clang-tidy.py //custom:compile_commands_tests --enable-headers $* --config=./conf/checker/.clang-tidy --config=./conf/linter/RustLike/.clang-tidy diff --git a/src/StreamFormat/Core/CompilerInfo.h b/src/StreamFormat/Core/CompilerInfo.h deleted file mode 100644 index 7babe3f2..00000000 --- a/src/StreamFormat/Core/CompilerInfo.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#ifndef STREAMFORMAT_DO_NOT_USE_DEFAULT_MACRO -#if defined(__clang__) -#define STREAMFORMAT_COMPILER_CLANG -#elif defined(__GNUC__) || defined(__GNUG__) -#define STREAMFORMAT_COMPILER_GCC -#elif defined(_MSC_VER) -#define STREAMFORMAT_COMPILER_MSVC -#endif - -#ifdef STREAMFORMAT_COMPILER_MSVC -#ifdef _DEBUG -#define STREAMFORMAT_DEBUG -#endif -#endif - -#if defined(STREAMFORMAT_COMPILER_CLANG) || defined(STREAMFORMAT_COMPILER_GCC) -#if !defined(NDEBUG) -#define STREAMFORMAT_DEBUG -#endif -#endif -#endif diff --git a/src/StreamFormat/FLog.h b/src/StreamFormat/FLog.h deleted file mode 100644 index 759c94a2..00000000 --- a/src/StreamFormat/FLog.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "FLog/Loggers/BasicLogger.h" -#include "FLog/Loggers/LoggerMultiSinkFast.h" -#include "FLog/Loggers/LoggerMultiSinkSafe.h" - -#include "FLog/Sinks/FileSink.h" - -#include "FLog/LoggerImpl/XLogger.h" - -#include "FLog/LoggerFactory.h" diff --git a/src/StreamFormat/FLog/DefaultLogger.h b/src/StreamFormat/FLog/DefaultLogger.h deleted file mode 100644 index 34281830..00000000 --- a/src/StreamFormat/FLog/DefaultLogger.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "LoggerImpl/XLogger.h" - -#ifndef STREAMFORMAT_BASE_LOGGER_NAME -#undef STREAMFORMAT_BASE_LOGGER_NAME -#define STREAMFORMAT_BASE_LOGGER_NAME "APP" -#endif - -namespace StreamFormat::FLog -{ - class DefaultLogger - { - public: - [[maybe_unused]] static BasicLogger& Core() - { - static BasicLogger instance(STREAMFORMAT_BASE_LOGGER_NAME "-Core", LogSeverity::Trace); - return instance; - } - [[maybe_unused]] static BasicLogger& Client() - { - static BasicLogger instance(STREAMFORMAT_BASE_LOGGER_NAME "-Client", LogSeverity::Trace); - return instance; - } - }; -} - -#ifdef STREAMFORMAT_LOGGER_ENABLE - #define CORE_TRACE(...) StreamFormat::FLog::BasicLogger::Core().Trace(__VA_ARGS__) - #define CORE_DEBUG(...) StreamFormat::FLog::BasicLogger::Core().Debug(__VA_ARGS__) - #define CORE_INFO(...) StreamFormat::FLog::BasicLogger::Core().Info(__VA_ARGS__) - #define CORE_WARN(...) StreamFormat::FLog::BasicLogger::Core().Warn(__VA_ARGS__) - #define CORE_ERROR(...) StreamFormat::FLog::BasicLogger::Core().Error(__VA_ARGS__) - #define CORE_FATAL(...) StreamFormat::FLog::BasicLogger::Core().Fatal(__VA_ARGS__) -#else - #define CORE_TRACE(...) - #define CORE_DEBUG(...) - #define CORE_INFO(...) - #define CORE_WARN(...) - #define CORE_ERROR(...) - #define CORE_FATAL(...) -#endif diff --git a/src/StreamFormat/FLog/Detail/Detail.h b/src/StreamFormat/FLog/Detail/Detail.h deleted file mode 100644 index 5c3e3231..00000000 --- a/src/StreamFormat/FLog/Detail/Detail.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT.h" - -#include "StreamFormat/FMT/Buffer/BufferManip.h" -#include "StreamFormat/FMT/Buffer/BufferWriteManip.h" - -namespace StreamFormat::FLog -{ - template - struct AddIndentInFormat - { - AddIndentInFormat(const FormatStr& format) - : Format(format) - {} - const FormatStr& Format; - }; - - template - struct ConcateNameAndSinkName - { - ConcateNameAndSinkName(const std::basic_string& loggerName, const std::basic_string& sinkName) - : LoggerName(loggerName) - , SinkName(sinkName) - {} - const std::basic_string& LoggerName; - const std::basic_string& SinkName; - }; - - template - struct FuturConcateNameAndSinkName - { - FuturConcateNameAndSinkName(const std::basic_string& loggerName) - : LoggerName(loggerName) - {} - const std::basic_string& LoggerName; - }; -} - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const StreamFormat::FLog::AddIndentInFormat& format, FormatterExecutor& executor) - { - Detail::BufferWriteManip(executor.BufferOut).FastWriteStringLitteral("{K:indent}"); - executor.WriteType(format.Format); - } - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const StreamFormat::FLog::ConcateNameAndSinkName& names, FormatterExecutor& executor) - { - executor.Run(names.LoggerName, FORMAT_SV("sink", names.SinkName)); - } - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const StreamFormat::FLog::FuturConcateNameAndSinkName& names, FormatterExecutor& executor) { executor.Run(names.LoggerName, "sink"); } - }; -} diff --git a/src/StreamFormat/FLog/LoggerFactory.h b/src/StreamFormat/FLog/LoggerFactory.h deleted file mode 100644 index 5d155a41..00000000 --- a/src/StreamFormat/FLog/LoggerFactory.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "Loggers/BasicLogger.h" -#include "Loggers/LoggerMultiSinkFast.h" -#include "Loggers/LoggerMultiSinkSafe.h" - -// TODO: -namespace StreamFormat::FLog -{ - class LoggerFactory - { - }; -} diff --git a/src/StreamFormat/FLog/LoggerImpl/XLogger.cpp b/src/StreamFormat/FLog/LoggerImpl/XLogger.cpp deleted file mode 100644 index 835a4777..00000000 --- a/src/StreamFormat/FLog/LoggerImpl/XLogger.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "XLogger.h" - -namespace StreamFormat::FLog -{ - template class Detail::XLogger>; - template class Detail::XLogger>; - template class Detail::XLogger>; -} - -namespace StreamFormat::FLog::Sinks -{ - template class BasicConsoleSink; - template class BasicFileSink; -} diff --git a/src/StreamFormat/FLog/LoggerImpl/XLogger.h b/src/StreamFormat/FLog/LoggerImpl/XLogger.h deleted file mode 100644 index c930f8f6..00000000 --- a/src/StreamFormat/FLog/LoggerImpl/XLogger.h +++ /dev/null @@ -1,204 +0,0 @@ -#pragma once - -#include "StreamFormat/FLog/Detail/Detail.h" -#include "StreamFormat/FLog/Loggers/BasicLogger.h" -#include "StreamFormat/FLog/Loggers/LoggerMultiSinkFast.h" -#include "StreamFormat/FLog/Loggers/LoggerMultiSinkSafe.h" -#include "StreamFormat/FLog/Sinks/FileSink.h" - -namespace StreamFormat::FLog -{ - struct LogSeverity - { - public: - enum class Value : int - { - Trace, - Debug, - Info, - Warn, - Error, - Fatal, - DefaultSeverity = Trace - }; - - public: - static constexpr Value Trace{Value::Trace}; - static constexpr Value Debug{Value::Debug}; - static constexpr Value Info{Value::Info}; - static constexpr Value Warn{Value::Warn}; - static constexpr Value Error{Value::Error}; - static constexpr Value Fatal{Value::Fatal}; - static constexpr Value DefaultSeverity = Trace; - - public: - class PatternOverride - { - public: - std::basic_string TracePattern = ""; - std::basic_string DebugPattern = ""; - std::basic_string InfoPattern = ""; - std::basic_string WarnPattern = ""; - std::basic_string ErrorPattern = ""; - std::basic_string FatalPattern = ""; - - std::basic_string_view GetPattern(const Value& severity) const - { - switch (severity) - { - case Value::Trace: - if (TracePattern.empty() == false) return TracePattern; - break; - case Value::Debug: - if (DebugPattern.empty() == false) return DebugPattern; - break; - case Value::Info: - if (InfoPattern.empty() == false) return InfoPattern; - break; - case Value::Warn: - if (WarnPattern.empty() == false) return WarnPattern; - break; - case Value::Error: - if (ErrorPattern.empty() == false) return ErrorPattern; - break; - case Value::Fatal: - if (FatalPattern.empty() == false) return FatalPattern; - break; - } - return std::basic_string_view{nullptr, 0}; - } - }; - }; -} - -namespace StreamFormat::FLog::Detail -{ - template - class XLogger : public Master - { - public: - template - XLogger(Args&&... args) - : Master(std::forward(args)...) - {} - - ~XLogger() override = default; - - public: - template - requires FMT::Detail::ConvertibleToBufferInfoView - void Log(Severity status, Format&& format, Args&&... args) { Master::template Log(status, format, std::forward(args)...); } - - template - void Log(Severity status, T&& t) - { - Master::template Log(status, std::forward(t)); - } - - public: - /////---------- Logger Severity with array as format ----------///// - template - requires FMT::Detail::ConvertibleToBufferInfoView - inline void Trace(Format&& format, Args&&... args) { return Log(LogSeverity::Trace, format, std::forward(args)...); } - template - requires FMT::Detail::ConvertibleToBufferInfoView - inline void Debug(Format&& format, Args&&... args) { return Log(LogSeverity::Debug, format, std::forward(args)...); } - template - requires FMT::Detail::ConvertibleToBufferInfoView - inline void Info(Format&& format, Args&&... args) { return Log(LogSeverity::Info, format, std::forward(args)...); } - template - requires FMT::Detail::ConvertibleToBufferInfoView - inline void Warn(Format&& format, Args&&... args) { return Log(LogSeverity::Warn, format, std::forward(args)...); } - template - requires FMT::Detail::ConvertibleToBufferInfoView - inline void Error(Format&& format, Args&&... args) { return Log(LogSeverity::Error, format, std::forward(args)...); } - template - requires FMT::Detail::ConvertibleToBufferInfoView - inline void Fatal(Format&& format, Args&&... args) { return Log(LogSeverity::Fatal, format, std::forward(args)...); } - - /////---------- NO-FORMAT Logger Severity ----------///// - template - inline void Trace(T&& t) - { - return Log(LogSeverity::Trace, std::forward(t)); - } - template - inline void Debug(T&& t) - { - return Log(LogSeverity::Debug, std::forward(t)); - } - template - inline void Info(T&& t) - { - return Log(LogSeverity::Info, std::forward(t)); - } - template - inline void Warn(T&& t) - { - return Log(LogSeverity::Warn, std::forward(t)); - } - template - inline void Error(T&& t) - { - return Log(LogSeverity::Error, std::forward(t)); - } - template - inline void Fatal(T&& t) - { - return Log(LogSeverity::Fatal, std::forward(t)); - } - }; -} - -namespace StreamFormat::FMT -{ - template - struct FormatterType - { - static void Format(const StreamFormat::FLog::LogSeverity::Value t, FormatterExecutor& executor) - { - executor.Data.KeepNewStyle = true; - switch (t) - { - case StreamFormat::FLog::LogSeverity::Trace: - FormatterType::Format(Detail::TextProperties::TextColor::BasicColorFG::BrightBlack, executor); - break; - case StreamFormat::FLog::LogSeverity::Debug: - FormatterType::Format(Detail::TextProperties::TextColor::BasicColorFG::Blue, executor); - break; - case StreamFormat::FLog::LogSeverity::Info: - FormatterType::Format(Detail::TextProperties::TextColor::BasicColorFG::Green, executor); - break; - case StreamFormat::FLog::LogSeverity::Warn: - FormatterType::Format(Detail::TextProperties::TextColor::BasicColorFG::Yellow, executor); - break; - case StreamFormat::FLog::LogSeverity::Error: - FormatterType::Format(Detail::TextProperties::TextColor::BasicColorFG::Red, executor); - break; - case StreamFormat::FLog::LogSeverity::Fatal: - FormatterType::Format(Detail::TextProperties::TextColor::BasicColorFG::BrightMagenta, executor); - break; - } - } - }; -} - -namespace StreamFormat::FLog -{ - using BasicLogger = Detail::XLogger>; - using LoggerMultiSinkFast = Detail::XLogger>; - using LoggerMultiSinkSafe = Detail::XLogger>; - - extern template class Detail::XLogger>; - extern template class Detail::XLogger>; - extern template class Detail::XLogger>; -} - -namespace StreamFormat::FLog::Sinks -{ - using ConsoleSink = BasicConsoleSink; - using FileSink = BasicFileSink; - - extern template class BasicConsoleSink; - extern template class BasicFileSink; -} diff --git a/src/StreamFormat/FLog/Loggers/BasicLogger.h b/src/StreamFormat/FLog/Loggers/BasicLogger.h deleted file mode 100644 index b025f545..00000000 --- a/src/StreamFormat/FLog/Loggers/BasicLogger.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once - -#include "StreamFormat/FLog/Detail/Detail.h" -#include "StreamFormat/FMT/Serializers/FormatChrono.h" - -#include -#include - -namespace StreamFormat::FLog::Detail -{ - template - class BasicLoggerImpl - { - public: - using SeverityValueType = typename Severity::Value; - - public: - BasicLoggerImpl() - : m_Name("Logger") - , m_Severity(Severity::Value::DefaultSeverity) - , m_Stream(std::cout) - , m_StartTime(std::chrono::high_resolution_clock::now()) - { - ResetPattern(); - } - - explicit BasicLoggerImpl(const std::string_view& name, typename Severity::Value severity = Severity::Value::DefaultSeverity, std::ostream& stream = std::cout) - : m_Name(name) - , m_Severity(severity) - , m_Stream(stream) - , preFormatBufferOutManager(64) - , fullFormatBufferOutManager(64) - , m_StartTime(std::chrono::high_resolution_clock::now()) - { - ResetPattern(); - } - explicit BasicLoggerImpl(const std::string_view& name, const std::string_view& format, typename Severity::Value severity = Severity::Value::DefaultSeverity, - std::ostream& stream = std::cout) - : m_Name(name) - , m_Severity(severity) - , m_Stream(stream) - , preFormatBufferOutManager(64) - , fullFormatBufferOutManager(64) - , m_StartTime(std::chrono::high_resolution_clock::now()) - { - SetPattern(format); - } - - virtual ~BasicLoggerImpl() = default; - - public: - void SetSeverity(const SeverityValueType& severity) { m_Severity = severity; } - void SetName(const std::string& name) { m_Name = name; } - void SetName(std::string&& name) { m_Name = std::move(name); } - void SetRealPattern(std::string_view pattern) { m_Pattern = pattern; } - void SetRealPatternStrmv(std::string&& pattern) { m_Pattern = std::move(pattern); } - void SetPattern(std::string_view pattern) - { - m_Pattern = "{color}"; - m_Pattern += pattern; - } - void ResetPattern() { SetPattern("[{time:pattern='%h:%m:%s:%ms'}] {name} >> {data}"); } - - private: - std::string m_Name; - SeverityValueType m_Severity; - std::ostream& m_Stream; - std::string m_Pattern; - FMT::Detail::DynamicBufferOutManager preFormatBufferOutManager; - FMT::Detail::DynamicBufferOutManager fullFormatBufferOutManager; - - std::chrono::time_point m_StartTime; - - public: - void NewLine() { m_Stream.write("\n", 1); } - - template - requires FMT::Detail::ConvertibleToBufferInfoView - void Log(const SeverityValueType& severity, Format&& format, Args&&... args) - { - if (severity < m_Severity) return; - - std::chrono::nanoseconds logTime = std::chrono::high_resolution_clock::now() - m_StartTime; - - FMT::Detail::FormatInManager(preFormatBufferOutManager, false, FMT::Detail::BufferInfoView(m_Pattern), FORMAT_SV("time", logTime), FORMAT_SV("name", m_Name), - FORMAT_SV("data", FLog::AddIndentInFormat(format))); - - FMT::Detail::FormatInManager(fullFormatBufferOutManager, true, preFormatBufferOutManager.GetLastGeneratedBufferInfoView(), std::forward(args)..., FORMAT_SV("color", severity)); - m_Stream.write(fullFormatBufferOutManager.GetBuffer(), static_cast(fullFormatBufferOutManager.GetLastGeneratedDataSize())); - m_Stream.flush(); - } - - template - void Log(const SeverityValueType& severity, T&& t) - { - if (severity < m_Severity) return; - - std::chrono::nanoseconds logTime = std::chrono::high_resolution_clock::now() - m_StartTime; - - FMT::Detail::FormatInManager(fullFormatBufferOutManager, true, FMT::Detail::BufferInfoView(m_Pattern), FORMAT_SV("data", t), FORMAT_SV("color", severity), - FORMAT_SV("time", logTime), FORMAT_SV("name", m_Name)); - m_Stream.write(fullFormatBufferOutManager.GetBuffer(), static_cast(fullFormatBufferOutManager.GetLastGeneratedDataSize())); - m_Stream.flush(); - } - }; -} diff --git a/src/StreamFormat/FLog/Loggers/LoggerMultiSinkFast.h b/src/StreamFormat/FLog/Loggers/LoggerMultiSinkFast.h deleted file mode 100644 index 9ede672b..00000000 --- a/src/StreamFormat/FLog/Loggers/LoggerMultiSinkFast.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "LoggerMultiSinks.h" - -namespace StreamFormat::FLog::Detail -{ - template - class BasicLoggerMultiSinkFastImpl : public BasicLoggerMultiSinkImpl - { - public: - using Base = BasicLoggerMultiSinkImpl; - using Base::SetName; - using Base::GetName; - using Base::GetSinks; - using Base::AddSink; - using Base::m_Name; - using Base::m_Sinks; - - using Base::m_StartTime; - - using typename Base::SeverityValueType; - - public: - BasicLoggerMultiSinkFastImpl() - : Base() - {} - - BasicLoggerMultiSinkFastImpl(std::basic_string&& name) - : Base(std::forward>(name)) - {} - - ~BasicLoggerMultiSinkFastImpl() override = default; - - public: - template - requires FMT::Detail::ConvertibleToBufferInfoView - void Log(const SeverityValueType& severity, const Format& format, Args&&... args) - { - std::chrono::nanoseconds logTime = std::chrono::high_resolution_clock::now() - m_StartTime; - - FMT::Detail::DynamicBufferOutManager manager(256); - auto formatBuffer = FMT::Detail::FormatInManager(manager, false, format, std::forward(args)...); - for (auto& sink : m_Sinks) - if (sink->NeedToLog(severity)) - sink->FormatAndWriteToSink(sink->GetPattern(severity), logTime, m_Name, static_cast>(*formatBuffer)); - - for (auto& sink : m_Sinks) - if (sink->NeedToLog(severity)) sink->WaitUnitlFinishedToWrite(); - } - - template - void Log(const SeverityValueType& severity, T&& t) - { - std::chrono::nanoseconds logTime = std::chrono::high_resolution_clock::now() - m_StartTime; - - FMT::Detail::DynamicBufferOutManager manager(256); - auto formatBuffer = FMT::Detail::FormatInManager(manager, false, std::forward(t)); - for (auto& sink : m_Sinks) - if (sink->NeedToLog(severity)) - sink->FormatAndWriteToSink(sink->GetPattern(severity), logTime, m_Name, static_cast>(*formatBuffer)); - - for (auto& sink : m_Sinks) - if (sink->NeedToLog(severity)) sink->WaitUnitlFinishedToWrite(); - } - }; -} diff --git a/src/StreamFormat/FLog/Loggers/LoggerMultiSinkSafe.h b/src/StreamFormat/FLog/Loggers/LoggerMultiSinkSafe.h deleted file mode 100644 index 2defd367..00000000 --- a/src/StreamFormat/FLog/Loggers/LoggerMultiSinkSafe.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include "LoggerMultiSinks.h" - -namespace StreamFormat::FLog::Detail -{ - template - class BasicLoggerMultiSinkSafeImpl : public BasicLoggerMultiSinkImpl - { - public: - using Base = BasicLoggerMultiSinkImpl; - using Base::SetName; - using Base::GetName; - using Base::GetSinks; - using Base::m_Name; - using Base::m_Sinks; - using Base::AddSink; - - using Base::m_StartTime; - - using typename Base::SeverityValueType; - - public: - BasicLoggerMultiSinkSafeImpl() - : Base() - {} - - BasicLoggerMultiSinkSafeImpl(std::basic_string&& name) - : Base(std::forward>(name)) - {} - - ~BasicLoggerMultiSinkSafeImpl() override = default; - - public: - template - requires FMT::Detail::ConvertibleToBufferInfoView - void Log(const SeverityValueType& severity, const Format& format, Args&&... args) - { - std::chrono::nanoseconds logTime = std::chrono::high_resolution_clock::now() - m_StartTime; - - // FIXME maybe add : name ; indent ??? - for (auto& sink : m_Sinks) - { - if (sink->NeedToLog(severity)) - { - FMT::Detail::DynamicBufferOutManager managerPattern(256); - FMT::Detail::DynamicBufferOutManager managerFormat(256); - auto formatPatternStr = - FMT::Detail::FormatInManager(managerPattern, false, std::string_view(sink->GetPattern(severity)), FORMAT_SV("time", logTime), - FORMAT_SV("name", FuturConcateNameAndSinkName(m_Name)), FORMAT_SV("data", FLog::AddIndentInFormat(format))); - auto formatFormatStr = FMT::Detail::FormatInManager(managerFormat, false, static_cast(*formatPatternStr), std::forward(args)..., - FORMAT_SV("sink", sink->GetName()), FORMAT_SV("color", severity)); - sink->WriteToSink(static_cast>(*formatFormatStr)); - } - } - - for (auto& sink : m_Sinks) - if (sink->NeedToLog(severity)) sink->WaitUnitlFinishedToWrite(); - } - - template - void Log(const SeverityValueType& severity, T&& t) - { - std::chrono::nanoseconds logTime = std::chrono::high_resolution_clock::now() - m_StartTime; - - for (auto& sink : m_Sinks) - { - if (sink->NeedToLog(severity)) - { - FMT::Detail::DynamicBufferOutManager manager(256); - auto formatBuffer = FMT::Detail::FormatInManager(manager, false, std::string_view(sink->GetPattern(severity)), FORMAT_SV("time", logTime), - FORMAT_SV("name", ConcateNameAndSinkName(m_Name, sink->GetName())), FORMAT_SV("data", t)); - sink->WriteToSink(static_cast>(*formatBuffer)); - } - } - - for (auto& sink : m_Sinks) - if (sink->NeedToLog(severity)) sink->WaitUnitlFinishedToWrite(); - } - }; -} diff --git a/src/StreamFormat/FLog/Loggers/LoggerMultiSinks.h b/src/StreamFormat/FLog/Loggers/LoggerMultiSinks.h deleted file mode 100644 index 86dcea76..00000000 --- a/src/StreamFormat/FLog/Loggers/LoggerMultiSinks.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "StreamFormat/FLog/Detail/Detail.h" -#include "StreamFormat/FLog/Sinks/LoggerSink.h" - -namespace StreamFormat::FLog::Detail -{ - template - class BasicLoggerMultiSinkImpl - { - public: - using SinkType = BasicLoggerSink; - using SeverityValueType = typename Severity::Value; - - public: - BasicLoggerMultiSinkImpl() - : m_Name("Logger:{sink}") - , m_StartTime(std::chrono::high_resolution_clock::now()) - {} - - BasicLoggerMultiSinkImpl(std::basic_string&& name) - : m_Name(std::forward>(name)) - , m_StartTime(std::chrono::high_resolution_clock::now()) - {} - - virtual ~BasicLoggerMultiSinkImpl() = default; - - public: - void SetName(std::basic_string&& name) { m_Name = std::forward>(name); } - - std::basic_string& GetName() { return m_Name; } - std::vector>& GetSinks() { return m_Sinks; } - - protected: - std::basic_string m_Name; - std::vector> m_Sinks; - - std::chrono::time_point m_StartTime; - - public: - void AddSink(std::shared_ptr sink) { m_Sinks.push_back(sink); } - - template - void EmplaceSink(Args&&... args) - { - std::shared_ptr sink = std::make_shared(std::forward(args)...); - AddSink(sink); - } - }; -} diff --git a/src/StreamFormat/FLog/Sinks/FileSink.h b/src/StreamFormat/FLog/Sinks/FileSink.h deleted file mode 100644 index d9e76830..00000000 --- a/src/StreamFormat/FLog/Sinks/FileSink.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include "LoggerSink.h" - -#include -#include -#include - -namespace StreamFormat::FLog::Sinks -{ - template - class BasicConsoleSink : public Detail::BasicLoggerSink - { - public: - using Base = Detail::BasicLoggerSink; - using typename Base::PatternType; - using typename Base::NameType; - using typename Base::BufferType; - - public: - BasicConsoleSink(std::basic_ostream& stream, NameType&& name) - : Base(std::forward(name)) - , m_Stream(stream) - {} - - BasicConsoleSink(std::basic_ostream& stream, NameType&& name, Detail::AsyncSink isAsync) - : Base(std::forward(name), isAsync) - , m_Stream(stream) - {} - - ~BasicConsoleSink() override = default; - - public: - std::basic_ostream& GetStream() { return m_Stream; } - - protected: - void WriteImpl(const BufferType& bufferToPrint) override - { - m_Stream.write(bufferToPrint.data(), bufferToPrint.size()); - m_Stream.write("\n", 1); - m_Stream.flush(); - } - - private: - std::basic_ostream& m_Stream; - }; - - template - class BasicFileSink : public Detail::BasicLoggerSink - { - public: - using Base = Detail::BasicLoggerSink; - using typename Base::PatternType; - using typename Base::NameType; - using typename Base::BufferType; - - public: - BasicFileSink(const std::filesystem::path& filePath, NameType&& name, Detail::AsyncSink isAsync) - : Base(std::forward(name), isAsync) - , m_Stream(filePath, std::ios::out) - {} - - ~BasicFileSink() override = default; - - public: - std::basic_ostream& GetStream() { return m_Stream; } - - protected: - void WriteImpl(const BufferType& bufferToPrint) override - { - m_Stream.write(bufferToPrint.data(), bufferToPrint.size()); - m_Stream.write("\n", 1); - m_Stream.flush(); - } - - private: - std::basic_ofstream m_Stream; - }; -} diff --git a/src/StreamFormat/FLog/Sinks/LoggerSink.h b/src/StreamFormat/FLog/Sinks/LoggerSink.h deleted file mode 100644 index 1bdebd99..00000000 --- a/src/StreamFormat/FLog/Sinks/LoggerSink.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include "StreamFormat/FLog/Detail/Detail.h" - -#include - -namespace StreamFormat::FLog::Detail -{ - enum class AsyncSink - { - Sync, - Async - }; - - template - class BasicLoggerSink - { - public: - using PatternType = std::basic_string; - using PatternTransfertType = std::basic_string_view; - using NameType = std::basic_string; - using BufferType = std::basic_string_view; - - using SeverityValueType = typename Severity::Value; - - public: - BasicLoggerSink(NameType&& name) - : Name(std::forward(name)) - , IsAsync(AsyncSink::Sync) - {} - - BasicLoggerSink(NameType&& name, AsyncSink isAsync) - : Name(std::forward(name)) - , IsAsync(isAsync) - {} - - virtual ~BasicLoggerSink() = default; - - public: - NameType Name = ""; - PatternType Pattern = "[{time:pattern='%h:%m:%s:%ms'}] {name} >> {data}"; - SeverityValueType SinkSeverity{SeverityValueType::DefaultSeverity}; - typename Severity::PatternOverride SeverityPatternOverride; - AsyncSink IsAsync; - - protected: - std::future m_AsyncWaiter; - - public: - bool NeedToLog(const SeverityValueType& severity) { return severity >= SinkSeverity; } - void WriteToSink(const SeverityValueType& severity, const BufferType& bufferToPrint) - { - if (NeedToLog(severity)) WriteToSink(bufferToPrint); - } - - public: - PatternTransfertType GetPattern(const typename Severity::Value& severity) const - { - PatternTransfertType customPattern = SeverityPatternOverride.GetPattern(severity); - if (customPattern.data() == nullptr || customPattern.size() == 0) return Pattern; - return customPattern; - } - - protected: - virtual void WriteImpl(const BufferType& bufferToPrint) = 0; - - public: - void WriteToSinkSync(const BufferType& bufferToPrint) { WriteImpl(bufferToPrint); } - void WriteToSinkAsync(const BufferType& bufferToPrint) - { - m_AsyncWaiter = std::async(std::launch::async, &BasicLoggerSink::WriteToSinkSync, this, bufferToPrint); - } - - void WriteToSink(const BufferType& bufferToPrint) - { - if (IsAsync == AsyncSink::Sync) - WriteToSinkSync(bufferToPrint); - else - WriteToSinkAsync(bufferToPrint); - } - - public: - void WaitUnitlFinishedToWrite() - { - if (IsAsync == AsyncSink::Async) return m_AsyncWaiter.get(); - } - - void FormatAndWriteToSinkSync(PatternTransfertType pattern, const std::chrono::nanoseconds& logTime, const NameType& loggerName, const BufferType& formatBuffer) - { - FMT::Detail::DynamicBufferOutManager manager(256); - auto formatPatternStr = FMT::Detail::FormatInManager(manager, false, pattern, FORMAT_SV("time", logTime), FORMAT_SV("name", ConcateNameAndSinkName(loggerName, Name)), - FORMAT_SV("data", formatBuffer)); - BufferType buffer(*formatPatternStr); - WriteToSinkSync(buffer); - } - - void FormatAndWriteToSinkAsync(PatternTransfertType pattern, const std::chrono::nanoseconds& logTime, const NameType& loggerName, const BufferType& formatBuffer) - { - m_AsyncWaiter = std::async(std::launch::async, &BasicLoggerSink::FormatAndWriteToSinkSync, this, pattern, logTime, loggerName, formatBuffer); - } - - void FormatAndWriteToSink(PatternTransfertType pattern, const std::chrono::nanoseconds& logTime, const NameType& loggerName, const BufferType& formatBuffer) - { - if (IsAsync == AsyncSink::Sync) - FormatAndWriteToSinkSync(pattern, logTime, loggerName, formatBuffer); - else - FormatAndWriteToSinkAsync(pattern, logTime, loggerName, formatBuffer); - } - }; -} diff --git a/src/StreamFormat/FMT.h b/src/StreamFormat/FMT.h deleted file mode 100644 index ba1ab432..00000000 --- a/src/StreamFormat/FMT.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "FMT/Context/FormatterExecutor/UtilityFunctions.h" - -#include "FMT/Serializers/FormatSTDLib.h" diff --git a/src/StreamFormat/FMT/Buffer/BufferInfo.h b/src/StreamFormat/FMT/Buffer/BufferInfo.h deleted file mode 100644 index 9d535a1a..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferInfo.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/Detail.h" - -namespace StreamFormat::FMT::Detail -{ - template - class BufferInfo - { - public: - using TChar = CharType; - - public: - TChar* Buffer; - TChar* CurrentPos; - TChar* BufferEnd; // Not included - - public: - constexpr inline TChar Get() const { return *CurrentPos; } - template typename TManip> constexpr inline TManip Manip() { return TManip(Buffer); } - - public: - BufferInfo() noexcept - : Buffer(nullptr) - , CurrentPos(nullptr) - , BufferEnd(nullptr) - {} - - BufferInfo(TChar* const buffer, const std::size_t size) noexcept - : Buffer(buffer) - , CurrentPos(buffer) - , BufferEnd(buffer + size) - {} - }; - - template - class BufferInfoView : public BufferInfo - { - public: - using typename BufferInfo::TChar; - - using BufferInfo::Buffer; - using BufferInfo::CurrentPos; - using BufferInfo::BufferEnd; - - using BufferInfo::Get; - using BufferInfo::Manip; - - public: - BufferInfoView() noexcept - : BufferInfo() - {} - - template - BufferInfoView(const CharType (&data)[SIZE]) noexcept - : BufferInfo(data, SIZE) - { - while (BufferEnd - 1 > Buffer && *(BufferEnd - 1) == 0) - --BufferEnd; - } - - BufferInfoView(std::basic_string_view sv) noexcept - : BufferInfo(sv.data(), sv.size()) - {} - - BufferInfoView(const CharType* const buffer, const std::size_t size) noexcept - : BufferInfo(buffer, size) - {} - - public: - operator BufferInfo() const { return BufferInfo {.Buffer = Buffer, .CurrentPos = CurrentPos, .BufferEnd = BufferEnd}; } - }; - - template - concept ConvertibleToBufferInfo = requires(T&& t) - { - BufferInfo(std::forward(t)); - }; - - template - concept ConvertibleToBufferInfoView = requires(T&& t) - { - BufferInfoView(std::forward(t)); - }; -} diff --git a/src/StreamFormat/FMT/Buffer/BufferManip.h b/src/StreamFormat/FMT/Buffer/BufferManip.h deleted file mode 100644 index 65e3cef0..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferManip.h +++ /dev/null @@ -1,145 +0,0 @@ -#pragma once - -#include "BufferInfo.h" -#include "StreamFormat/FMT/Detail/Exception.h" - -namespace StreamFormat::FMT::Detail -{ - class FMTBufferManipError : public FMTError - { - public: - const char* what() const noexcept override { return "FMTBufferManipError"; } - }; - - struct BufferManipResult - { - bool Result = false; - constexpr inline BufferManipResult(bool result) noexcept : Result(result) {} - constexpr inline operator bool() const noexcept { return Result; } - - bool HasFailed() const noexcept { return !Result; } - - void ThrowIfFailed() const - { - if (Result == false) - throw FMTBufferManipError{}; - } - }; - - template - class BufferManipException; - - template - class BufferAccess - { - public: - constexpr inline BufferAccess(const BufferInfo& buffer) noexcept : Buffer(buffer) {} - public: - const BufferInfo& Buffer; - - public: - constexpr inline std::size_t GetBufferTotalSize() const noexcept { return static_cast(Buffer.BufferEnd - Buffer.Buffer); } - constexpr inline std::size_t GetBufferCurrentSize() const noexcept { return static_cast(Buffer.CurrentPos - Buffer.Buffer); } - constexpr inline std::size_t GetBufferRemainingSize() const noexcept { return static_cast(Buffer.BufferEnd - Buffer.CurrentPos); } - - public: - constexpr inline BufferManipResult CanMoveForward(const std::size_t count = 1) const noexcept { return Buffer.CurrentPos + count <= Buffer.BufferEnd; } - constexpr inline BufferManipResult CanMoveBackward(const std::size_t count = 1) const noexcept { return Buffer.CurrentPos - count >= Buffer.Buffer; } - - constexpr inline BufferManipResult IsOutOfBound() const noexcept { return Buffer.CurrentPos < Buffer.Buffer || Buffer.CurrentPos >= Buffer.BufferEnd; } - constexpr inline BufferManipResult IsEmpty() const noexcept { return Buffer.CurrentPos >= Buffer.BufferEnd; } - constexpr inline BufferManipResult IsEndOfString() const noexcept { return IsEmpty() || Buffer.Get() == 0; } - - constexpr inline TChar GetNextForce(const std::size_t count = 1) const noexcept { return *(Buffer.CurrentPos + count); } - constexpr inline TChar GetPrevForce(const std::size_t count = 1) const noexcept { return *(Buffer.CurrentPos - count); } - }; - - template - class BufferManip - { - public: - constexpr inline BufferManip(BufferInfo& buffer) noexcept : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - public: - BufferManipException ThrowIfFailed() { return BufferManipException(Buffer); } - - public: - constexpr inline void Set(TChar* const buffer, const std::size_t size) noexcept - { - Buffer.Buffer = buffer; - Buffer.CurrentPos = buffer; - Buffer.BufferEnd = buffer + size; - } - - constexpr inline void Reload(BufferInfo& buffer) noexcept - { - Buffer.Buffer = buffer.Buffer; - Buffer.CurrentPos = buffer.CurrentPos; - Buffer.BufferEnd = buffer.BufferEnd; - } - - BufferAccess Access() { return BufferAccess(Buffer); } - - public: - constexpr inline void ForceForward(const std::size_t count = 1) noexcept { Buffer.CurrentPos += count; } - constexpr inline BufferManipResult Forward(const std::size_t count = 1) noexcept - { - if (!Access().CanMoveForward(count)) return false; - Buffer.CurrentPos += count; - return true; - } - - constexpr inline void ForceBackward(const std::size_t count = 1) noexcept { Buffer.CurrentPos -= count; } - constexpr inline BufferManipResult Backward(const std::size_t count = 1) noexcept - { - if (!Access().CanMoveBackward(count)) return false; - Buffer.CurrentPos -= count; - return true; - } - - constexpr inline TChar GetAndForceForward() noexcept { return *Buffer.CurrentPos++; } - constexpr inline TChar GetAndForceBackward() noexcept { return *Buffer.CurrentPos--; } - }; - - template - class BufferManipException - { - public: - BufferManipException(BufferInfo& buffer) : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - public: - inline void Forward(const std::size_t count = 1) - { - BufferAccess(Buffer).Forward(count).ThrowIfFailed(); - } - inline void Backward(const std::size_t count = 1) - { - BufferAccess(Buffer).Backward(count).ThrowIfFailed(); - } - - inline TChar GetAndForward() - { - BufferAccess(Buffer).CanMoveForward(1).ThrowIfFailed(); - return *Buffer.CurrentPos++; - } - inline TChar GetAndBackward() - { - BufferAccess(Buffer).CanMoveBackward(1).ThrowIfFailed(); - return *Buffer.CurrentPos--; - } - inline TChar GetNext(const std::size_t count = 1) const - { - BufferAccess(Buffer).CanMoveForward(count).ThrowIfFailed(); - return BufferManip(Buffer).GetNextForce(count); - } - inline TChar GetPrev(const std::size_t count = 1) const - { - BufferAccess(Buffer).CanMoveBackward(count).ThrowIfFailed(); - return BufferManip(Buffer).GetPrevForce(count); - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/BufferOutManager/BasicBufferOutManager.h b/src/StreamFormat/FMT/Buffer/BufferOutManager/BasicBufferOutManager.h deleted file mode 100644 index d1e78892..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferOutManager/BasicBufferOutManager.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/Detail.h" -#include "StreamFormat/FMT/Buffer/BufferInfo.h" - -namespace StreamFormat::FMT::Detail -{ - template - class BasicBufferOutManager - { - public: - virtual ~BasicBufferOutManager() = default; - - protected: - virtual void BeginContextImpl() {} - virtual void ComputeGeneratedSizeImpl(const std::size_t /* totalGeneratedLength */) {} - - public: - void BeginContext() { BeginContextImpl(); } - void ComputeGeneratedSize(std::size_t totalGeneratedLength) - { - ComputeGeneratedSizeImpl(totalGeneratedLength); - SetLastGeneratedDataSize(totalGeneratedLength); - } - - public: - virtual CharType* GetBuffer() = 0; - virtual const CharType* GetBuffer() const = 0; - virtual std::size_t GetBufferSize() const = 0; - - public: - virtual bool AddSize(const std::size_t count) = 0; - - public: - BufferInfoView GetLastGeneratedBufferInfoView() const { return BufferInfoView(GetBuffer(), m_LastGeneratedDataSize); } - operator BufferInfoView() const { return GetLastGeneratedBufferInfoView(); } - - std::basic_string_view GetLastGeneratedStringView() const { return std::basic_string_view(GetBuffer(), m_LastGeneratedDataSize); } - operator std::basic_string_view() const { return GetLastGeneratedStringView(); } - std::basic_string GetLastGeneratedString() const { return std::basic_string(GetBuffer(), m_LastGeneratedDataSize); } - operator std::basic_string() const { return GetLastGeneratedString(); } - - public: - std::size_t GetLastGeneratedDataSize() const { return m_LastGeneratedDataSize; } - - private: - void SetLastGeneratedDataSize(const std::size_t size) { m_LastGeneratedDataSize = size; } - - protected: - std::size_t m_LastGeneratedDataSize{0}; - }; -} diff --git a/src/StreamFormat/FMT/Buffer/BufferOutManager/DynamicBufferOutManager.h b/src/StreamFormat/FMT/Buffer/BufferOutManager/DynamicBufferOutManager.h deleted file mode 100644 index 3949af13..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferOutManager/DynamicBufferOutManager.h +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once - -#include "BasicBufferOutManager.h" - -#include -#include -#include - -namespace StreamFormat::FMT::Detail -{ - template - class DynamicBufferOutManager : public BasicBufferOutManager - { - public: - DynamicBufferOutManager(std::size_t beginSize = DEFAULT_BEGIN_SIZE) - { - m_Buffer.reset(new CharType[beginSize]); - m_BufferSize = beginSize; - } - ~DynamicBufferOutManager() override = default; - - public: - static constexpr std::size_t DEFAULT_BEGIN_SIZE = 128; - static constexpr std::size_t GROW_UP_BUFFER_SIZE = 2; - static constexpr bool DEBUG_RESIZE = false; - - public: - CharType* GetBuffer() override { return m_Buffer.get(); } - const CharType* GetBuffer() const override { return m_Buffer.get(); } - std::size_t GetBufferSize() const override { return m_BufferSize; } - - public: - bool AddSize(const std::size_t count) override { return Resize(count + m_BufferSize); } - bool Resize(const std::size_t targetBufferSize); - - protected: - std::unique_ptr m_Buffer; - std::size_t m_BufferSize; - }; - - template - class ShrinkDynamicBufferOutManager : public DynamicBufferOutManager - { - public: - using Base = DynamicBufferOutManager; - using Base::DEFAULT_BEGIN_SIZE; - using Base::GROW_UP_BUFFER_SIZE; - using Base::DEBUG_RESIZE; - - using Base::GetBuffer; - using Base::GetBufferSize; - using Base::Resize; - - using Base::m_Buffer; - using Base::m_BufferSize; - - static constexpr float MEAN_SIZE_OVERFLOW = 4.2f; - static constexpr float MEAN_SIZE_RESIZE = 1.4f; - static constexpr float MEAN_CALCFACT_OLD = 5; - static constexpr float MEAN_CALCFACT_LAST = 1; - - public: - ShrinkDynamicBufferOutManager(std::size_t beginSize = DEFAULT_BEGIN_SIZE) - : Base(beginSize) - , m_MeanGeneratedSize(beginSize) - {} - - ~ShrinkDynamicBufferOutManager() override = default; - - protected: - void BeginContextImpl() override { ShrinkIfNeeded(); } - void ComputeGeneratedSizeImpl(std::size_t totalGeneratedLength) override - { - m_MeanGeneratedSize = (m_MeanGeneratedSize * MEAN_CALCFACT_OLD + totalGeneratedLength * MEAN_CALCFACT_LAST) / (MEAN_CALCFACT_OLD + MEAN_CALCFACT_LAST); - } - - public: - void ShrinkIfNeeded() - { - if (m_BufferSize > static_cast(m_MeanGeneratedSize * MEAN_SIZE_OVERFLOW)) Resize(static_cast(m_MeanGeneratedSize * MEAN_SIZE_RESIZE)); - } - - private: - std::size_t m_MeanGeneratedSize; - }; - - template - bool DynamicBufferOutManager::Resize(const std::size_t targetBufferSize) - { - std::size_t newBufferSize = targetBufferSize; - - if (m_BufferSize < targetBufferSize) - { - newBufferSize = m_BufferSize; - while (newBufferSize < targetBufferSize) - newBufferSize *= GROW_UP_BUFFER_SIZE; - } - - CharType* newBuffer = new CharType[newBufferSize]; - if (newBuffer == nullptr) return false; - - std::memcpy(newBuffer, m_Buffer.get(), std::min(newBufferSize, m_BufferSize)); - - if constexpr (DEBUG_RESIZE) std::cout << "Resize from " << m_BufferSize << " to " << newBufferSize << std::endl; - - m_Buffer.reset(newBuffer); - m_BufferSize = newBufferSize; - - return true; - } -} diff --git a/src/StreamFormat/FMT/Buffer/BufferOutManager/GivenBufferOutManager.h b/src/StreamFormat/FMT/Buffer/BufferOutManager/GivenBufferOutManager.h deleted file mode 100644 index 20a366e4..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferOutManager/GivenBufferOutManager.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "BasicBufferOutManager.h" - -namespace StreamFormat::FMT::Detail -{ - template - class GivenBufferOutManager : public BasicBufferOutManager - { - public: - template - GivenBufferOutManager(CharType (&buffer)[SIZE]) - : m_Buffer(buffer) - , m_BufferSize(SIZE) - {} - - GivenBufferOutManager(CharType* buffer, std::size_t bufferSize) - : m_Buffer(buffer) - , m_BufferSize(bufferSize) - {} - - ~GivenBufferOutManager() override = default; - - public: - CharType* GetBuffer() override { return m_Buffer; } - const CharType* GetBuffer() const override { return m_Buffer; } - std::size_t GetBufferSize() const override { return m_BufferSize; } - - public: - bool AddSize(const std::size_t /* count */) override { return false; } - - private: - CharType* m_Buffer; - std::size_t m_BufferSize; - }; -} diff --git a/src/StreamFormat/FMT/Buffer/BufferOutManager/StaticBufferOutManager.h b/src/StreamFormat/FMT/Buffer/BufferOutManager/StaticBufferOutManager.h deleted file mode 100644 index 8631710e..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferOutManager/StaticBufferOutManager.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "BasicBufferOutManager.h" - -namespace StreamFormat::FMT::Detail -{ - template - class StaticBufferOutManager : public BasicBufferOutManager - { - public: - ~StaticBufferOutManager() override = default; - - public: - CharType* GetBuffer() override { return m_Buffer; } - const CharType* GetBuffer() const override { return m_Buffer; } - std::size_t GetBufferSize() const override { return Count; } - - public: - bool AddSize(const std::size_t) override { return false; } - - private: - CharType m_Buffer[Count]; - }; -} diff --git a/src/StreamFormat/FMT/Buffer/BufferOutManip.h b/src/StreamFormat/FMT/Buffer/BufferOutManip.h deleted file mode 100644 index 49b0ac90..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferOutManip.h +++ /dev/null @@ -1,151 +0,0 @@ -#pragma once - -#include "BufferInfo.h" -#include "BufferManip.h" - -#include "BufferOutManager/BasicBufferOutManager.h" - -namespace StreamFormat::FMT::Detail -{ - template - class BufferOutInfo : public BufferInfo - { - public: - using typename BufferInfo::TChar; - - using BufferInfo::Buffer; - using BufferInfo::CurrentPos; - using BufferInfo::BufferEnd; - - using BufferInfo::Get; - using BufferInfo::Manip; - - public: - BufferOutInfo(BasicBufferOutManager& bufferOutManager) noexcept - : BufferInfo() - { - SetManager(bufferOutManager); - } - - public: - BasicBufferOutManager* Manager; - - public: - void SetManager(BasicBufferOutManager& bufferOutManager) - { - Manager = &bufferOutManager; - Manager->BeginContext(); - BufferManip(*this).Set(Manager->GetBuffer(), Manager->GetBufferSize()); - } - }; - - template - concept ConvertibleToBufferOutInfo = requires(T&& t) - { - BufferOutInfo(std::forward(t)); - }; - - template - class BufferOutManip - { - public: - constexpr inline BufferOutManip(BufferOutInfo& buffer) noexcept : Buffer(buffer) {} - public: - BufferOutInfo& Buffer; - - public: - void SetManager(BasicBufferOutManager& bufferOutManager) - { - Buffer.SetManager(bufferOutManager); - } - - void ComputeGeneratedSize() { Buffer.Manager->ComputeGeneratedSize(BufferAccess(Buffer).GetBufferCurrentSize()); } - - public: - bool AddSize(const std::size_t count) - { - if (Buffer.Manager == nullptr) throw Detail::FMTShouldNotEndHere{}; - if (Buffer.CurrentPos > Buffer.BufferEnd) throw Detail::FMTParseError{}; - std::size_t currentSize = BufferAccess(Buffer).GetBufferCurrentSize(); - if (Buffer.Manager->AddSize(count) == false) return false; - BufferManip(Buffer).Set(Buffer.Manager->GetBuffer(), Buffer.Manager->GetBufferSize()); - Buffer.CurrentPos = Buffer.Manager->GetBuffer() + currentSize; - return true; - } - - inline BufferManipResult Reserve(const std::size_t count = 1) - { - if (Buffer.CurrentPos + count <= Buffer.BufferEnd) - return true; - return AddSize(static_cast(count)); - } - - inline BufferManipResult Forward(const std::size_t count = 1) - { - if (Reserve(count)) - { - Buffer.CurrentPos += count; - return true; - } - return false; - } - - public: - inline void SetChar(const TChar c) { *Buffer.CurrentPos = c; } - inline BufferManipResult Pushback(const TChar c) - { - if (Reserve(1)) - { - *Buffer.CurrentPos++ = c; - return true; - } - return false; - } - inline BufferManipResult SetInverse(const TChar c) - { - if (BufferAccess(Buffer).CanMoveBackward(1)) - { - *--Buffer.CurrentPos = c; - return true; - } - return false; - } - inline void ForcePushback(const TChar c) { *Buffer.CurrentPos++ = c; } - inline void ForceSetInverse(const TChar c) { *--Buffer.CurrentPos = c; } - - public: - inline BufferManipResult Pushback(const TChar c, auto count) - { - if (Reserve(count)) - { - while (count-- > 0) - ForcePushback(c); - return true; - } - return false; - } - - public: - inline void AddSpaces(const auto count) { Pushback(' ', count); } - - protected: - template - inline void PushbackSeqImpl(const TChar c, const Rest... rest) - { - ForcePushback(c); - if constexpr (sizeof...(rest) > 0) PushbackSeqImpl(rest...); - } - - public: - template - inline BufferManipResult PushbackSeq(const CharToPush... ele) - { - if (Reserve(sizeof...(ele))) - { - PushbackSeqImpl(ele...); - return true; - } - return false; - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/BufferReadManip.h b/src/StreamFormat/FMT/Buffer/BufferReadManip.h deleted file mode 100644 index 90f49bd1..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferReadManip.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/BufferManip.h" - -namespace StreamFormat::FMT::Detail -{ - template - class BufferReadManip - { - public: - constexpr inline BufferReadManip(BufferInfo& buffer) noexcept : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - public: - template - constexpr BufferManipResult FastReadInteger(T& i) noexcept - { - T res = 0; - - bool sign = false; - if constexpr (std::is_signed_v) - { - sign = BufferTestManip(Buffer).IsEqualToForward('-'); - if (!BufferTestAccess(Buffer).IsADigit()) return false; - } - - while (BufferTestAccess(Buffer).IsADigit()) - res = res * static_cast(10) + static_cast(BufferManip(Buffer).ThrowIfFailed().GetAndForward() - static_cast('0')); - - i = sign ? -res : res; - return true; - } - - public: - template - constexpr inline BufferManipResult FastReadFloat(T& i, std::int32_t floatPrecision = -1) noexcept - { - BufferTestAccess access(Buffer); - BufferTestManip manip(Buffer); - - bool sign = manip.IsEqualToForward('-'); - - bool hasIntPart = false; - if (access.IsNotEqualTo('.')) - { - hasIntPart = access.IsADigit(); - if (hasIntPart == false) return false; - T res = 0; - while (access.IsADigit()) - res = res * static_cast(10) + static_cast(BufferManipException(Buffer).GetAndForward() - static_cast('0')); - i = sign ? -res : res; - } - - if (manip.IsEqualToForward('.') == false) return hasIntPart; - - if (floatPrecision < 0) - while (access.IsADigit() && BufferAccess(Buffer).IsEndOfString() == false) - BufferManip(Buffer).ForceForward(); - else - { - while (access.IsADigit() && floatPrecision > 0 && BufferAccess(Buffer).IsEndOfString() == false) - { - BufferManip(Buffer).ForceForward(); - floatPrecision--; - } - } - BufferManip(Buffer).ForceBackward(); - - T dec = (T)0; - while (access.IsADigit()) - { - dec += static_cast(BufferManip(Buffer).GetAndForceBackward() - '0'); - dec /= 10; - } - i += dec; - return true; - } - - public: - template - BufferManipResult FastReadCharPtr(const CharPtr* str, std::size_t sizeToCopy, bool isZeroEnded = true) - { - if (BufferAccess(Buffer).CanMoveForward(sizeToCopy) == false) - return BufferReadManip(Buffer).FastReadCharPtr(str, BufferAccess(Buffer).GetBufferRemainingSize(), isZeroEnded); - - // TODO : Opti with bigger types - while (sizeToCopy-- != 0) - *str++ = BufferManip(Buffer).GetAndForward(); - if (isZeroEnded) *str = 0; - - return true; - } - template - inline BufferManipResult FastReadCharArray(const CharStr (&str)[SIZE], bool isZeroEnded = true) - { - return FastReadCharPtr(str, SIZE); - } - template - inline BufferManipResult FastReadCharBound(const CharStr* begin, const CharStr* end, bool isZeroEnded = true) - { - return FastReadCharPtr(begin, end - begin - (isZeroEnded ? 1 : 0), isZeroEnded); - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/BufferTestManip.h b/src/StreamFormat/FMT/Buffer/BufferTestManip.h deleted file mode 100644 index 33b6a502..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferTestManip.h +++ /dev/null @@ -1,155 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/BufferManip.h" - -namespace StreamFormat::FMT::Detail -{ - template - class BufferTestAccess - { - public: - constexpr inline BufferTestAccess(const BufferInfo& buffer) noexcept : Buffer(buffer) {} - public: - const BufferInfo& Buffer; - - public: - constexpr inline BufferManipResult IsEqualTo(const TChar c) const noexcept { return Buffer.Get() == c; } - constexpr inline BufferManipResult IsNotEqualTo(const TChar c) const noexcept { return Buffer.Get() != c; } - template - constexpr inline BufferManipResult IsEqualTo(const TChar c, const CharToTest... ele) const noexcept - { - return IsEqualTo(c) || IsEqualTo(ele...); - } - template - constexpr inline BufferManipResult IsNotEqualTo(const TChar c, const CharToTest... ele) const noexcept - { - return IsNotEqualTo(c) && IsNotEqualTo(ele...); - } - - constexpr inline BufferManipResult NextIsEqualTo(const TChar c) const noexcept { return BufferAccess(Buffer).GetNextForce() + 1 == c; } - constexpr inline BufferManipResult NextIsNotEqualTo(const TChar c) const noexcept { return BufferAccess(Buffer).GetNextForce() + 1 != c; } - constexpr inline BufferManipResult PrevIsEqualTo(const TChar c) const noexcept { return BufferAccess(Buffer).GetPrevForce() - 1 == c; } - constexpr inline BufferManipResult PrevIsNotEqualTo(const TChar c) const noexcept { return BufferAccess(Buffer).GetPrevForce() - 1 != c; } - - public: - constexpr inline BufferManipResult IsLowerCase() const noexcept { return Buffer.Get() >= 'a' && Buffer.Get() <= 'z'; } - constexpr inline BufferManipResult IsUpperCase() const noexcept { return Buffer.Get() >= 'A' && Buffer.Get() <= 'Z'; } - constexpr inline BufferManipResult IsADigit() const noexcept { return Buffer.Get() >= '0' && Buffer.Get() <= '9'; } - - public: - template - constexpr BufferManipResult IsSame(const CharToTest* str, std::size_t size) const noexcept - { - if (size > BufferAccess(Buffer).GetBufferRemainingSize()) return false; - - const TChar* bufferStr = Buffer.CurrentPos; - bool isSame = true; - while (isSame && size != 0 && *str != 0) - { - isSame = *bufferStr++ == *str++; - --size; - } - if (size != 0 && *str != 0) isSame = false; - return isSame; - } - template - constexpr inline BufferManipResult IsSame(std::basic_string_view sv) const noexcept - { - return IsSame(sv.data(), sv.size()); - } - }; - - template - class BufferTestManip - { - public: - constexpr inline BufferTestManip(BufferInfo& buffer) noexcept : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - using TConstChar = std::remove_const_t; - - public: - BufferTestAccess Access() const noexcept { return BufferTestAccess(Buffer); } - - public: - template - constexpr inline BufferManipResult IsEqualToForward(const CharToTest... ele) noexcept - { - if (Access().IsEqualTo(ele...)) - return BufferManip(Buffer).Forward(); - return false; - } - template - constexpr inline BufferManipResult IsNotEqualForward(const CharToTest... ele) noexcept - { - if (Access().IsNotEqualTo(ele...)) - return BufferManip(Buffer).Forward(); - return false; - } - - public: - template - constexpr BufferManipResult IsSameForward(const CharToTest* str, std::size_t size) noexcept - { - if (Access().IsSame(str, size)) - return BufferManip(Buffer).Forward(size); - return false; - } - template - constexpr inline BufferManipResult IsSameForward(std::basic_string_view sv) noexcept - { - if (Access().IsSame(sv)) - return BufferManip(Buffer).Forward(sv.size()); - return false; - } - - public: - template - inline void Skip(const CharToTest... ele) noexcept { IsEqualToForward(ele...); } - template - inline void SkipAll(const CharToTest... ele) noexcept - { - while (Access().IsEqualTo(ele...) && BufferAccess(Buffer).CanMoveForward()) - BufferManip(Buffer).ForceForward(); - } - - public: - inline void SkipSpace() noexcept { Skip(' ', '\t'); } - inline void SkipBlank() noexcept { Skip(' ', '\t', '\n', '\r', '\v'); } - - inline void SkipAllSpaces() noexcept { SkipAll(' ', '\t'); } - inline void SkipAllBlanks() noexcept { SkipAll(' ', '\t', '\n', '\r', '\v'); } - - public: - template - inline void GoTo(const CharToTest... ele) noexcept - { - while (Access().IsNotEqualTo(ele...) && BufferAccess(Buffer).CanMoveForward()) - BufferManip(Buffer).ForceForward(); - } - template - inline void GoToForward(const CharToTest... ele) noexcept - { - GoTo(ele...); - BufferManip(Buffer).Forward(); - } - - public: - template - std::basic_string_view ViewExec(Func&& func) - { - TChar* begin = Buffer.CurrentPos; - func(); - TChar* end = Buffer.CurrentPos; - return std::basic_string_view(begin, end - begin); - } - - template - inline std::basic_string_view ViewUntil(CharToTest&&... c) - { - return ViewExec([&]{BufferTestManip(Buffer).GoTo(std::forward(c)...);}); - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/BufferWriteManip.h b/src/StreamFormat/FMT/Buffer/BufferWriteManip.h deleted file mode 100644 index ed7a28eb..00000000 --- a/src/StreamFormat/FMT/Buffer/BufferWriteManip.h +++ /dev/null @@ -1,159 +0,0 @@ -#pragma once - -#include "BufferInfo.h" -#include "BufferManip.h" -#include "BufferTestManip.h" -#include "BufferOutManip.h" - -#include -#include - -namespace StreamFormat::FMT::Detail -{ - class BufferWriteUtils - { - public: - template - static std::int32_t GetNumberOfDigitDec(T value) - { - if constexpr (std::numeric_limits::is_signed) - { - if (value < 0) value = -value; - } - std::int32_t nb = 0; - while (true) - { - if (value < 10) - return nb + 1; - else if (value < 100) - return nb + 2; - else if (value < 1000) - return nb + 3; - else if (value < 10000) - return nb + 4; - else - { - value /= static_cast(10000); - nb += 4; - } - } - } - }; - - template - class BufferWriteManip - { - public: - constexpr inline BufferWriteManip(BufferOutInfo& buffer) noexcept : Buffer(buffer) {} - public: - BufferOutInfo& Buffer; - - public: - static constexpr TChar BIN[2] = {'0', '1'}; - static constexpr TChar OCT[8] = {'0', '1', '2', '3', '4', '5', '6', '7'}; - static constexpr TChar UPPER_HEX[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - static constexpr TChar LOWER_HEX[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - - public: - template - requires std::is_integral_v - constexpr void FastWriteInteger(T i) - { - BufferOutManip manip(Buffer); - - if (i == 0) { manip.Pushback('0'); return; } - - if constexpr (std::is_signed_v) - { - if (i < 0) { manip.Pushback('-'); i = -i; } - } - - std::int32_t nbDigit = BufferWriteUtils::GetNumberOfDigitDec(i); - manip.Forward(nbDigit).ThrowIfFailed(); - while (i > 0) - { - if (BufferAccess(Buffer).IsOutOfBound()) - BufferAccess(Buffer).IsOutOfBound(); - manip.ForceSetInverse(i % 10 + '0'); - i /= 10; - } - manip.Forward(nbDigit).ThrowIfFailed(); - } - - public: - template - requires std::is_floating_point_v - void FastWriteFloat(T i, std::int32_t floatPrecision = 2) - { - BufferOutManip manip(Buffer); - - if (i == 0) - { manip.Pushback('0'); return; } - if (i < 0) - { manip.Pushback('-'); i = -i; } - - T k = std::trunc(i); - i = i - k; - std::int32_t nbDigit = BufferWriteUtils::GetNumberOfDigitDec(k); - manip.Forward(nbDigit); - std::int32_t nbDigit_ = nbDigit; - while (nbDigit_ > 0) - { - manip.ForceSetInverse(char(std::fmod(k, 10)) + '0'); - k /= 10; - nbDigit_--; - } - manip.Forward(nbDigit); - manip.Pushback('.'); - - while (floatPrecision-- >= 0) - { - TChar intPart = static_cast(std::trunc(i *= 10)); - manip.Pushback(intPart + '0'); - i -= intPart; - } - } - - public: - template - void FastWriteCharArray(const CharInput* str, std::size_t size) - { - if (BufferOutManip(Buffer).Reserve(size) == false) - return FastWriteCharArray(str, BufferAccess(Buffer).GetBufferRemainingSize()); - - // TODO: Opti with bigger types - while (size-- != 0 && *str != 0) - BufferOutManip(Buffer).ForcePushback(*str++); - } - template - inline void FastWriteString(std::basic_string_view sv) - { - FastWriteCharArray(sv.data(), sv.size()); - } - inline void FastWriteString(std::basic_string_view sv) - { - FastWriteCharArray(sv.data(), sv.size()); - } - template - inline void FastWriteStringLitteral(CharInput (&str)[SIZE]) - { - std::size_t size = SIZE; - while (str[size - 1] == 0) --size; - FastWriteCharArray(str, size); - } - - public: - template inline void BasicWriteType(std::basic_string_view str) { FastWriteString(str); } - template inline void BasicWriteType(CharInput (&str)[SIZE]) { FastWriteStringLitteral(str); } - template requires std::is_integral_v void BasicWriteType(T t) { FastWriteInteger(t); } - template requires std::is_floating_point_v void BasicWriteType(T t) { FastWriteFloat(t); } - - template - inline void BasicWriteType(Type&& type, Rest&&... rest) - { - BasicWriteType(type); - if constexpr (sizeof...(rest) > 0) - BasicWriteType(std::forward(rest)...); - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/FMTBufferOutManip.h b/src/StreamFormat/FMT/Buffer/FMTBufferOutManip.h deleted file mode 100644 index 49857bcf..00000000 --- a/src/StreamFormat/FMT/Buffer/FMTBufferOutManip.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include "BufferInfo.h" -#include "BufferOutManip.h" -#include "BufferTestManip.h" - -namespace StreamFormat::FMT::Detail -{ - template - class FMTBufferOutInfo : public BufferOutInfo - { - public: - using typename BufferOutInfo::TChar; - - using BufferOutInfo::Buffer; - using BufferOutInfo::CurrentPos; - using BufferOutInfo::BufferEnd; - - using BufferOutInfo::Get; - using BufferOutInfo::Manip; - - using BufferOutInfo::Manager; - - public: - FMTBufferOutInfo(BasicBufferOutManager& bufferOutManager) noexcept - : BufferOutInfo(bufferOutManager) - {} - - public: - std::size_t NoStride = 0; - std::size_t Indent = 0; - }; - - template - class FMTBufferOutManip - { - public: - FMTBufferOutManip(FMTBufferOutInfo& buffer) : Buffer(buffer) {} - public: - FMTBufferOutInfo& Buffer; - - public: - constexpr inline void AddNoStride(const std::size_t noStride) noexcept { Buffer.NoStride += noStride; } - - constexpr inline void AddIndent(const std::size_t indent) noexcept { Buffer.Indent += indent; } - constexpr inline void RemoveIndent(const std::size_t indent) noexcept { Buffer.Indent -= indent; } - constexpr inline void SetIndent() noexcept { Buffer.Indent = BufferManip(Buffer).GetBufferCurrentSize() - Buffer.NoStride; } - - public: - constexpr inline void NewLineIndent() - { - BufferOutManip(Buffer).Pushback('\n'); - BufferOutManip(Buffer).Pushback(' ', Buffer.Indent); - } - - constexpr inline void PushbackCheckIndent(const TChar c) - { - BufferOutManip(Buffer).Pushback(c); - if (c == '\n') BufferOutManip(Buffer).Pushback(' ', Buffer.Indent); - } - }; - - template - class FMTBufferParamsManip - { - public: - FMTBufferParamsManip(BufferInfo& buffer) : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - public: - template - inline void ParamGoTo(const CharToTest... ele) - { - BufferTestManip(Buffer).GoTo(ele..., '}'); - } - template - inline void ParamGoToForward(const CharToTest... ele) - { - BufferTestManip(Buffer).GoToForward(ele..., '}'); - } - - inline BufferManipResult IsBeginOfParameter() - { - return BufferTestAccess(Buffer).IsEqualTo('{'); - } - inline BufferManipResult IsEndOfParameter() - { - return BufferTestAccess(Buffer).IsEqualTo('}'); - } - - public: - template - bool NextIsNamedArgs(const std::basic_string_view& sv) - { - BufferTestAccess access(Buffer); - BufferTestManip manip(Buffer); - - TChar* const oldpos = Buffer.CurrentPos; - if (manip.IsSameForward(sv) && (access.IsEqualTo(':') || access.IsEqualTo('}'))) return true; - Buffer.CurrentPos = oldpos; - return false; - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/FMTBufferReadManip.h b/src/StreamFormat/FMT/Buffer/FMTBufferReadManip.h deleted file mode 100644 index 29eb3a6e..00000000 --- a/src/StreamFormat/FMT/Buffer/FMTBufferReadManip.h +++ /dev/null @@ -1,240 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/Utils/BufferShiftManip.h" -#include "StreamFormat/FMT/Buffer/BufferManip.h" -#include "StreamFormat/FMT/Buffer/BufferTestManip.h" -#include "StreamFormat/FMT/Buffer/BufferReadManip.h" - -namespace StreamFormat::FMT::Detail -{ - template - class FMTBufferReadManip - { - public: - FMTBufferReadManip(BufferInfo& buffer) : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - public: - template - void ReadInteger(T& i, ShiftInfo shift = ShiftInfo{}) - { - BufferShiftReadManip shiftManip(Buffer); - Detail::BufferTestAccess access(Buffer); - Detail::BufferTestManip manip(Buffer); - T res = 0; - - shiftManip.SkipShiftBeginSpace(shift); - - bool sign = false; - if constexpr (std::is_signed_v) - { - sign = manip.IsEqualToForward('-'); - if (sign) --shift.Size; - } - - access.IsADigit(); - - while (access.IsADigit()) - { - res = res * 10 + (BufferManipException(Buffer).GetAndForward() - '0'); - --shift.Size; - } - - shiftManip.SkipShiftEnd(shift); - - if (shift.Size > 0) throw FMTParseError(); - - i = sign ? -res : res; - } - public: - template - void ReadFloat(T& i, std::int32_t floatPrecision = -1, ShiftInfo shift = ShiftInfo{}) - { - BufferShiftReadManip shiftManip(Buffer); - Detail::BufferTestAccess access(Buffer); - Detail::BufferTestManip manip(Buffer); - - shiftManip.SkipShiftBeginSpace(shift); - - bool sign = manip.IsEqualToForward('-'); - if (sign) --shift.Size; - - T res = 0; - - bool hasIntPart = false; - if (access.IsNotEqualTo('.')) - { - hasIntPart = access.IsADigit(); - if (hasIntPart == false) return; - while (access.IsADigit()) - { - res = res * 10 + (BufferManipException(Buffer).GetAndForward() - '0'); - --shift.Size; - } - } - - sign ? i = -res : i = res; - if (manip.IsEqualToForward('.') == false) return; - - if (floatPrecision <= 0) - while (access.IsADigit() && access.IsEndOfString() == false) - { - BufferManip(Buffer).ForceForward(); - --shift.Size; - } - else - { - while (BufferAccess(Buffer).IsADigit() && floatPrecision > 0 && BufferAccess(Buffer).IsEndOfString() == false) - { - BufferManip(Buffer).ForceForward(); - floatPrecision--; - --shift.Size; - } - } - BufferManip(Buffer).ForceBackward(); - - T dec = (T)0; - while (access.IsADigit()) - { - dec += static_cast(BufferManip(Buffer).GetAndForceBackward() - '0'); - dec /= 10; - } - - shiftManip.SkipShiftEnd(shift); - - if (shift.Size > 0) throw FMTParseError(); - - sign ? i = -res - dec : i = res + dec; - } - - public: - template - void ReadIntegerH(T& i, std::uint8_t digitSize, std::uint8_t (&digitLUT)(TChar), TChar base_prefix = '\0', ShiftInfo shift = ShiftInfo{}) - { - BufferShiftReadManip shiftManip(Buffer); - Detail::BufferTestAccess access(Buffer); - Detail::BufferTestManip manip(Buffer); - - shift.Size -= sizeof(T) * 8; - if (base_prefix != '\0') shift.Size -= 2; - - shiftManip.SkipShiftBeginSpace(shift); - - if (base_prefix != '\0') - { manip.Skip('0'); manip.Skip(base_prefix); } - - T res = 0; - - while (digitLUT(Buffer.Get()) != std::numeric_limits::max()) - { - res = res << digitSize; - res += digitLUT(Buffer.Get()); - BufferManip(Buffer).ForceForward(); - } - - shiftManip.SkipShiftEnd(shift); - - if (shift.Size > 0) throw FMTParseError(); - - i = res; - } - - protected: - static constexpr std::uint8_t DigitLUT_BIN(TChar in) - { - if (in == '0') return 0; - if (in == '1') return 1; - return std::numeric_limits::max(); - } - static constexpr std::uint8_t DigitLUT_OCT(TChar in) - { - if (in >= '0' && in <= '7') - return in - '0'; - return std::numeric_limits::max(); - } - static constexpr std::uint8_t DigitLUT_DEC(TChar in) - { - if (in >= '0' && in <= '9') - return in - '0'; - return std::numeric_limits::max(); - } - static constexpr std::uint8_t DigitLUT_HEXUPPER(TChar in) - { - if (in >= '0' && in <= '9') - return in - '0'; - if (in >= 'A' && in <= 'F') - return in - 'A'; - return std::numeric_limits::max(); - } - static constexpr std::uint8_t DigitLUT_HEXLOWER(TChar in) - { - if (in >= '0' && in <= '9') - return in - '0'; - if (in >= 'a' && in <= 'f') - return in - 'a'; - return std::numeric_limits::max(); - } - - public: - template - void ReadIntegerFormatData(T& i, const FormatData& formatData) - { - if (formatData.HasSpec) - { - switch (formatData.IntegerPrint) - { - case IntegerPrintBase::Dec: - if (formatData.Shift.Type == ShiftInfo::ShiftType::Nothing) - return BufferReadManip(Buffer).FastReadInteger(i).ThrowIfFailed(); - else - return ReadInteger(i, formatData.Shift); - case IntegerPrintBase::Bin: - case IntegerPrintBase::BinUpper: - return ReadIntegerH(i, 1, DigitLUT_BIN, formatData.PrefixSuffix ? (char)formatData.IntegerPrint : '\0', formatData.Shift); - case IntegerPrintBase::Oct: - case IntegerPrintBase::OctUpper: - return ReadIntegerH(i, 3, DigitLUT_OCT, formatData.PrefixSuffix ? (char)formatData.IntegerPrint : '\0', formatData.Shift); - case IntegerPrintBase::Hex: - return ReadIntegerH(i, 4, DigitLUT_HEXLOWER, formatData.PrefixSuffix ? (char)formatData.IntegerPrint : '\0', formatData.Shift); - case IntegerPrintBase::HexUpper: - return ReadIntegerH(i, 4, DigitLUT_HEXUPPER, formatData.PrefixSuffix ? (char)formatData.IntegerPrint : '\0', formatData.Shift); - } - } - return BufferReadManip(Buffer).FastReadInteger(i).ThrowIfFailed(); - } - template - void ReadFloatFormatData(T& i, const FormatData& formatData) - { - if (formatData.HasSpec) - { - if (formatData.ShiftType == ShiftInfo::ShiftType::Nothing) - return BufferReadManip(Buffer).FastReadFloat(i, formatData.FloatPrecision).ThrowIfFailed(); - else - return ReadFloat(i, formatData.FloatPrecision, formatData.Shift); - } - return BufferReadManip(Buffer).FastReadFloat(i, formatData.FloatPrecision).ThrowIfFailed(); - } - - public: - template - void ReadCharPtr(const CharStr* str, std::size_t sizeContainer, std::size_t sizeToWrite, ShiftInfo shift = ShiftInfo{}) - { - // FIXME - // TODO - throw FMTImplError{}; - } - - template - inline void ReadCharArray(const CharStr (&str)[SIZE], ShiftInfo shift = ShiftInfo{}) - { - ReadCharPtr(str, SIZE, 0, shift); - } - template - inline void ReadCharBound(const CharStr* begin, const CharStr* end, ShiftInfo shift = ShiftInfo{}) - { - ReadCharPtr(begin, end - begin, 0, shift); - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/FMTBufferWriteManip.h b/src/StreamFormat/FMT/Buffer/FMTBufferWriteManip.h deleted file mode 100644 index ca354506..00000000 --- a/src/StreamFormat/FMT/Buffer/FMTBufferWriteManip.h +++ /dev/null @@ -1,253 +0,0 @@ -#pragma once - -#include "BufferInfo.h" -#include "FMTBufferOutManip.h" -#include "Utils/BufferShiftManip.h" -#include "BufferOutManip.h" -#include "BufferWriteManip.h" - -#include - -namespace StreamFormat::FMT::Detail -{ - template - class FMTBufferWriteManip - { - public: - FMTBufferWriteManip(FMTBufferOutInfo& buffer) : Buffer(buffer) {} - public: - FMTBufferOutInfo& Buffer; - - public: - template - void WriteInteger(T i, Detail::ShiftInfo shift = Detail::ShiftInfo{}) - { - shift.Print.ValidateForNumber(); - - std::int32_t nbDigit = BufferWriteUtils::GetNumberOfDigitDec(i); - - shift.Size -= nbDigit; - if (i < 0) --shift.Size; - - if (shift.Size <= 0) return BufferWriteManip(Buffer).FastWriteInteger(i); - - if (!shift.Print.BeforeIsADigit()) BufferShiftWriteManip(Buffer).WriteShiftBegin(shift); - if (i < 0) - { - BufferOutManip(Buffer).Pushback('-'); - i = -i; - } - if (shift.Print.BeforeIsADigit()) BufferShiftWriteManip(Buffer).WriteShiftRightAll(shift); - - if (i == 0) - BufferOutManip(Buffer).Pushback('0'); - else - { - BufferOutManip(Buffer).Forward(nbDigit); - std::int32_t nbDigit_ = nbDigit; - while (nbDigit_ > 0) - { - BufferOutManip(Buffer).ForceSetInverse(i % 10 + '0'); - i /= 10; - nbDigit_--; - } - BufferOutManip(Buffer).Forward(nbDigit); - } - - BufferShiftWriteManip(Buffer).WriteShiftEnd(shift); - } - - public: - template - void WriteFloat(T i, std::int32_t floatPrecision = 2, Detail::ShiftInfo shift = Detail::ShiftInfo{}) - { - shift.Print.ValidateForNumber(); - - std::int32_t nbDigit = BufferWriteUtils::GetNumberOfDigitDec(std::trunc(i)); - - shift.Size -= nbDigit + floatPrecision + 1; - if (i < 0) --shift.Size; - - if (shift.Size <= 0) return BufferWriteManip(Buffer).FastWriteFloat(i, floatPrecision); - - if (!shift.Print.BeforeIsADigit()) BufferShiftWriteManip(Buffer).WriteShiftBegin(shift); - if (i < 0) - { - BufferOutManip(Buffer).Pushback('-'); - i = -i; - } - if (shift.Print.BeforeIsADigit()) BufferShiftWriteManip(Buffer).WriteShiftRightAll(shift); - - T k = std::trunc(i); - if (k == 0) - BufferOutManip(Buffer).Pushback('0'); - else - { - BufferOutManip(Buffer).Forward(nbDigit); - std::int32_t nbDigit_ = nbDigit; - while (nbDigit_ > 0) - { - BufferOutManip(Buffer).ForceSetInverse(char(std::fmod(i, 10)) + '0'); - k /= 10; - nbDigit_--; - } - BufferOutManip(Buffer).Forward(nbDigit); - } - - BufferOutManip(Buffer).Pushback('.'); - i -= k; - while (floatPrecision-- != 0) - { - T decimal = std::trunc(i *= 10); - BufferOutManip(Buffer).Pushback((char)decimal + '0'); - i -= decimal; - } - - BufferShiftWriteManip(Buffer).WriteShiftEnd(shift); - } - - public: - template - void WriteIntegerH(T i, std::uint8_t digitSize, const TChar* const lut, TChar base_prefix = '\0', ShiftInfo shift = ShiftInfo{}) - { - BufferOutManip manip(Buffer); - - std::int32_t digitCount = sizeof(T) * 8; - { - // Remove leading 0 - std::int32_t lastPosWithData = 0; - std::int32_t k = digitCount + 1; - T cpyI = i; - while (--k != 0) - { - if ((cpyI & (0b1 << digitSize)) != 0) lastPosWithData = k; - cpyI = cpyI >> digitSize; - } - digitCount -= lastPosWithData; - } - - if (base_prefix != '\0') - { - BufferOutManip(Buffer).Pushback('0'); - BufferOutManip(Buffer).Pushback(base_prefix); - } - - manip.Forward(digitCount); - std::int32_t k = digitCount + 1; - while (--k != 0) - { - manip.ForceSetInverse(lut[i & (0b1 << digitSize)]); - i = i >> digitSize; - } - manip.Forward(digitCount); - } - - public: - template - void WriteIntegerFormatData(T i, const FormatData& formatData) - { - if (formatData.HasSpec) - { - switch (formatData.IntegerPrint) - { - case IntegerPrintBase::Dec: - if (formatData.Shift.Type == ShiftInfo::ShiftType::Nothing) - return BufferWriteManip(Buffer).FastWriteInteger(i); - else - return WriteInteger(i, formatData.Shift); - case IntegerPrintBase::Bin: - case IntegerPrintBase::BinUpper: - return WriteIntegerH(i, 1, BufferWriteManip::BIN, formatData.PrefixSuffix ? (char)formatData.IntegerPrint : '\0', formatData.Shift); - case IntegerPrintBase::Oct: - case IntegerPrintBase::OctUpper: - return WriteIntegerH(i, 3, BufferWriteManip::OCT, formatData.PrefixSuffix ? (char)formatData.IntegerPrint : '\0', formatData.Shift); - case IntegerPrintBase::Hex: - return WriteIntegerH(i, 4, BufferWriteManip::LOWER_HEX, formatData.PrefixSuffix ? (char)formatData.IntegerPrint : '\0', formatData.Shift); - case IntegerPrintBase::HexUpper: - return WriteIntegerH(i, 4, BufferWriteManip::UPPER_HEX, formatData.PrefixSuffix ? (char)formatData.IntegerPrint : '\0', formatData.Shift); - - } - } - return BufferWriteManip(Buffer).FastWriteInteger(i); - } - template - void WriteFloatFormatData(T i, const FormatData& formatData) - { - if (formatData.HasSpec) - { - if (formatData.Shift.Type != ShiftInfo::ShiftType::Nothing) - return WriteFloat(i, formatData.FloatPrecision, formatData.Shift); - } - - return BufferWriteManip(Buffer).FastWriteFloat(i, formatData.FloatPrecision); - } - - public: - template - inline void WriteIndentCharPtr(const CharStr* str, std::size_t size) - { - while (size > 0) - { - const CharStr* const begin = str; - while (size > 0 && *str != '\n') - { - ++str, --size; - } - const CharStr* const end = str; - - BufferWriteManip(Buffer).FastWriteCharArray(begin, end - begin); - - if (size > 0 && *str == '\n') - { - FMTBufferOutManip(Buffer).NewLineIndent(); - ++str; - --size; - } - } - } - template - inline void WriteIndentCharBound(const CharStr* begin, const CharStr* end) - { - WriteIndentCharPtr(begin, end - begin); - } - template - inline void WriteIndentString(std::basic_string_view str) - { - WriteIndentCharPtr(str.data(), str.size()); - } - - template - inline void WriteCharPtr(const CharStr* str, std::size_t size, ShiftInfo& shift) - { - if (shift.Size <= 0) - return BufferWriteManip(Buffer).FastWriteCharArray(str, size); - - BufferOutManip(Buffer).Reserve(std::max(static_cast(shift.Size), size)).ThrowIfFailed(); - - if (static_cast(shift.Size) > size) - { - shift.Size -= static_cast(size); - - BufferShiftWriteManip(Buffer).WriteShiftBegin(shift); - - BufferWriteManip(Buffer).FastWriteCharArray(str, size); - - BufferShiftWriteManip(Buffer).WriteShiftEnd(shift); - } - else - { - BufferWriteManip(Buffer).FastWriteCharArray(str, size); - } - } - template - inline void WriteCharBound(const CharStr* begin, const CharStr* end, ShiftInfo& shift) - { - WriteCharPtr(begin, end - begin, shift); - } - template - inline void WriteString(std::basic_string_view str, ShiftInfo& shift) - { - WriteCharPtr(str.data(), str.size(), shift); - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/Utils/BufferGlobberManip.h b/src/StreamFormat/FMT/Buffer/Utils/BufferGlobberManip.h deleted file mode 100644 index e55549e4..00000000 --- a/src/StreamFormat/FMT/Buffer/Utils/BufferGlobberManip.h +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/BufferManip.h" - -namespace StreamFormat::FMT::Detail -{ - template - class Globber - { - public: - enum class PatternMatchType - { - MatchBiggest, - MatchSmallest - }; - - private: - static const TChar* BufferInExecGlob_(BufferInfo& bufferIn, BufferInfo& glob) - { - if (BufferAccess(glob).IsEndOfString()) return bufferIn.CurrentPos; - - if (BufferAccess(bufferIn).IsEndOfString()) return nullptr; - - if (BufferTestAccess(glob).IsEqualTo('?')) - { - BufferManip(glob).Forward(); - BufferManip(bufferIn).Forward(); - return BufferInExecGlob_(bufferIn, glob); - } - else if (BufferTestAccess(glob).IsEqualTo('*')) - { - BufferManip(glob).Forward(); - const TChar* further = BufferInExecGlob_(bufferIn, glob); - while (BufferAccess(bufferIn).CanMoveForward()) - { - BufferManip(bufferIn).Forward(); - const TChar* last = BufferInExecGlob_(bufferIn, glob); - if (last > further || further == nullptr) further = last; - } - return further; - } - else if (BufferTestAccess(glob).IsEqualTo('[')) - { - BufferManip(bufferIn).Forward(); - const TChar* begin = glob.CurrentPos; - BufferTestManip(glob).GoToForward(']'); - const TChar* end = glob.CurrentPos; - - BufferInfoView charSet(begin, end - begin); - - bool is_inverted = BufferTestManip(glob).IsEqualToForward('!'); - TChar toMatch = BufferManipException(bufferIn).GetAndForward(); - bool found = false; - - while (found == false && BufferAccess(charSet).CanMoveForward()) - { - if (BufferTestAccess(charSet).IsEqualTo(toMatch)) - { - found = true; - break; - } - - if (BufferTestAccess(charSet).IsEqualTo('-')) - { - TChar beginSubSet = BufferAccess(charSet).GetPrevForce(); - TChar endSubSet = BufferAccess(charSet).GetNextForce(); - if (toMatch >= beginSubSet && toMatch <= endSubSet) - { - found = true; - break; - } - } - - BufferManip(charSet).Forward(); - } - - if (found && is_inverted == false) - return BufferInExecGlob_(bufferIn, glob); - else if (found == false && is_inverted == true) - return BufferInExecGlob_(bufferIn, glob); - return nullptr; - } - - if (bufferIn.Get() == glob.Get()) - { - BufferManip(glob).Forward(); - BufferManip(bufferIn).Forward(); - return BufferInExecGlob_(bufferIn, glob); - } - return nullptr; - } - - public: - static void BufferInExecGlob(BufferInfo& bufferIn, BufferInfo& glob, [[maybe_unused]] PatternMatchType patternMatchtype = PatternMatchType::MatchBiggest) - { - const TChar* furtherPointMatched = BufferInExecGlob_(bufferIn, glob); - if (furtherPointMatched != nullptr) - bufferIn.CurrentPos = furtherPointMatched; - } - }; - - template - class BufferGlobberManip - { - public: - constexpr inline BufferGlobberManip(BufferInfo& buffer) noexcept : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - public: - BufferManipResult FastReadCharPtrGlobber(std::basic_string_view globPattern, TChar* str, std::size_t sizeToCopy) - { - BufferInfo globber(globPattern); - const TChar* begin = Buffer.CurrentPos; - Globber::BufferInExecGlob(*this, globber); - const TChar* end = Buffer.CurrentPos; - - BufferInfo subContext(begin, end); - return BufferReadManip(subContext).FastReadCharPtr(str, sizeToCopy); - } - - BufferManipResult FastReadCharPtrRegex(std::basic_string_view regexPattern, TChar* str, std::size_t sizeToCopy) - { - throw FMTImplError{}; - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/Utils/BufferShiftManip.h b/src/StreamFormat/FMT/Buffer/Utils/BufferShiftManip.h deleted file mode 100644 index 31f15fe1..00000000 --- a/src/StreamFormat/FMT/Buffer/Utils/BufferShiftManip.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/BufferOutManip.h" - -namespace StreamFormat::FMT::Detail -{ - template - class BufferShiftWriteManip - { - public: - BufferShiftWriteManip(BufferOutInfo& buffer) : Buffer(buffer) {} - public: - BufferOutInfo& Buffer; - - public: - inline void WriteShiftCenterBegin(Detail::ShiftInfo& shift) - { - if (shift.Type == Detail::ShiftInfo::ShiftType::CenterRight || shift.Type == Detail::ShiftInfo::ShiftType::CenterLeft) - { - std::int32_t shift_ = shift.Size / 2; - if (shift.Type == Detail::ShiftInfo::ShiftType::CenterLeft) shift_ = (shift.Size + 1) / 2; - BufferOutManip(Buffer).Pushback(shift.Print.Before, shift.Size - shift_); - shift.Size = shift_; - } - } - - inline void WriteShiftCenterEnd(Detail::ShiftInfo& shift) - { - if (shift.Type == Detail::ShiftInfo::ShiftType::CenterRight || shift.Type == Detail::ShiftInfo::ShiftType::CenterLeft) - BufferOutManip(Buffer).Pushback(shift.Print.After, shift.Size); - } - - inline void WriteShiftRightAll(Detail::ShiftInfo& shift) - { - if (shift.Type == Detail::ShiftInfo::ShiftType::Right) - BufferOutManip(Buffer).Pushback(shift.Print.Before, shift.Size); - } - - inline void WriteShiftLeftAll(Detail::ShiftInfo& shift) - { - if (shift.Type == Detail::ShiftInfo::ShiftType::Left) - BufferOutManip(Buffer).Pushback(shift.Print.After, shift.Size); - } - - inline void WriteShiftBegin(Detail::ShiftInfo& shift) - { - WriteShiftCenterBegin(shift); - WriteShiftRightAll(shift); - } - - inline void WriteShiftEnd(Detail::ShiftInfo& shift) - { - WriteShiftLeftAll(shift); - WriteShiftCenterEnd(shift); - } - }; - - template - class BufferShiftReadManip - { - public: - BufferShiftReadManip(BufferInfo& buffer) : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - public: - void SkipShiftBeginSpace(Detail::ShiftInfo& shift) - { - if (shift.Print.BeforeIsADigit() == false) return; - if (shift.Type == Detail::ShiftInfo::ShiftType::Right || shift.Type == Detail::ShiftInfo::ShiftType::CenterLeft || shift.Type == Detail::ShiftInfo::ShiftType::CenterRight) - while (Buffer.Get() == ' ') - { - BufferManip(Buffer).Forward(); - --shift.Size; - } - } - - void SkipShiftEnd(Detail::ShiftInfo& shift) - { - if (shift.Type == Detail::ShiftInfo::ShiftType::Left || shift.Type == Detail::ShiftInfo::ShiftType::CenterLeft || shift.Type == Detail::ShiftInfo::ShiftType::CenterRight) - while (Buffer.Get() == ' ' && shift.Size > 0) - { - BufferManip(Buffer).Forward(); - --shift.Size; - } - } - }; -} diff --git a/src/StreamFormat/FMT/Buffer/Utils/BufferUtils.h b/src/StreamFormat/FMT/Buffer/Utils/BufferUtils.h deleted file mode 100644 index 84bc313e..00000000 --- a/src/StreamFormat/FMT/Buffer/Utils/BufferUtils.h +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/BufferOutManip.h" -#include "StreamFormat/FMT/Buffer/BufferTestManip.h" -#include "StreamFormat/FMT/Buffer/BufferWriteManip.h" -#include "StreamFormat/FMT/Buffer/BufferReadManip.h" - -#include "StreamFormat/FMT/Buffer/BufferOutManager/DynamicBufferOutManager.h" -#include "StreamFormat/FMT/Buffer/BufferOutManager/GivenBufferOutManager.h" -#include "StreamFormat/FMT/Buffer/BufferOutManager/StaticBufferOutManager.h" - -namespace StreamFormat::FMT::Detail -{ - template - class BufferUtilsManip - { - public: - constexpr inline BufferUtilsManip(BufferInfo& buffer) noexcept : Buffer(buffer) {} - public: - BufferInfo& Buffer; - - using TConstChar = std::remove_const_t; - - public: - static constexpr std::size_t GET_WORD_FROM_LIST_NOT_FOUND = (std::numeric_limits::max)(); - - template - std::size_t GetWordFromList(const std::basic_string_view (&data)[SIZE], const std::size_t defaultValue = GET_WORD_FROM_LIST_NOT_FOUND) - { - for (std::size_t idx = 0; idx < SIZE; ++idx) - if (BufferTestManip(Buffer).IsSameForward(data[idx])) return idx; - return defaultValue; - } - - // TODO: use static map ? - template - using DictPairs = std::pair, T>; - - template - T GetWordFromDictPairs(const DictPairs (&data)[SIZE], std::convertible_to auto defaultValue = T{}) - { - for (std::size_t idx = 0; idx < SIZE; ++idx) - if (BufferTestManip(Buffer).IsSameForward(data[idx].first)) return data[idx].second; - return defaultValue; - } - }; - - class BufferUtils - { - public: - template - static void ParseEscapedQuotedString(Detail::BufferInfo& buffer, Detail::BufferOutInfo& stringOut) - { - Detail::BufferTestManip(buffer).Skip('"'); - while (Detail::BufferAccess(buffer).IsEndOfString() == false) - { - Detail::BufferWriteManip(stringOut).FastWriteString( - Detail::BufferTestManip(buffer).ViewUntil('"', '\\') - ); - - if (Detail::BufferTestAccess(buffer).IsEqualTo('"')) break; - - Detail::BufferTestManip(buffer).Skip('\\'); - switch (buffer.Get()) - { - // TODO : Do all others escape char - case '"': - Detail::BufferOutManip(stringOut).Pushback('"'); - break; - case 't': - Detail::BufferOutManip(stringOut).Pushback('\t'); - break; - case 'r': - Detail::BufferOutManip(stringOut).Pushback('\r'); - break; - case 'n': - Detail::BufferOutManip(stringOut).Pushback('\n'); - break; - default: - break; - } - } - Detail::BufferTestManip(buffer).Skip('"'); - } - - template - static void FormatEscapedQuotedString(Detail::BufferOutInfo& buffer, Detail::BufferInfo& stringIn) - { - Detail::BufferOutManip(buffer).Pushback('"'); - while (Detail::BufferAccess(stringIn).IsEndOfString() == false) - { - Detail::BufferWriteManip(buffer).FastWriteString( - Detail::BufferTestManip(stringIn).ViewUntil('\\') - ); - - if (Detail::BufferAccess(stringIn).IsEndOfString()) break; - - Detail::BufferTestManip(stringIn).Skip('\\'); - switch (stringIn.Get()) - { - // TODO : Do all others escape char - case '"': - Detail::BufferOutManip(buffer).Pushback('"'); - break; - case 't': - Detail::BufferOutManip(buffer).Pushback('\t'); - break; - case 'r': - Detail::BufferOutManip(buffer).Pushback('\r'); - break; - case 'n': - Detail::BufferOutManip(buffer).Pushback('\n'); - break; - default: - break; - } - } - Detail::BufferOutManip(buffer).Pushback('"'); - } - }; -} diff --git a/src/StreamFormat/FMT/Context/BasicContext/BasicArgsInterface.h b/src/StreamFormat/FMT/Context/BasicContext/BasicArgsInterface.h deleted file mode 100644 index 30cc38d8..00000000 --- a/src/StreamFormat/FMT/Context/BasicContext/BasicArgsInterface.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/ConvertTraits.h" -#include "StreamFormat/FMT/Detail/Detail.h" - -#include -#include -#include - -namespace StreamFormat::FMT::Context -{ - template - class BasicContext; - - template - class ContextExecutor; -} - -namespace StreamFormat::FMT::Detail -{ - struct PointerID - { - const std::type_info& TypeInfo; - void* Ptr = nullptr; - }; - - template - class BasicArgsInterface - { - public: - BasicArgsInterface() {} - virtual ~BasicArgsInterface() = default; - - public: - virtual size_t Size() = 0; - - public: - virtual void RunTypeAtIndex(std::int32_t idx) = 0; - - virtual std::int32_t GetIndexOfCurrentNamedArg(BufferInfoView& format) = 0; - virtual std::int32_t GetFormatIndexAt(std::int32_t idx) = 0; - - virtual PointerID GetTypeAt(std::int32_t idx) = 0; - virtual typename std::basic_string_view GetStringAt(std::int32_t idx) = 0; - virtual int64_t GetIntAt(std::int32_t idx) = 0; - - public: - template - const T* GetTypeAtIndex(std::int32_t idx) - { - PointerID ptr = GetTypeAt(idx); - if (ptr.TypeInfo != typeid(T)) - return nullptr; - return static_cast(ptr.Ptr); - } - - template - void RunFuncFromTypeAtIndex(std::int32_t idx, std::function func) - { - const T* value = GetTypeAtIndex(idx); - if (value != nullptr) func(*value); - } - }; - - template - class EmptyContextArgsTupleInterface : public BasicArgsInterface - { - public: - EmptyContextArgsTupleInterface() {} - ~EmptyContextArgsTupleInterface() override = default; - - public: - size_t Size() override { return 0; } - - public: - void RunTypeAtIndex(std::int32_t) override {} - - std::int32_t GetIndexOfCurrentNamedArg(BufferInfoView& format) override { return std::int32_t{-1}; } - std::int32_t GetFormatIndexAt(std::int32_t) override { return std::int32_t{-1}; } - - PointerID GetTypeAt(std::int32_t) override { return PointerID{.TypeInfo = typeid(void), .Ptr = nullptr}; } - std::basic_string_view GetStringAt(std::int32_t) override { return ""; } - std::int64_t GetIntAt(std::int32_t) override { return 0; } - }; -} diff --git a/src/StreamFormat/FMT/Context/BasicContext/BasicContext.h b/src/StreamFormat/FMT/Context/BasicContext/BasicContext.h deleted file mode 100644 index 59d1754a..00000000 --- a/src/StreamFormat/FMT/Context/BasicContext/BasicContext.h +++ /dev/null @@ -1,172 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/ConvertTraits.h" -#include "StreamFormat/FMT/Detail/Detail.h" - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/BufferManip.h" -#include "StreamFormat/FMT/Buffer/BufferTestManip.h" -#include "StreamFormat/FMT/Buffer/BufferReadManip.h" - -#include "BasicArgsInterface.h" - -#include "ITextPropertiesExecutor.h" -#include "TextPropertiesManager.h" - -namespace StreamFormat::FMT::Context -{ - template - class BasicContext; - - template - class ContextExecutor - { - public: - ContextExecutor(Detail::ITextPropertiesExecutor& textPropertiesExecutor) - : Data{} - , TextManager{textPropertiesExecutor} - {} - virtual ~ContextExecutor() = default; - - public: - virtual void ExecSettings() = 0; - virtual Detail::BufferManipResult ExecRawString(std::basic_string_view) = 0; - - public: - Detail::FormatData Data; - Detail::TextPropertiesManager TextManager; - }; - - template - class BasicContext - { - public: - using TChar = CharType; - - public: - BasicContext( - ContextExecutor& executor, - Detail::BufferInfoView format, - Detail::BasicArgsInterface& argsInterface - ); - virtual ~BasicContext() = default; - - public: - ContextExecutor& Executor; - - Detail::BufferInfoView Format; - Detail::BasicArgsInterface& ArgsInterface; - std::int32_t ValuesIndex; - - public: - void Run(); - - public: - Detail::BufferManipResult GetFormatIndex(std::int32_t& idx); - - template - Detail::BufferManipResult FormatReadParameter(T& i, const T& defaultValue); - - public: - void FormatDataApplyNextOverride(); - - protected: - std::basic_string_view ParseNextOverrideFormatData(); - - void ParseFormatDataBase(); - void ParseFormatDataSpecial(); - void ParseFormatDataSpecial_ShiftType(const Detail::ShiftInfo::ShiftType type); - void ParseFormatDataCustom(); - void ParseFormatData(); - - void ParseVariable(std::int32_t formatIdx); - bool Parse(); - - public: - template - inline void ExecNextFormatData(Func&& func, Args&&... args) - { - if (Executor.Data.NextOverride.size() == 0) - return func(std::forward(args)...); - Detail::FormatData formatDataCopy = Executor.Data; - FormatDataApplyNextOverride(); - func(std::forward(args)...); - Executor.Data = formatDataCopy; - } - }; -} - -namespace StreamFormat::FMT::Context -{ - template - BasicContext::BasicContext( - ContextExecutor& executor, - Detail::BufferInfoView format, - Detail::BasicArgsInterface& argsInterface - ) - : Executor(executor) - , Format{format} - , ArgsInterface{argsInterface} - , ValuesIndex{0} - {} - - template - void BasicContext::Run() - { - while (!Detail::BufferAccess(Format).IsEndOfString()) - { - const TChar* beginContinousString = Format.CurrentPos; - std::size_t sizeContinousString = 0; - while (Detail::BufferAccess(Format).IsEndOfString() == false && Detail::BufferTestAccess(Format).IsEqualTo('{') == false) - { - ++sizeContinousString; - Detail::BufferManip(Format).Forward(); - } - Executor.ExecRawString(std::basic_string_view(beginContinousString, sizeContinousString)); - - if (Detail::BufferAccess(Format).IsEndOfString() == false && Detail::BufferTestAccess(Format).IsEqualTo('{')) - { - bool parseArg = Parse(); - if (parseArg == false) - Executor.ExecRawString("{").ThrowIfFailed(); - } - } - } - - template - void BasicContext::FormatDataApplyNextOverride() - { - if (Executor.Data.NextOverride.size() == 0) return; - - Detail::BufferInfoView overridePos(Executor.Data.NextOverride); - Detail::BufferInfoView formatPos = Format; - Format = overridePos; - ParseFormatData(); - Format = formatPos; - } - - template - template - Detail::BufferManipResult BasicContext::FormatReadParameter(T& i, const T& defaultValue) - { - if (!Detail::BufferTestAccess(Format).IsEqualTo('{')) - { - if (Detail::BufferReadManip(Format).FastReadInteger(i) == false) - i = defaultValue; - return true; - } - - // SubIndex - std::int32_t formatIdx = 0; - if (GetFormatIndex(formatIdx) == false) return false; - Detail::BufferTestManip(Format).IsEqualToForward('}'); - if constexpr (std::is_convertible_v) - i = static_cast(ArgsInterface.GetIntAt(formatIdx)); - else if constexpr (std::is_convertible_v>) - i = static_cast(ArgsInterface.GetStringAt(formatIdx)); - - return true; - } -} - -#include "BasicContextParse-impl.h" diff --git a/src/StreamFormat/FMT/Context/BasicContext/BasicContextParse-impl.h b/src/StreamFormat/FMT/Context/BasicContext/BasicContextParse-impl.h deleted file mode 100644 index 836f0352..00000000 --- a/src/StreamFormat/FMT/Context/BasicContext/BasicContextParse-impl.h +++ /dev/null @@ -1,289 +0,0 @@ -#pragma once - -#include "BasicContext.h" - -#include "StreamFormat/FMT/Buffer/BufferManip.h" -#include "StreamFormat/FMT/Buffer/BufferTestManip.h" -#include "StreamFormat/FMT/Buffer/BufferWriteManip.h" -#include "StreamFormat/FMT/Buffer/BufferReadManip.h" -#include "StreamFormat/FMT/Buffer/FMTBufferOutManip.h" -#include "StreamFormat/FMT/Buffer/FMTBufferReadManip.h" - -namespace StreamFormat::FMT::Context -{ - template - std::basic_string_view BasicContext::ParseNextOverrideFormatData() - { - Detail::BufferTestAccess access(Format); - Detail::BufferTestManip manip(Format); - - manip.SkipAllSpaces(); - Detail::FMTBufferParamsManip(Format).ParamGoTo('{', '=', ':'); - manip.SkipAllSpaces(); - manip.IsEqualToForward('=', ':'); - manip.SkipAllSpaces(); - Detail::FMTBufferParamsManip(Format).ParamGoTo('{'); - - const TChar* begin = Format.CurrentPos; - manip.IsEqualToForward('{').ThrowIfFailed(); - int scopes = 0; - while (Detail::FMTBufferParamsManip(Format).IsEndOfParameter() == false || scopes > 0) - { - manip.GoTo('\'', '}', '{'); - if (manip.IsEqualToForward('\'')) - manip.GoToForward('\''); - else if (manip.IsEqualToForward('{')) - scopes++; - else if (scopes > 0 && manip.IsEqualToForward('}')) - scopes--; - } - manip.IsEqualToForward('}').ThrowIfFailed(); - const TChar* end = Format.CurrentPos; - return std::basic_string_view(begin, end - begin); - } - - template - void BasicContext::ParseFormatDataBase() - { - Detail::BufferTestManip manip(Format); - - if (manip.IsEqualToForward('C')) - Executor.TextManager.ParseColor(*this); - else if (manip.IsEqualToForward('S')) - Executor.TextManager.ParseStyle(*this); - else if (manip.IsEqualToForward('F')) - Executor.TextManager.ParseFront(*this); - - else if (manip.IsEqualToForward('K')) - Executor.Data.KeepNewStyle = true; - - else if (manip.IsEqualToForward('N')) - Executor.Data.NextOverride = ParseNextOverrideFormatData(); - } - - template - void BasicContext::ParseFormatDataSpecial_ShiftType(const Detail::ShiftInfo::ShiftType type) - { - Executor.Data.Shift.Type = type; - FormatReadParameter(Executor.Data.Shift.Size, -1); - if (Detail::BufferTestManip(Format).IsEqualToForward(':')) - { - Executor.Data.Shift.Print.Before = Detail::BufferManip(Format).ThrowIfFailed().GetAndForward(); - Executor.Data.Shift.Print.After = Executor.Data.Shift.Print.Before; - if (Detail::BufferTestManip(Format).IsEqualToForward('|')) - Executor.Data.Shift.Print.After = Detail::BufferManip(Format).ThrowIfFailed().GetAndForward(); - } - } - - template - void BasicContext::ParseFormatDataSpecial() - { - Detail::BufferTestAccess access(Format); - Detail::BufferTestManip manip(Format); - - if (manip.IsEqualToForward('{')) - { - std::int32_t formatIndex = 0; - if (GetFormatIndex(formatIndex) == false) return; - - if ((Executor.Data.TestApply(ArgsInterface.template GetTypeAtIndex>(formatIndex)) || - Executor.Data.TestApply(ArgsInterface.template GetTypeAtIndex>(formatIndex)) || - Executor.Data.TestApply(ArgsInterface.template GetTypeAtIndex(formatIndex)) || - Executor.Data.TestApply(ArgsInterface.template GetTypeAtIndex(formatIndex))) == false) - throw Detail::FMTGivenTypeError{}; - manip.IsEqualToForward('}'); - } - - else if (manip.IsEqualToForward('.')) - FormatReadParameter(Executor.Data.FloatPrecision, -1); - - else if (access.IsEqualTo('d', 'b', 'B', 'o', 'O', 'x', 'X')) - Executor.Data.IntegerPrint = static_cast(Detail::BufferManip(Format).ThrowIfFailed().GetAndForward()); - - else if (manip.IsEqualToForward('#')) - Executor.Data.PrefixSuffix = true; - - - else if (manip.IsEqualToForward('>')) - ParseFormatDataSpecial_ShiftType(Detail::ShiftInfo::ShiftType::Right); - - else if (manip.IsEqualToForward('<')) - ParseFormatDataSpecial_ShiftType(Detail::ShiftInfo::ShiftType::Left); - - else if (manip.IsEqualToForward('^')) - { - if (manip.IsEqualToForward('<')) - ParseFormatDataSpecial_ShiftType(Detail::ShiftInfo::ShiftType::CenterLeft); - else - { - manip.IsEqualToForward('>'); - ParseFormatDataSpecial_ShiftType(Detail::ShiftInfo::ShiftType::CenterRight); - } - } - } - - template - void BasicContext::ParseFormatDataCustom() - { - Detail::BufferTestAccess access(Format); - Detail::BufferTestManip manip(Format); - - std::basic_string_view name = manip.ViewExec( - [&]{Detail::FMTBufferParamsManip(Format).ParamGoTo(' ', '=', '\'', '{', ',');} - ); - Detail::FMTBufferParamsManip(Format).ParamGoTo('=', '\'', '{', ','); - manip.IsEqualToForward('='); - manip.SkipAllSpaces(); - - if (manip.IsEqualToForward('\'')) - { - std::basic_string_view value = Detail::BufferTestManip(Format).ViewUntil('\''); - Executor.Data.Specifiers.Concat(Detail::FormatSpecifier{name, value}); - } - else if (access.IsADigit()) - { - std::int32_t value = 0; - Detail::BufferReadManip(Format).FastReadInteger(value); - Executor.Data.Specifiers.Concat(Detail::FormatSpecifier{name, value}); - } - else if (manip.IsEqualToForward('{')) - { - std::int32_t idx = 0; - GetFormatIndex(idx); - // TODO / FIXME - // Executor.Data.Specifiers.Concat(Detail::FormatSpecifier{name, GetTypeAtIndexAuto(idx)}); - manip.IsEqualToForward('}'); - } - else if (access.IsEqualTo(',', '}')) - { - Executor.Data.Specifiers.Concat(Detail::FormatSpecifier{name}); - } - } - - /////---------- Impl ----------///// - template - void BasicContext::ParseFormatData() - { - Detail::BufferTestAccess access(Format); - Detail::BufferTestManip manip(Format); - - Executor.Data.HasSpec = true; - while (Detail::BufferAccess(Format).IsEndOfString() == false && Detail::FMTBufferParamsManip(Format).IsEndOfParameter() == false) - { - manip.SkipAllSpaces(); - - if (access.IsUpperCase()) - ParseFormatDataBase(); - else if (!access.IsLowerCase()) - ParseFormatDataSpecial(); - else - ParseFormatDataCustom(); - - Detail::FMTBufferParamsManip(Format).ParamGoTo(','); - Detail::BufferTestManip(Format).IsEqualToForward(','); - } - } - - template - Detail::BufferManipResult BasicContext::GetFormatIndex(std::int32_t& idx) - { - const TChar* mainSubFormat = Format.CurrentPos; - - Detail::BufferTestAccess access(Format); - Detail::BufferTestManip manip(Format); - - // I : if there is no number specified : ':' or '}' - if (access.IsEqualTo(':') || access.IsEqualTo('}')) - if (ValuesIndex < ArgsInterface.Size()) - { - idx = ValuesIndex++; - return true; - } - - // II: A number(idx) - std::int32_t subIndex = -1; - if (Detail::BufferReadManip(Format).FastReadInteger(subIndex)) - if (access.IsEqualTo(':') || access.IsEqualTo('}')) - if (subIndex >= 0 && subIndex < ArgsInterface.Size()) - { - idx = subIndex; - return true; - } - Format.CurrentPos = mainSubFormat; - - // III : A name - std::int32_t indexOfNamedArg = ArgsInterface.GetIndexOfCurrentNamedArg(Format); - if (indexOfNamedArg >= 0 && indexOfNamedArg < ArgsInterface.Size()) - { - idx = indexOfNamedArg; - return true; - } - Format.CurrentPos = mainSubFormat; - - // VI : { which is a idx to an argument - if (manip.IsEqualToForward('{')) - { - std::int32_t recIndex = -1; - if (GetFormatIndex(recIndex) == false) - return false; - - if (manip.IsEqualToForward('}') && recIndex >= 0 && recIndex < ArgsInterface.Size()) - { - manip.SkipAllSpaces(); - if (access.IsEqualTo(':', '}')) - { - std::int32_t finalRecIndex = ArgsInterface.GetFormatIndexAt(recIndex); - if (finalRecIndex >= 0 && finalRecIndex < ArgsInterface.Size()) - return finalRecIndex; - return false; - } - } - } - Format.CurrentPos = mainSubFormat; - return false; - } - - template - void BasicContext::ParseVariable(std::int32_t formatIdx) - { - Detail::FormatData saveFormatData = Executor.Data; - Executor.Data = Detail::FormatData{}; - Detail::TextProperties::Properties saveTextProperties = Executor.TextManager.Save(); - - if (Detail::BufferTestAccess(Format).IsEqualTo(':', '{')) - { - Detail::BufferManip(Format).Forward(); - ParseFormatData(); - } - - ArgsInterface.RunTypeAtIndex(formatIdx); - - if (Executor.Data.KeepNewStyle == false) - Executor.TextManager.Reload(saveTextProperties); - - Executor.Data = saveFormatData; - } - - template - bool BasicContext::Parse() - { - Detail::BufferManip(Format).Forward(); // Skip { - - if (Detail::BufferTestAccess(Format).IsUpperCase()) - { - ParseFormatData(); - Detail::FMTBufferParamsManip(Format).ParamGoToForward(); // Skip } - return true; - } - - std::int32_t formatIdx = -1; - if (GetFormatIndex(formatIdx) && formatIdx >= 0 && formatIdx < ArgsInterface.Size()) - { - ParseVariable(formatIdx); - Detail::FMTBufferParamsManip(Format).ParamGoToForward(); // Skip } - return true; - } - - return false; - } -} diff --git a/src/StreamFormat/FMT/Context/BasicContext/ITextPropertiesExecutor.h b/src/StreamFormat/FMT/Context/BasicContext/ITextPropertiesExecutor.h deleted file mode 100644 index e010ee11..00000000 --- a/src/StreamFormat/FMT/Context/BasicContext/ITextPropertiesExecutor.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/Detail.h" -#include "StreamFormat/FMT/TextProperties/TextProperties.h" - -namespace StreamFormat::FMT::Detail -{ - class ITextPropertiesExecutor - { - public: - virtual ~ITextPropertiesExecutor() = default; - - public: - virtual void LinkToExecutor(void* executor) = 0; - - public: - virtual void AllPropertiesReset() = 0; - - public: - virtual void ResetColor() = 0; - virtual void ExecuteColor(const TextProperties::TextColor::BasicColorFG& t) = 0; - virtual void ExecuteColor(const TextProperties::TextColor::BasicColorBG& t) = 0; - virtual void ExecuteColor(const TextProperties::TextColor::BasicColor& t) = 0; - virtual void ExecuteColor(const TextProperties::TextColor::Color24bFG& t) = 0; - virtual void ExecuteColor(const TextProperties::TextColor::Color24bBG& t) = 0; - virtual void ExecuteColor(const TextProperties::TextColor::Color24b& t) = 0; - virtual void ExecuteColor(const TextProperties::TextColor::ColorCubeFG& t) = 0; - virtual void ExecuteColor(const TextProperties::TextColor::ColorCubeBG& t) = 0; - virtual void ExecuteColor(const TextProperties::TextColor::ColorCube& t) = 0; - - public: - virtual void ResetFront() = 0; - virtual void ExecuteFront(const TextProperties::TextFront::FrontID& t) = 0; - - public: - virtual void ResetStyle() = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::Intensity& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::Italic& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::Underline& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::UnderlineColor::Color& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::UnderlineColor::ColorCube& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::UnderlineColor::Color24b& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::Blink& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::Inverted& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::Ideogram& t) = 0; - virtual void ExecuteStyle(const TextProperties::TextStyle::Script& t) = 0; - }; -} diff --git a/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager-impl.h b/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager-impl.h deleted file mode 100644 index d483925c..00000000 --- a/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager-impl.h +++ /dev/null @@ -1,237 +0,0 @@ -#pragma once - -#include "TextPropertiesManager.h" - -#include "StreamFormat/FMT/Buffer/BufferManip.h" -#include "StreamFormat/FMT/Buffer/BufferOutManip.h" -#include "StreamFormat/FMT/Buffer/BufferTestManip.h" -#include "StreamFormat/FMT/Buffer/FMTBufferOutManip.h" -#include "StreamFormat/FMT/Buffer/Utils/BufferUtils.h" - -namespace StreamFormat::FMT::Detail -{ - template - void Detail::TextPropertiesManager::ApplyColorOnIndex(Context::BasicContext& context, std::int32_t index) - { - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextColor::Color& data) { this->ReloadColor(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextColor::BasicColorFG& data) { this->AskApplyColor(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextColor::BasicColorBG& data) { this->AskApplyColor(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextColor::ColorCubeFG& data) { this->AskApplyColor(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextColor::ColorCubeBG& data) { this->AskApplyColor(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextColor::Color24bFG& data) { this->AskApplyColor(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextColor::Color24bBG& data) { this->AskApplyColor(data); }); - } - - template - void Detail::TextPropertiesManager::ApplyFrontOnIndex(Context::BasicContext& context, std::int32_t index) - { - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextFront::Front& data) { this->ReloadFront(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextFront::FrontID& data) { this->AskApplyFront(data); }); - } - - template - void Detail::TextPropertiesManager::ApplyStyleOnIndex(Context::BasicContext& context, std::int32_t index) - { - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::Style& data) { this->ReloadStyle(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::Intensity& data) { this->AskApplyStyle(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::Italic& data) { this->AskApplyStyle(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::Underline& data) { this->AskApplyStyle(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::Blink& data) { this->AskApplyStyle(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::Inverted& data) { this->AskApplyStyle(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::Ideogram& data) { this->AskApplyStyle(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::Script& data) { this->AskApplyStyle(data); }); - - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::UnderlineColor::ColorCube& data) { this->AskApplyStyle(data); }); - context.ArgsInterface.template RunFuncFromTypeAtIndex( - index, [this](const Detail::TextProperties::TextStyle::UnderlineColor::Color24b& data) { this->AskApplyStyle(data); }); - } - - template - void Detail::TextPropertiesManager::ParseColor(Context::BasicContext& context) - { - if (BufferTestManip(context.Format).IsEqualToForward(':')) - { - BufferTestManip(context.Format).SkipAllSpaces(); - if (BufferTestManip(context.Format).IsEqualToForward('{')) - { - std::int32_t idx = 0; - context.GetFormatIndex(idx).ThrowIfFailed(); - ApplyColorOnIndex(context, idx); - BufferTestManip(context.Format).IsEqualToForward('}'); - } - else - { - Detail::TextProperties::TextColor::BasicColorFG colorFg; - bool colorFgFound = GetColorCode(context.Format, colorFg); - - FMTBufferParamsManip(context.Format).ParamGoTo('-', ','); - if (BufferTestManip(context.Format).IsEqualToForward('-')) - { - BufferTestManip(context.Format).SkipAllSpaces(); - Detail::TextProperties::TextColor::BasicColorBG colorBg; - bool colorBgFound = GetColorCode(context.Format, colorBg); - if (colorBgFound && colorFgFound) - AskApplyColor(Detail::TextProperties::TextColor::BasicColor{colorFg, colorBg}); - else - ReloadDefaultColor(); - } - else - { - if (colorFgFound) - AskApplyColor(colorFg); - else - ReloadDefaultColor(); - } - } - } - else - ReloadDefaultColor(); - } - - template - void Detail::TextPropertiesManager::ParseStyle(Context::BasicContext& context) - { - if (BufferTestManip(context.Format).IsEqualToForward(':')) - { - if (!BufferTestAccess(context.Format).IsEqualTo('}', ',')) - { - bool l = true; - while (l) - { - BufferTestManip(context.Format).SkipAllSpaces(); - if (BufferTestManip(context.Format).IsEqualToForward('{')) - { - std::int32_t idx = 0; - context.GetFormatIndex(idx).ThrowIfFailed(); - ApplyStyleOnIndex(context, idx); - BufferTestManip(context.Format).IsEqualToForward('}'); - } - else - { - ParseStyleNamed(context.Format); - } - FMTBufferParamsManip(context.Format).ParamGoTo('|', ','); - l = BufferTestManip(context.Format).IsEqualToForward('|'); - BufferTestManip(context.Format).SkipAllSpaces(); - } - } - else - ReloadDefaultStyle(); - } - else - ReloadDefaultStyle(); - } - - template - void Detail::TextPropertiesManager::ParseStyleNamed(BufferInfoView& format) - { - Detail::BufferUtilsManip utils(format); - - static constexpr std::pair, Detail::TextProperties::TextStyle::Intensity> styleIntensity[] = { - {"bold", Detail::TextProperties::TextStyle::Intensity::Bold}, - {"dim", Detail::TextProperties::TextStyle::Intensity::Dim}, - {"n-intensity", Detail::TextProperties::TextStyle::Intensity::Normal} - }; - - static constexpr std::pair, Detail::TextProperties::TextStyle::Italic> styleItalic[] = { - {"italic", Detail::TextProperties::TextStyle::Italic::Enable}, - {"n-italic", Detail::TextProperties::TextStyle::Italic::Disable} - }; - - // TODO: magic values - static constexpr typename std::pair, Detail::TextProperties::TextStyle::Underline> styleUnderline[] = { - {"underlined", Detail::TextProperties::TextStyle::Underline::Underlined}, - {"d-underlined", Detail::TextProperties::TextStyle::Underline::DoubleUnerlined}, - {"n-underlined", Detail::TextProperties::TextStyle::Underline::Disable}, - {"c-underlined", Detail::TextProperties::TextStyle::Underline::SelectUnderlinedColor}}; - - static constexpr typename std::pair, Detail::TextProperties::TextStyle::Blink> styleBlink[] = {{"slowblink", Detail::TextProperties::TextStyle::Blink::SlowBlink}, - {"fastblink", Detail::TextProperties::TextStyle::Blink::FastBlink}, - {"n-blink", Detail::TextProperties::TextStyle::Blink::Disable}}; - - static constexpr typename std::pair, Detail::TextProperties::TextStyle::Inverted> styleInverted[] = { - {"inverted", Detail::TextProperties::TextStyle::Inverted::Enable}, - {"n-inverted", Detail::TextProperties::TextStyle::Inverted::Disable}, - }; - - static constexpr typename std::pair, Detail::TextProperties::TextStyle::Ideogram> styleIdeogram[] = { - {"i-underlined", Detail::TextProperties::TextStyle::Ideogram::Underlined}, {"i-d-underlined", Detail::TextProperties::TextStyle::Ideogram::DoubleUnderlined}, - {"i-overlined", Detail::TextProperties::TextStyle::Ideogram::Overlined}, {"i-d-overlined", Detail::TextProperties::TextStyle::Ideogram::DoubleOverlined}, - {"i-stress", Detail::TextProperties::TextStyle::Ideogram::StressMarking}, {"n-i", Detail::TextProperties::TextStyle::Ideogram::AllDisable}, - }; - - static constexpr typename std::pair, Detail::TextProperties::TextStyle::Script> styleScript[] = { - {"superscript", Detail::TextProperties::TextStyle::Script::Superscript}, - {"subscript", Detail::TextProperties::TextStyle::Script::Subscript}, - {"n-script", Detail::TextProperties::TextStyle::Script::AllDisable}}; - - std::uint8_t code = (std::uint8_t)BufferUtilsManip(format).GetWordFromDictPairs(styleIntensity, (Detail::TextProperties::TextStyle::Intensity)255); - if (code != 255) return ApplyStyle(Detail::TextProperties::TextStyle::Intensity{code}); - code = (std::uint8_t)BufferUtilsManip(format).GetWordFromDictPairs(styleItalic, (Detail::TextProperties::TextStyle::Italic)255); - if (code != 255) return ApplyStyle(Detail::TextProperties::TextStyle::Italic{code}); - code = (std::uint8_t)BufferUtilsManip(format).GetWordFromDictPairs(styleBlink, (Detail::TextProperties::TextStyle::Blink)255); - if (code != 255) return ApplyStyle(Detail::TextProperties::TextStyle::Blink{code}); - code = (std::uint8_t)BufferUtilsManip(format).GetWordFromDictPairs(styleInverted, (Detail::TextProperties::TextStyle::Inverted)255); - if (code != 255) return ApplyStyle(Detail::TextProperties::TextStyle::Inverted{code}); - code = (std::uint8_t)BufferUtilsManip(format).GetWordFromDictPairs(styleIdeogram, (Detail::TextProperties::TextStyle::Ideogram)255); - if (code != 255) return ApplyStyle(Detail::TextProperties::TextStyle::Ideogram{code}); - code = (std::uint8_t)BufferUtilsManip(format).GetWordFromDictPairs(styleScript, (Detail::TextProperties::TextStyle::Script)255); - if (code != 255) return ApplyStyle(Detail::TextProperties::TextStyle::Script{code}); - - code = (std::uint8_t)BufferUtilsManip(format).GetWordFromDictPairs(styleUnderline, (Detail::TextProperties::TextStyle::Underline)255); - if (code != 255) - { - if (code == (std::uint8_t)Detail::TextProperties::TextStyle::Underline::SelectUnderlinedColor) - { - Detail::TextProperties::TextStyle::UnderlineColor::ColorCube underlineColor = SelectUnderlinedColorStyle(format); - return ApplyStyle(underlineColor); - } - return ApplyStyle(Detail::TextProperties::TextStyle::Underline{code}); - } - } - - template - TextProperties::TextStyle::UnderlineColor::ColorCube TextPropertiesManager::SelectUnderlinedColorStyle(BufferInfoView& format) - { - FMTBufferParamsManip(format).ParamGoTo(':'); - BufferTestManip(format).IsEqualToForward(':'); - BufferTestManip(format).SkipAllSpaces(); - Detail::TextProperties::TextStyle::UnderlineColor::ColorCube color; - if (GetColorCode(format, color)) return color; - // TODO : handle Color24b - return Detail::TextProperties::TextStyle::UnderlineColor::ColorCube{}; - } - - template - void Detail::TextPropertiesManager::ParseFront(Context::BasicContext& context) - { - static constexpr std::string_view frontCode[] = {"default", "front0", "front1", "front2", "front3", "front4", "front5", "front6", "front7", "front8", "front9"}; - - if (BufferTestManip(context.Format).IsEqualToForward(':')) - { - BufferTestManip(context.Format).SkipAllSpaces(); - Detail::TextProperties::TextFront::FrontID frontID = (static_cast(BufferUtilsManip(context.Format).GetWordFromList(frontCode))); - ApplyFront(frontID); - } - else - ReloadDefaultFront(); - } -} diff --git a/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager.cpp b/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager.cpp deleted file mode 100644 index bcef40f3..00000000 --- a/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "TextPropertiesManager.h" - -namespace StreamFormat::FMT::Detail -{ - void TextPropertiesApplyManager::ReloadColorFG(const TextProperties::TextColor::ColorFG& target) - { - if (target.Type != m_CurrentContextProperties.Color.Fg.Type) - { - switch (target.Type) - { - case TextProperties::TextColor::ColorType::BasicColor: - ApplyColor(target.Data.BasicColor); - break; - case TextProperties::TextColor::ColorType::ColorCube: - ApplyColor(target.Data.ColorCube); - break; - case TextProperties::TextColor::ColorType::Color24b: - ApplyColor(target.Data.Color24b); - break; - } - } - else - { - switch (target.Type) - { - case TextProperties::TextColor::ColorType::BasicColor: - if (m_CurrentContextProperties.Color.Fg.Data.BasicColor != target.Data.BasicColor) ApplyColor(target.Data.BasicColor); - break; - case TextProperties::TextColor::ColorType::ColorCube: - if (m_CurrentContextProperties.Color.Fg.Data.ColorCube != target.Data.ColorCube) ApplyColor(target.Data.ColorCube); - break; - case TextProperties::TextColor::ColorType::Color24b: - if (m_CurrentContextProperties.Color.Fg.Data.Color24b != target.Data.Color24b) ApplyColor(target.Data.Color24b); - break; - } - } - } - - void TextPropertiesApplyManager::ReloadColorBG(const TextProperties::TextColor::ColorBG& target) - { - if (target.Type != m_CurrentContextProperties.Color.Bg.Type) - { - switch (target.Type) - { - case TextProperties::TextColor::ColorType::BasicColor: - ApplyColor(target.Data.BasicColor); - break; - case TextProperties::TextColor::ColorType::ColorCube: - ApplyColor(target.Data.ColorCube); - break; - case TextProperties::TextColor::ColorType::Color24b: - ApplyColor(target.Data.Color24b); - break; - } - } - else - { - switch (target.Type) - { - case TextProperties::TextColor::ColorType::BasicColor: - if (m_CurrentContextProperties.Color.Bg.Data.BasicColor != target.Data.BasicColor) ApplyColor(target.Data.BasicColor); - break; - case TextProperties::TextColor::ColorType::ColorCube: - if (m_CurrentContextProperties.Color.Bg.Data.ColorCube != target.Data.ColorCube) ApplyColor(target.Data.ColorCube); - break; - case TextProperties::TextColor::ColorType::Color24b: - if (m_CurrentContextProperties.Color.Bg.Data.Color24b != target.Data.Color24b) ApplyColor(target.Data.Color24b); - break; - } - } - } - - void TextPropertiesApplyManager::ReloadStyle(const TextProperties::TextStyle::Style& target) - { - if (target.Intensity != m_CurrentContextProperties.Style.Intensity) - { - ApplyStyle(target.Intensity); - m_CurrentContextProperties.Style.Intensity = target.Intensity; - } - if (target.Italic != m_CurrentContextProperties.Style.Italic) - { - ApplyStyle(target.Italic); - m_CurrentContextProperties.Style.Italic = target.Italic; - } - if (target.Blink != m_CurrentContextProperties.Style.Blink) - { - ApplyStyle(target.Blink); - m_CurrentContextProperties.Style.Blink = target.Blink; - } - if (target.Inverted != m_CurrentContextProperties.Style.Inverted) - { - ApplyStyle(target.Inverted); - m_CurrentContextProperties.Style.Inverted = target.Inverted; - } - if (target.Ideogram != m_CurrentContextProperties.Style.Ideogram) - { - ApplyStyle(target.Ideogram); - m_CurrentContextProperties.Style.Ideogram = target.Ideogram; - } - if (target.Script != m_CurrentContextProperties.Style.Script) - { - ApplyStyle(target.Script); - m_CurrentContextProperties.Style.Script = target.Script; - } - - if (target.Underline != m_CurrentContextProperties.Style.Underline) - { - ApplyStyle(target.Underline); - m_CurrentContextProperties.Style.Underline = target.Underline; - } - - if (target.UnderlineColor.Type != m_CurrentContextProperties.Style.UnderlineColor.Type) - { - switch (target.UnderlineColor.Type) - { - case TextProperties::TextStyle::UnderlineColor::ColorType::Default: - ApplyStyle(TextProperties::TextStyle::UnderlineColor::ColorCube{TextProperties::TextStyle::UnderlineColor::ColorCube::Default}); - break; - case TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube: - ApplyStyle(target.UnderlineColor.Data.ColorCube); - m_CurrentContextProperties.Style.UnderlineColor.Data.ColorCube = target.UnderlineColor.Data.ColorCube; - break; - case TextProperties::TextStyle::UnderlineColor::ColorType::Color24b: - ApplyStyle(target.UnderlineColor.Data.Color24b); - m_CurrentContextProperties.Style.UnderlineColor.Data.Color24b = target.UnderlineColor.Data.Color24b; - break; - } - m_CurrentContextProperties.Style.UnderlineColor.Type = target.UnderlineColor.Type; - } - else - { - switch (target.UnderlineColor.Type) - { - case TextProperties::TextStyle::UnderlineColor::ColorType::Default: - break; - case TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube: - if (m_CurrentContextProperties.Style.UnderlineColor.Data.ColorCube != target.UnderlineColor.Data.ColorCube) - { - ApplyStyle(target.UnderlineColor.Data.ColorCube); - m_CurrentContextProperties.Style.UnderlineColor.Data.ColorCube = target.UnderlineColor.Data.ColorCube; - } - break; - case TextProperties::TextStyle::UnderlineColor::ColorType::Color24b: - if (m_CurrentContextProperties.Style.UnderlineColor.Data.Color24b != target.UnderlineColor.Data.Color24b) - { - ApplyStyle(target.UnderlineColor.Data.Color24b); - m_CurrentContextProperties.Style.UnderlineColor.Data.Color24b = target.UnderlineColor.Data.Color24b; - } - break; - } - } - } - - void TextPropertiesApplyManager::ReloadFront(const TextProperties::TextFront::Front& target) - { - if (m_CurrentContextProperties.Front == target) return; - - ApplyFront(target.CurrentID); - m_CurrentContextProperties.Front = target; - } -} diff --git a/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager.h b/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager.h deleted file mode 100644 index f7b9539e..00000000 --- a/src/StreamFormat/FMT/Context/BasicContext/TextPropertiesManager.h +++ /dev/null @@ -1,209 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/Detail.h" -#include "ITextPropertiesExecutor.h" -#include "BasicArgsInterface.h" -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/BufferTestManip.h" -#include "StreamFormat/FMT/Buffer/Utils/BufferUtils.h" - -namespace StreamFormat::FMT::Detail -{ - class TextPropertiesApplyManager - { - public: - TextPropertiesApplyManager(ITextPropertiesExecutor& textPropertiesExecutor) - : m_TextPropertiesExecutor{textPropertiesExecutor} - , m_CurrentContextProperties{} - {} - - void Terminate() { ReloadDefault(); } - - public: - template - requires Detail::TextPropertiesColorCanApply - void ApplyColor(const T& modif) - { - m_CurrentContextProperties.Color.Apply(modif); - m_TextPropertiesExecutor.ExecuteColor(modif); - } - template - requires Detail::TextPropertiesStyleCanApply - void ApplyStyle(const T& modif) - { - m_CurrentContextProperties.Style.Apply(modif); - m_TextPropertiesExecutor.ExecuteStyle(modif); - } - template - requires Detail::TextPropertiesFrontCanApply - void ApplyFront(const T& modif) - { - m_CurrentContextProperties.Front.Apply(modif); - m_TextPropertiesExecutor.ExecuteFront(modif); - } - - void AllPropertiesReset() - { - ApplyColorReset(); - ApplyStyleReset(); - ApplyFrontReset(); - } - void ApplyColorReset() - { - m_CurrentContextProperties.Color.ModifyReset(); - m_TextPropertiesExecutor.ResetColor(); - } - void ApplyStyleReset() - { - m_CurrentContextProperties.Style.ModifyReset(); - m_TextPropertiesExecutor.ResetStyle(); - } - void ApplyFrontReset() - { - m_CurrentContextProperties.Front.ModifyReset(); - m_TextPropertiesExecutor.ResetFront(); - } - - public: - Detail::TextProperties::Properties Save() { return m_CurrentContextProperties; } - - public: - void ReloadDefault() - { - ReloadDefaultColor(); - ReloadDefaultStyle(); - ReloadDefaultFront(); - } - void ReloadDefaultColor() - { - ReloadDefaultColorFG(); - ReloadDefaultColorBG(); - } - void ReloadDefaultColorFG() { ReloadColorFG(Detail::TextProperties::TextColor::ColorFG{}); } - void ReloadDefaultColorBG() { ReloadColorBG(Detail::TextProperties::TextColor::ColorBG{}); } - void ReloadDefaultStyle() { ReloadStyle(Detail::TextProperties::TextStyle::Style{}); } - void ReloadDefaultFront() { ReloadFront(Detail::TextProperties::TextFront::Front{}); } - - void Reload(const Detail::TextProperties::Properties& target) - { - ReloadColor(target.Color); - ReloadStyle(target.Style); - ReloadFront(target.Front); - } - void ReloadColor(const Detail::TextProperties::TextColor::Color& target) - { - ReloadColorFG(target.Fg); - ReloadColorBG(target.Bg); - } - - void ReloadColorFG(const Detail::TextProperties::TextColor::ColorFG& target); - void ReloadColorBG(const Detail::TextProperties::TextColor::ColorBG& target); - void ReloadStyle(const Detail::TextProperties::TextStyle::Style& target); - void ReloadFront(const Detail::TextProperties::TextFront::Front& target); - - public: - ITextPropertiesExecutor& GetTextPropertiesExecutor() { return m_TextPropertiesExecutor; } - Detail::TextProperties::Properties& GetCurrentContextProperties() { return m_CurrentContextProperties; } - - protected: - ITextPropertiesExecutor& m_TextPropertiesExecutor; - Detail::TextProperties::Properties m_CurrentContextProperties; - - public: - template - requires Detail::TextPropertiesColorCanApply - inline void AskApplyColor(const T& modif) - { - if (m_CurrentContextProperties.Color.NeedModif(modif)) ApplyColor(modif); - } - template - requires Detail::TextPropertiesStyleCanApply - inline void AskApplyStyle(const T& modif) - { - if (m_CurrentContextProperties.Style.NeedModif(modif)) ApplyStyle(modif); - } - template - requires Detail::TextPropertiesFrontCanApply - inline void AskApplyFront(const T& modif) - { - if (m_CurrentContextProperties.Front.NeedModif(modif)) ApplyFront(modif); - } - - void AskApplyColor(const Detail::TextProperties::TextColor::BasicColor& modif) - { - if (m_CurrentContextProperties.Color.NeedModif(modif.Fg)) - { - if (m_CurrentContextProperties.Color.NeedModif(modif.Bg)) ApplyColor(modif); - return ApplyColor(modif.Fg); - } - if (m_CurrentContextProperties.Color.NeedModif(modif.Fg)) return ApplyColor(modif.Bg); - } - - void AskApplyColor(const Detail::TextProperties::TextColor::ColorCube& modif) - { - if (m_CurrentContextProperties.Color.NeedModif(modif.Fg)) - { - if (m_CurrentContextProperties.Color.NeedModif(modif)) return ApplyColor(modif); - return ApplyColor(modif.Fg); - } - if (m_CurrentContextProperties.Color.NeedModif(modif.Fg)) return ApplyColor(modif.Bg); - } - - void AskApplyColor(const Detail::TextProperties::TextColor::Color24b& modif) - { - if (m_CurrentContextProperties.Color.NeedModif(modif.Fg)) - { - if (m_CurrentContextProperties.Color.NeedModif(modif)) return ApplyColor(modif); - return ApplyColor(modif.Fg); - } - if (m_CurrentContextProperties.Color.NeedModif(modif.Fg)) return ApplyColor(modif.Bg); - } - - void AskApplyColor(const Detail::TextProperties::TextColor::ColorFG& modif) { ReloadColorFG(modif); } - void AskApplyColor(const Detail::TextProperties::TextColor::ColorBG& modif) { ReloadColorBG(modif); } - void AskApplyColor(const Detail::TextProperties::TextColor::Color& modif) { ReloadColor(modif); } - }; - - template - class TextPropertiesManager : public TextPropertiesApplyManager - { - public: - TextPropertiesManager(ITextPropertiesExecutor& textPropertiesExecutor) - : TextPropertiesApplyManager(textPropertiesExecutor) - {} - - public: - void ApplyColorOnIndex(Context::BasicContext& context, std::int32_t index); - void ApplyStyleOnIndex(Context::BasicContext& context, std::int32_t index); - void ApplyFrontOnIndex(Context::BasicContext& context, std::int32_t index); - - public: - void ParseColor(Context::BasicContext& context); - void ParseStyle(Context::BasicContext& context); - void ParseFront(Context::BasicContext& context); - - private: - template - bool GetColorCode(BufferInfoView& format, T& t); - void ParseStyleNamed(BufferInfoView& format); - Detail::TextProperties::TextStyle::UnderlineColor::ColorCube SelectUnderlinedColorStyle(BufferInfoView& format); - }; -} - -namespace StreamFormat::FMT::Detail -{ - template - template - bool Detail::TextPropertiesManager::GetColorCode(BufferInfoView& format, T& t) - { - static constexpr std::string_view colorCode[] = {"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", " ", "default"}; - - std::uint8_t step = static_cast(BufferTestManip(format).IsEqualToForward('+') ? T::BaseBStep : T::BaseStep); - std::uint8_t code = static_cast(BufferUtilsManip(format).GetWordFromList(colorCode)); - if (code == BufferUtilsManip::GET_WORD_FROM_LIST_NOT_FOUND) return false; - t = static_cast(code + step); - return true; - } -} - -#include "TextPropertiesManager-impl.h" diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/BasicFormatterExecutor.h b/src/StreamFormat/FMT/Context/FormatterExecutor/BasicFormatterExecutor.h deleted file mode 100644 index f393eb3f..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/BasicFormatterExecutor.h +++ /dev/null @@ -1,108 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Context/BasicContext/BasicContext.h" - -#include "StreamFormat/FMT/Buffer/FMTBufferOutManip.h" -#include "StreamFormat/FMT/Buffer/BufferWriteManip.h" - -#include "FormatterType.h" -#include "IndexArgs.h" -#include "NamedArgs.h" -#include "STDEnumerable.h" - -#include "FormatterArgs.h" - -namespace StreamFormat::FMT::Context -{ - template - class BasicFormatterExecutor : public ContextExecutor - { - public: - using TChar = CharType; - private: - using M_Type = BasicFormatterExecutor; - - public: - BasicFormatterExecutor(Detail::FMTBufferOutInfo& bufferOut, Detail::ITextPropertiesExecutor& textPropertiesExecutor); - ~BasicFormatterExecutor() override = default; - - void Terminate(); - - public: - Detail::FMTBufferOutInfo& BufferOut; - - using ContextExecutor::Data; - using ContextExecutor::TextManager; - - protected: - Detail::BufferManipResult ExecRawString(std::basic_string_view sv) override { Detail::BufferWriteManip(BufferOut).FastWriteString(sv); return true; } - void ExecSettings() override; - - public: - template - void Run_(Detail::BufferInfoView format, Args&&... args); - template - void Run(Format&& format, Args&&... args); - - public: - template - inline void WriteType(Type&& type, Rest&&... rest) - { - FormatterType>::Type, M_Type>::Format(std::forward(type), *this); - if constexpr (sizeof...(rest) > 0) - WriteType(std::forward(rest)...); - } - }; -} - -namespace StreamFormat::FMT::Context -{ - template - BasicFormatterExecutor::BasicFormatterExecutor(Detail::FMTBufferOutInfo& bufferOut, Detail::ITextPropertiesExecutor& textPropertiesExecutor) - : ContextExecutor(textPropertiesExecutor) - , BufferOut(bufferOut) - { - textPropertiesExecutor.LinkToExecutor(this); - } - - template - void BasicFormatterExecutor::Terminate() - { - Detail::BufferOutManip(BufferOut).ComputeGeneratedSize(); - - // End char not included in buffer manager context to deduce size correctly - if (Detail::BufferOutManip(BufferOut).Reserve(1)) - Detail::BufferOutManip(BufferOut).Pushback('\0'); - } - - template - void BasicFormatterExecutor::ExecSettings() - { - // Indent - auto indent = Data.Specifiers.Get("indent"); - if (indent != nullptr) - BufferOut.Indent = indent->AsNumber; - } - - template - template - void BasicFormatterExecutor::Run_(Detail::BufferInfoView format, Args&&... args) - { - auto argsInterface = Detail::FormatterArgsInterface, Args...>(*this, std::forward(args)...); - - Detail::TextProperties::Properties saveTextProperties = TextManager.Save(); - Context::BasicContext context(*this, format, argsInterface); - context.Run(); - TextManager.Reload(saveTextProperties); - } - - template - template - void BasicFormatterExecutor::Run(Format&& formatInput, Args&&... args) - { - Run_(Detail::BufferInfoView{formatInput}, std::forward(args)...); - } -} - -#include "FormatBasics-impl.h" -#include "FormatTextProperties-impl.h" diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatBasics-impl.h b/src/StreamFormat/FMT/Context/FormatterExecutor/FormatBasics-impl.h deleted file mode 100644 index 1ee9d417..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatBasics-impl.h +++ /dev/null @@ -1,192 +0,0 @@ -#pragma once - -#include "BasicFormatterExecutor.h" - -#include "StreamFormat/FMT/Buffer/FMTBufferWriteManip.h" - -namespace StreamFormat::FMT -{ - //---------------------------------------------// - //----------------- Internals -----------------// - //---------------------------------------------// - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const typename FormatterExecutor::Detail::template FormatSpecifier& specifier, FormatterExecutor& executor) - { - if (specifier.ValueIsText) - executor.Run("{ '{}', '{}' }", specifier.Name, specifier.AsText); - else - executor.Run("{ '{}', '{}' }", specifier.Name, specifier.AsNumber); - } - }; - - //----------------------------------------------// - //----------------- Forwarders -----------------// - //----------------------------------------------// - - namespace Detail::Forwarders - { - template - void FormatObjectArray(const T* const buffer, std::size_t totalsize, FormatterExecutor& executor) - { - std::size_t beginIdx = (std::size_t)executor.Data.Specifiers.GetAsNumber("begin", 0); - totalsize = executor.Data.Specifiers.GetAsNumber("totalsize", totalsize); - totalsize = executor.Data.Specifiers.GetAsNumber("end", totalsize); - - std::size_t size = executor.Data.Specifiers.GetAsNumber("size", totalsize - beginIdx); - - if (size == std::numeric_limits::max()) - { - Detail::BufferWriteManip(executor.BufferOut).FastWriteString(""); - return; - } - - Detail::BufferWriteManip(executor.BufferOut).FastWriteString(executor.Data.Specifiers.GetAsText("begin", STDEnumerableUtility::DefaultBegin)); - - std::basic_string_view join = executor.Data.Specifiers.GetAsText("join", STDEnumerableUtility::DefaultJoin); - - bool first = true; - const T* itbegin = buffer + beginIdx; - const T* itend = buffer + size + beginIdx; - - while (itbegin < itend) - { - if (first) - first = false; - else - Detail::FMTBufferWriteManip(executor.BufferOut).WriteIndentString(join); - executor.WriteType(*itbegin++); - } - - Detail::BufferWriteManip(executor.BufferOut).FastWriteString(executor.Data.Specifiers.GetAsText("end", STDEnumerableUtility::DefaultEnd)); - } - - template - void FormatString(const T* buffer, std::size_t size, FormatterExecutor& executor) - { - std::size_t beginIdx = (std::size_t)executor.Data.Specifiers.GetAsNumber("begin", 0); - size = executor.Data.Specifiers.GetAsNumber("size", size); - if (size == std::numeric_limits::max()) size = std::basic_string_view(buffer).size(); - - if (executor.Data.Specifiers.Has("array")) return FormatObjectArray(buffer, size, executor); - - if (beginIdx > size) return; - const T* begin = buffer + beginIdx; - - // TODO: current indent ignore shift - if (executor.Data.Specifiers.Has("indent")) - return Detail::FMTBufferWriteManip(executor.BufferOut).WriteIndentCharPtr(begin, size); - - if (executor.Data.PrefixSuffix) Detail::BufferOutManip(executor.BufferOut).Pushback('\"'); - - if (executor.Data.HasSpec == false) - Detail::BufferWriteManip(executor.BufferOut).FastWriteCharArray(begin, size); - else - Detail::FMTBufferWriteManip(executor.BufferOut).WriteCharPtr(begin, size, executor.Data.Shift); - - if (executor.Data.PrefixSuffix) Detail::BufferOutManip(executor.BufferOut).Pushback('\"'); - } - } - - //-----------------------------------------------// - //----------------- C/CXX Types -----------------// - //-----------------------------------------------// - - // Bool - template - struct FormatterType - { - static void Format(const bool t, FormatterExecutor& executor) - { - if (executor.Data.PrefixSuffix) - { - if (t == true) - Detail::BufferWriteManip(executor.BufferOut).FastWriteStringLitteral("True"); - else - Detail::BufferWriteManip(executor.BufferOut).FastWriteStringLitteral("False"); - } - else - { - if (t == true) - Detail::BufferManip(executor.BufferOut).Pushback('1'); - else - Detail::BufferManip(executor.BufferOut).Pushback('0'); - } - } - }; - - template - requires (std::is_integral_v && !std::is_floating_point_v && !Detail::IsCharType::Value) - struct FormatterType - { - static inline void Format(const T t, FormatterExecutor& executor) { Detail::FMTBufferWriteManip(executor.BufferOut).WriteIntegerFormatData(t, executor.Data); } - }; - - template - requires std::is_floating_point_v - struct FormatterType - { - static inline void Format(const T t, FormatterExecutor& executor) { Detail::FMTBufferWriteManip(executor.BufferOut).WriteFloatFormatData(t, executor.Data); } - }; - - template - requires Detail::IsCharType::Value - struct FormatterType - { - static inline void Format(const T t, FormatterExecutor& executor) { Detail::BufferOutManip(executor.BufferOut).Pushback(t); } - }; - - //-------------------------------------------------------// - //----------------- Pointers and Arrays -----------------// - //-------------------------------------------------------// - - template - struct FormatterType - { - static void Format(const void* const t, FormatterExecutor& executor) - { - if (t == nullptr) - return Detail::BufferOutManip(executor.BufferOut).FastWriteString(executor.Data.GetAsText("null", "nullptr")); - Detail::BufferWriteManip(executor.BufferOut).FastWriteInteger(std::size_t(t)); - } - }; - - template - struct FormatterType - { - static void Format(const T* const t, FormatterExecutor& executor) - { - if (t == nullptr) - return Detail::BufferWriteManip(executor.BufferOut).FastWriteString(executor.Data.Specifiers.GetAsText("null", "nullptr")); - - if constexpr (Detail::IsCharType::Value) - { - Detail::Forwarders::FormatString(t, std::numeric_limits::max(), executor); - } - else - { - Detail::Forwarders::FormatObjectArray(t, std::numeric_limits::max(), executor); - } - } - }; - - template - struct FormatterType - { - static void Format(T const (&t)[SIZE], FormatterExecutor& executor) - { - if constexpr (Detail::IsCharType::Value) - { - std::size_t size = SIZE; - while (t[size - 1] == '\0') --size; - Detail::Forwarders::FormatString(t, size, executor); - } - else - { - Detail::Forwarders::FormatObjectArray(t, SIZE, executor); - } - } - }; -} diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatTextProperties-impl.h b/src/StreamFormat/FMT/Context/FormatterExecutor/FormatTextProperties-impl.h deleted file mode 100644 index ed2ca4f0..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatTextProperties-impl.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include "BasicFormatterExecutor.h" - -namespace StreamFormat::FMT -{ - //------------------------------------------// - //----------------- Resets -----------------// - //------------------------------------------// - - template - struct FormatterType - { - static void Format(const Detail::TextProperties::ResetProperties, FormatterExecutor& executor) - { - executor.TextManager.AllPropertiesReset(); - } - }; - - template - struct FormatterType - { - static void Format(const Detail::TextProperties::TextColor::ResetColor, FormatterExecutor& executor) - { - executor.TextManager.ApplyColorReset(); - } - }; - - template - struct FormatterType - { - static void Format(const Detail::TextProperties::TextStyle::ResetStyle, FormatterExecutor& executor) - { - executor.TextManager.ApplyStyleReset(); - } - }; - - template - struct FormatterType - { - static void Format(const Detail::TextProperties::TextFront::ResetFront, FormatterExecutor& executor) - { - executor.TextManager.ApplyFrontReset(); - } - }; - - //---------------------------------------// - //----------------- Ask -----------------// - //---------------------------------------// - - template - requires Detail::TextPropertiesColorIsApply - struct FormatterType - { - static void Format(const T& t, FormatterExecutor& executor) - { - executor.TextManager.AskApplyColor(t); - } - }; - - template - requires Detail::TextPropertiesStyleIsApply - struct FormatterType - { - static void Format(const T& t, FormatterExecutor& executor) - { - executor.TextManager.AskApplyStyle(t); - } - }; - - template - requires Detail::TextPropertiesFrontIsApply - struct FormatterType - { - static void Format(const T& t, FormatterExecutor& executor) - { - executor.TextManager.AskApplyFront(t); - } - }; -} diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterArgs.h b/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterArgs.h deleted file mode 100644 index 5cd456b7..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterArgs.h +++ /dev/null @@ -1,161 +0,0 @@ - -#pragma once - -#include "StreamFormat/FMT/Context/BasicContext/BasicArgsInterface.h" -#include "StreamFormat/FMT/Detail/Detail.h" - -#include "FormatterType.h" - -namespace StreamFormat::FMT::Detail -{ - template - struct FormatterArgs; - - template <> - struct FormatterArgs<> - { - public: - FormatterArgs() = default; - - public: - static inline constexpr std::size_t Size() { return 0; } - - public: - template - inline void RunTypeAtIndex(FormatterExecutor&, std::int32_t) - { - throw Detail::FMTGivenIndexError(); - } - - template - inline std::int32_t GetIndexOfCurrentNamedArg(FormatterExecutor&, std::int32_t) - { - return std::int32_t{-1}; - } - - inline PointerID GetTypeAtIndex(std::int32_t) { return PointerID{.TypeInfo = typeid(void), .Ptr = nullptr}; } - - template - inline void GetTypeAtIndexConvert(T*, std::int32_t) - {} - }; - - template - struct FormatterArgs : public FormatterArgs - { - private: - using TypeWithoutRef = std::remove_reference_t; - - public: - FormatterArgs(const TypeWithoutRef& t, Rest&&... rest) - : FormatterArgs(std::forward(rest)...) - , m_Value(t) - {} - - private: - const TypeWithoutRef& m_Value; - - public: - static inline constexpr std::size_t Size() { return sizeof...(Rest) + 1; } - - public: - template - inline void RunTypeAtIndex(Executor& executor, std::int32_t idx) - { - if (idx == 0) return executor.WriteType(m_Value); - return FormatterArgs::RunTypeAtIndex(executor, idx - 1); - } - - public: - template - inline std::int32_t GetIndexOfCurrentNamedArg(BufferInfoView& format, std::int32_t beginSearchIndex) - { - if constexpr (Detail::IsANamedArgs>::value) - { - if (Detail::FMTBufferParamsManip(format).NextIsNamedArgs(m_Value.GetName())) - return beginSearchIndex; - } - return FormatterArgs::GetIndexOfCurrentNamedArg(format, beginSearchIndex + 1); - } - - public: - inline PointerID GetTypeAtIndex(std::int32_t idx) - { - if (idx == 0) return PointerID{.TypeInfo = typeid(const TypeWithoutRef), .Ptr = const_cast(static_cast(&m_Value))}; - return FormatterArgs::GetTypeAtIndex(idx - 1); - } - - public: - template - inline void GetTypeAtIndexConvert(T* value, std::int32_t idx) - { - if (idx == 0) - { - if constexpr (FMTCanContextConvert) - { - *value = FMTContextConvert::Convert(m_Value); - return; - } - else - { - // Warrning : Need to transmit : 'Could not convert' - return; - } - } - return FormatterArgs::template GetTypeAtIndexConvert(value, idx - 1); - } - }; - - template - class FormatterArgsInterface : public BasicArgsInterface - { - public: - using ContextArgsType = FormatterArgs; - - public: - FormatterArgsInterface(FormatterExecutor& executor, Args&&... args) - : BasicArgsInterface() - , Executor(executor) - , ArgsInterface(std::forward(args)...) - {} - ~FormatterArgsInterface() override = default; - - public: - size_t Size() override { return ArgsInterface.Size(); } - - void RunTypeAtIndex(std::int32_t idx) override - { - return ArgsInterface.RunTypeAtIndex(Executor, idx); - } - std::int32_t GetIndexOfCurrentNamedArg(BufferInfoView& format) override - { - return ArgsInterface.GetIndexOfCurrentNamedArg(format, std::int32_t{0}); - } - PointerID GetTypeAt(std::int32_t idx) override - { - return ArgsInterface.GetTypeAtIndex(idx); - } - - public: - template - T GetTAtConvert(std::int32_t idx) - { - T res; - ArgsInterface.template GetTypeAtIndexConvert(&res, idx); - return res; - } - - std::int32_t GetFormatIndexAt(std::int32_t idx) override { return GetTAtConvert(idx); } - - std::basic_string_view GetStringAt(std::int32_t idx) override - { - return GetTAtConvert>(idx); - } - - std::int64_t GetIntAt(std::int32_t idx) override { return GetTAtConvert(idx); } - - protected: - FormatterExecutor& Executor; - ContextArgsType ArgsInterface; - }; -} diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterTextPropertiesExecutor/FormatterANSITextPropertiesExecutor.h b/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterTextPropertiesExecutor/FormatterANSITextPropertiesExecutor.h deleted file mode 100644 index 94f877ce..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterTextPropertiesExecutor/FormatterANSITextPropertiesExecutor.h +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once - -#include "FormatterTextPropertiesExecutor.h" - -namespace StreamFormat::FMT::Detail -{ - template - class FormatterANSITextPropertiesExecutor final : public IFormatterTextPropertiesExecutor - { - public: - FormatterANSITextPropertiesExecutor() = default; - ~FormatterANSITextPropertiesExecutor() override = default; - - using IFormatterTextPropertiesExecutor::Buffer; - - public: - void AllPropertiesReset() override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).FastWriteStringLitteral("\033[0m"); - } - - public: - void ResetColor() override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).FastWriteStringLitteral("\033[39;49m"); - } - - void ExecuteColor(const TextProperties::TextColor::BasicColorFG& t) - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - void ExecuteColor(const TextProperties::TextColor::BasicColorBG& t) - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColor& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t.Fg), ";", static_cast(t.Bg), "m"); - } - void ExecuteColor(const Detail::TextProperties::TextColor::Color24bFG& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[38;2;", t.R, ";", t.G, ";", t.B, "m"); - } - void ExecuteColor(const Detail::TextProperties::TextColor::Color24bBG& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[48;2;", t.R, ";", t.G, ";", t.B, "m"); - } - void ExecuteColor(const Detail::TextProperties::TextColor::Color24b& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[38;2;", t.Fg.R, ";", t.Fg.G, ";", t.Fg.B, "; 48; 2;", t.Bg.R, ";", t.Bg.G, ";", t.Bg.B, "m"); - } - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCubeFG& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[38;5;", t.GetColorRef(), "m"); - } - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCubeBG& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[48;5;", t.GetColorRef(), "m"); - } - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCube& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[48;5;", t.Fg.GetColorRef(), ";48;5;", t.Bg.GetColorRef(), "m"); - } - public: - void ResetFront() override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", Detail::TextProperties::TextFront::FrontID::DefaultFrontID, "m"); - } - void ExecuteFront(const Detail::TextProperties::TextFront::FrontID& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", t.ID, "m"); - } - public: - void ResetStyle() override - { - // TODO - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).FastWriteStringLitteral("\033[0m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Intensity& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Italic& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Underline& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::Color&) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[59m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::ColorCube& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[58;5;", t.GetColorRef(), "m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::Color24b& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[58;2;", t.R, ";", t.G, ";", t.B, "m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Blink& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Inverted& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Ideogram& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Script& t) override - { - NoStrideFunction noStride(*Buffer); - BufferWriteManip(*Buffer).BasicWriteType("\033[", static_cast(t), "m"); - } - }; -} diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterTextPropertiesExecutor/FormatterTextPropertiesExecutor.h b/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterTextPropertiesExecutor/FormatterTextPropertiesExecutor.h deleted file mode 100644 index 0418ca90..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterTextPropertiesExecutor/FormatterTextPropertiesExecutor.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Context/BasicContext/ITextPropertiesExecutor.h" -#include "StreamFormat/FMT/Buffer/FMTBufferOutManip.h" -#include "StreamFormat/FMT/Context/FormatterExecutor/BasicFormatterExecutor.h" - -namespace StreamFormat::FMT::Detail -{ - template - class IFormatterTextPropertiesExecutor : public ITextPropertiesExecutor - { - public: - ~IFormatterTextPropertiesExecutor() override = default; - - void LinkToExecutor(void* executor) override - { - Buffer = &reinterpret_cast*>(executor)->BufferOut; - } - - protected: - Detail::FMTBufferOutInfo* Buffer{nullptr}; - }; -} - -namespace StreamFormat::FMT::Detail -{ - template - class FormatterNOTextPropertiesExecutor final : public IFormatterTextPropertiesExecutor - { - public: - FormatterNOTextPropertiesExecutor() = default; - ~FormatterNOTextPropertiesExecutor() override = default; - - public: - void AllPropertiesReset() override {} - - public: - void ResetColor() override {} - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColorFG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColorBG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColor&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::Color24bFG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::Color24bBG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::Color24b&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCubeFG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCubeBG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCube&) override {} - - public: - void ResetFront() override {} - void ExecuteFront(const Detail::TextProperties::TextFront::FrontID&) override {} - - public: - void ResetStyle() override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Intensity&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Italic&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Underline&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::Color&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::ColorCube&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::Color24b&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Blink&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Inverted&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Ideogram&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Script&) override {} - }; -} diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h b/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h deleted file mode 100644 index eec96c42..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/Detail.h" - -#define STREAMFORMAT_FORMATTER_DECLARED -namespace StreamFormat::FMT -{ - template - struct FormatterType - { - static inline void Format(const T&, FormatterExecutor& executor) - { -#ifdef UNKOWN_TYPE_MESSAGE - executor.Run("({C:red}FMT unknow type: {})", typeid(T).name()); -#endif -#ifdef UNKOWN_TYPE_THROW - throw Detail::FMTShouldNotEndHere{}; -#endif -#ifdef UNKOWN_TYPE_FAIL - throw Detail::FMTShouldNotEndHere{}; -#endif -#ifdef UNKOWN_TYPE_DEBUG - STREAMFORMAT_DEBUGBREAK(); -#endif - } - }; -} - -#define STREAMFORMAT_AUTO_FORMATTER(Type, fmt, ...) \ - template \ - struct StreamFormat::FMT::FormatterType \ - { \ - static void Format(const Type& value, FormatterExecutor& executor) { executor.Run(fmt, __VA_ARGS__); } \ - }; - -#define STREAMFORMAT_AUTO_FORMATTER_T(Type, fmt, ...) \ - template \ - struct StreamFormat::FMT::FormatterType \ - { \ - static void Format(const Type&, FormatterExecutor& executor) { executor.Run(fmt, __VA_ARGS__); } \ - }; diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/IndexArgs.h b/src/StreamFormat/FMT/Context/FormatterExecutor/IndexArgs.h deleted file mode 100644 index 9235b4e9..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/IndexArgs.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FCIndexArgs - { - public: - FCIndexArgs(const std::uint8_t idx, const T& t) - : m_Value(t) - , m_Idx(idx) - {} - - public: - inline bool IsRightIdx(std::uint8_t idx) const { return idx == m_Idx; } - - public: - inline const T& GetValue() const { return m_Value; } - - protected: - const T& m_Value; - const std::uint8_t m_Idx; - }; - - template - struct FormatterType, FormatterExecutor> - { - template - static inline void Format(const FCIndexArgs& t, FormatterExecutor& executor) - { - executor.WriteType(t.GetValue()); - } - }; -} diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/NamedArgs.h b/src/StreamFormat/FMT/Context/FormatterExecutor/NamedArgs.h deleted file mode 100644 index 9b475886..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/NamedArgs.h +++ /dev/null @@ -1,104 +0,0 @@ -#pragma once - -#include "FormatterType.h" - -namespace StreamFormat::FMT -{ - /////---------- string_view NamedArgs Do not allocate memory (Best) ----------///// - template - struct StringViewNamedArgs - { - public: - template - StringViewNamedArgs(const CharName (&name)[SIZE], const T& t) - : m_Name(name) - , value(t) - {} - - StringViewNamedArgs(std::basic_string_view name, const T& t) - : m_Name(name) - , value(t) - {} - - public: - T& GetValue() { return value; } - const T& GetValue() const { return value; } - std::basic_string_view GetName() const { return m_Name; } - - protected: - std::basic_string_view m_Name; - const T& value; - }; - - template - struct FormatterType, FormatterExecutor> - { - static inline void Format(const StringViewNamedArgs& t, FormatterExecutor& executor) { executor.WriteType(t.GetValue()); } - }; - - /////---------- stringNamedArgs Allocate memory (Only if necessary) ----------///// - template - struct StringNamedArgs - { - public: - StringNamedArgs(const std::string& str, const T& t) - : m_Name(str) - , value(t) - {} - - StringNamedArgs(std::string&& str, const T& t) - : m_Name(std::move(str)) - , value(t) - {} - - public: - T& GetValue() { return value; } - const T& GetValue() const { return value; } - std::basic_string_view GetName() const { return m_Name; } - - protected: - std::basic_string m_Name; - const T& value; - }; - - template - struct FormatterType, FormatterExecutor> - { - static inline void Format(const StringNamedArgs& t, FormatterExecutor& executor) { executor.WriteType(t.GetValue()); } - }; - - namespace Detail - { - template - struct IsANamedArgs - { - public: - [[maybe_unused]] inline constexpr static bool value = false; - }; - - template - struct IsANamedArgs> - { - [[maybe_unused]] inline constexpr static bool value = true; - }; - - template - struct IsANamedArgs> - { - [[maybe_unused]] inline constexpr static bool value = true; - }; - - template - inline constexpr bool IsANamedArgsValue = false; - - template - inline constexpr bool IsANamedArgsValue> = true; - - template - inline constexpr bool IsANamedArgsValue> = true; - } -} - -#define FORMAT(value) StreamFormat::FMT::StringViewNamedArgs(#value, value) -#define FORMAT_SV(name, value) StreamFormat::FMT::StringViewNamedArgs(name, value) -#define FORMAT_STR(name, value) StreamFormat::FMT::StringNamedArgs(name, value) diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/STDEnumerable.h b/src/StreamFormat/FMT/Context/FormatterExecutor/STDEnumerable.h deleted file mode 100644 index 7538c5b5..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/STDEnumerable.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include "FormatterType.h" -#include "StreamFormat/FMT/Context/Utils/ContextFunctions.h" -#include "StreamFormat/FMT/Detail/Detail.h" - -#include -#include - -namespace StreamFormat::FMT -{ - class STDEnumerableUtility - { - public: - static constexpr std::string_view DefaultJoin = ", "; - static constexpr std::string_view DefaultBegin = "{ "; - static constexpr std::string_view DefaultEnd = " }"; - }; - - template - class STDEnumerable - { - public: - explicit inline STDEnumerable(const T& value, std::basic_string_view strJoin = ", ", std::basic_string_view strBegin = "{ ", - std::basic_string_view strEnd = " }", const std::int32_t beginIdx = 0, - const std::int32_t size = -1) - : m_Value(value) - , m_StrJoin(strJoin) - , m_StrBegin(strBegin) - , m_StrEnd(strEnd) - , m_BeginIdx(beginIdx) - , m_Size(size < 0 ? (std::int32_t)value.size() - beginIdx : size) - {} - - inline const T& GetValue() const { return m_Value; } - - inline std::basic_string_view GetStrJoin() const { return m_StrJoin; } - inline std::basic_string_view GetStrBegin() const { return m_StrBegin; } - inline std::basic_string_view GetStrEnd() const { return m_StrEnd; } - - inline std::int32_t GetBeginIdx() const { return m_BeginIdx; } - inline std::int32_t GetSize() const { return m_Size; } - - private: - const T& m_Value; - - std::basic_string_view m_StrJoin; - std::basic_string_view m_StrBegin; - std::basic_string_view m_StrEnd; - - std::int32_t m_BeginIdx; - std::int32_t m_Size; - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const STDEnumerable& enumerable, FormatterExecutor& executor) - { - executor.BufferOut.WriteIndentStringView(enumerable.GetStrBegin()); - executor.BufferOut.AddIndent(enumerable.GetStrBegin().size()); - - { - // TODO: Why ? ... - Detail::FunctionApplyNextOverride applyNextOverride(executor); - - bool first = true; - std::for_each_n(enumerable.GetValue().cbegin() + enumerable.GetBeginIdx(), enumerable.GetSize(), [&](const auto& element) { - if (first) - first = false; - else - executor.BufferOut.WriteIndentStringView(enumerable.GetStrJoin()); - - executor.WriteType(element); - }); - } - - executor.BufferOut.RemoveIndent(enumerable.GetStrBegin().size()); - executor.BufferOut.WriteIndentStringView(enumerable.GetStrEnd()); - } - }; - - template - struct ForwardAsSTDEnumerable - { - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const T& container, FormatterExecutor& executor) - { - STDEnumerable enumerable(container, executor.Data.GetAsText("join", STDEnumerableUtility::DefaultJoin), - executor.Data.GetAsText("begin", STDEnumerableUtility::DefaultBegin), - executor.Data.GetAsText("end", STDEnumerableUtility::DefaultEnd), - executor.Data.GetAsNumber("begin", 0), - executor.Data.GetAsNumber("size", -1)); - - executor.WriteType(enumerable); - } - }; - -} diff --git a/src/StreamFormat/FMT/Context/FormatterExecutor/UtilityFunctions.h b/src/StreamFormat/FMT/Context/FormatterExecutor/UtilityFunctions.h deleted file mode 100644 index d467e28a..00000000 --- a/src/StreamFormat/FMT/Context/FormatterExecutor/UtilityFunctions.h +++ /dev/null @@ -1,209 +0,0 @@ -#pragma once - -#include "BasicFormatterExecutor.h" - -#include "StreamFormat/FMT/Buffer/BufferOutManager/DynamicBufferOutManager.h" -#include "StreamFormat/FMT/Buffer/BufferOutManager/GivenBufferOutManager.h" -#include "StreamFormat/FMT/Buffer/BufferOutManager/StaticBufferOutManager.h" - -#include "FormatterTextPropertiesExecutor/FormatterANSITextPropertiesExecutor.h" - -#include - -namespace StreamFormat::FMT -{ - /////---------- Impl with as Format ----------////// - namespace Detail - { - template - requires(IsCharType::Value) - void FormatInManager( - Detail::BasicBufferOutManager& bufferOutManager, - bool newline, - BufferInfoView format, - Args&&... args - ) - { - using TCharResolved = std::remove_const_t; - - Detail::FormatterANSITextPropertiesExecutor textPropertiesExecutor; - Detail::FMTBufferOutInfo bufferOut{bufferOutManager}; - Context::BasicFormatterExecutor executor(bufferOut, textPropertiesExecutor); - executor.Run(format, std::forward(args)...); - if (newline) BufferOutManip(bufferOut).Pushback('\n'); - executor.Terminate(); - } - - template - requires(IsCharType::Value) - void FormatInManager(Detail::BasicBufferOutManager& bufferOutManager, bool newline, T&& t) - { - using TCharResolved = std::remove_const_t; - - Detail::FormatterANSITextPropertiesExecutor textPropertiesExecutor; - Detail::FMTBufferOutInfo bufferOut{bufferOutManager}; - Context::BasicFormatterExecutor executor(bufferOut, textPropertiesExecutor); - executor.WriteType(std::forward(t)); - if (newline) BufferOutManip(bufferOut).Pushback('\n'); - executor.Terminate(); - } - } - - template - requires(Detail::IsCharType::Value && Detail::ConvertibleToBufferInfoView) - void FormatInChar(TChar (&buffer)[BUFFER_SIZE], Format&& formatInput, Args&&... args) - { - Detail::GivenBufferOutManager bufferOutManager(buffer); - Detail::FormatInManager(bufferOutManager, false, Detail::BufferInfoView{formatInput}, std::forward(args)...); - } - - template - requires(Detail::IsCharType::Value && Detail::ConvertibleToBufferInfoView) - void FormatInChar(TChar* const buffer, const std::size_t bufferSize, Format&& formatInput, Args&&... args) - { - Detail::GivenBufferOutManager bufferOutManager(buffer, bufferSize); - Detail::FormatInManager(bufferOutManager, false, Detail::BufferInfoView{formatInput}, std::forward(args)...); - } - - template - requires(Detail::IsCharType::Value && Detail::ConvertibleToBufferInfoView) - void CFilePrint(FILE* stream, Format&& formatInput, Args&&... args) - { - Detail::DynamicBufferOutManager bufferOutManager(256); - Detail::FormatInManager(bufferOutManager, false, Detail::BufferInfoView{formatInput}, std::forward(args)...); - - std::fwrite(bufferOutManager.GetBuffer(), bufferOutManager.GetLastGeneratedDataSize(), 1, stream); - std::fflush(stream); - } - - template - requires(Detail::IsCharType::Value && Detail::ConvertibleToBufferInfoView) - void CFilePrintLn(FILE* stream, Format&& formatInput, Args&&... args) - { - Detail::DynamicBufferOutManager bufferOutManager(256); - Detail::FormatInManager(bufferOutManager, true, Detail::BufferInfoView{formatInput}, std::forward(args)...); - - std::fwrite(bufferOutManager.GetBuffer(), bufferOutManager.GetLastGeneratedDataSize(), 1, stream); - std::fflush(stream); - } - - template - requires(Detail::IsCharType::Value && Detail::ConvertibleToBufferInfoView) - void FilePrint(std::basic_ostream& stream, Format&& formatInput, Args&&... args) - { - Detail::DynamicBufferOutManager bufferOutManager(256); - Detail::FormatInManager(bufferOutManager, false, Detail::BufferInfoView{formatInput}, std::forward(args)...); - - stream.write(bufferOutManager.GetBuffer(), bufferOutManager.GetLastGeneratedDataSize()); - stream.flush(); - } - - template - requires(Detail::IsCharType::Value && Detail::ConvertibleToBufferInfoView) - void FilePrintLn(std::basic_ostream& stream, Format&& formatInput, Args&&... args) - { - Detail::DynamicBufferOutManager bufferOutManager(256); - Detail::FormatInManager(bufferOutManager, true, Detail::BufferInfoView{formatInput}, std::forward(args)...); - - stream.write(bufferOutManager.GetBuffer(), bufferOutManager.GetLastGeneratedDataSize()); - stream.flush(); - } - - template - requires(Detail::IsCharType::Value && Detail::ConvertibleToBufferInfoView) - void FormatInString(std::basic_string& str, Format&& formatInput, Args&&... args) - { - Detail::DynamicBufferOutManager bufferOutManager(256); - Detail::FormatInManager(bufferOutManager, false, Detail::BufferInfoView{formatInput}, std::forward(args)...); - str = bufferOutManager.GetLastGeneratedString(); - } - - template - requires(Detail::IsCharType::Value && Detail::ConvertibleToBufferInfoView) - inline std::basic_string FormatString(Format&& formatInput, Args&&... args) - { - Detail::DynamicBufferOutManager bufferOutManager(256); - Detail::FormatInManager(bufferOutManager, false, Detail::BufferInfoView{formatInput}, std::forward(args)...); - return bufferOutManager.GetLastGeneratedString(); - } - - /////---------- NO-FORMAT Impl except for string which are formatted to avoid {} ----------////// - - template - requires(Detail::IsCharType::Value) - void FormatInChar(TChar (&buffer)[BUFFER_SIZE], T&& t) - { - Detail::GivenBufferOutManager bufferOutManager(buffer, BUFFER_SIZE); - Detail::FormatInManager(bufferOutManager, false, std::forward(t)); - } - - template - requires(Detail::IsCharType::Value) - void FormatInChar(TChar* const buffer, const std::size_t bufferSize, T&& t) - { - Detail::GivenBufferOutManager bufferOutManager(buffer, bufferSize); - Detail::FormatInManager(bufferOutManager, false, std::forward(t)); - } - - template - requires(Detail::IsCharType::Value) - void CFilePrint(FILE* stream, T&& t) - { - Detail::DynamicBufferOutManager bufferOutManager(32); - Detail::FormatInManager(bufferOutManager, false, std::forward(t)); - - std::fwrite(bufferOutManager.GetBuffer(), static_cast(bufferOutManager.GetLastGeneratedDataSize()), 1, stream); - std::fflush(stream); - } - - template - requires(Detail::IsCharType::Value) - void CFilePrintLn(FILE* stream, T&& t) - { - Detail::DynamicBufferOutManager bufferOutManager(32); - Detail::FormatInManager(bufferOutManager, true, std::forward(t)); - - std::fwrite(bufferOutManager.GetBuffer(), static_cast(bufferOutManager.GetLastGeneratedDataSize()), 1, stream); - std::fflush(stream); - } - - template - requires(Detail::IsCharType::Value) - void FilePrint(std::basic_ostream& stream, T&& t) - { - Detail::DynamicBufferOutManager bufferOutManager(32); - Detail::FormatInManager(bufferOutManager, false, std::forward(t)); - - stream.write(bufferOutManager.GetBuffer(), static_cast(bufferOutManager.GetLastGeneratedDataSize())); - stream.flush(); - } - - template - requires(Detail::IsCharType::Value) - void FilePrintLn(std::basic_ostream& stream, T&& t) - { - Detail::DynamicBufferOutManager bufferOutManager(32); - Detail::FormatInManager(bufferOutManager, true, std::forward(t)); - - stream.write(bufferOutManager.GetBuffer(), static_cast(bufferOutManager.GetLastGeneratedDataSize())); - stream.flush(); - } - - template - requires(Detail::IsCharType::Value) - void FormatInString(std::basic_string& str, T&& t) - { - Detail::DynamicBufferOutManager bufferOutManager(32); - Detail::FormatInManager(bufferOutManager, false, std::forward(t)); - str = bufferOutManager.GetLastGeneratedString(); - } - - template - requires(Detail::IsCharType::Value) - inline std::basic_string FormatString(T&& t) - { - Detail::DynamicBufferOutManager bufferOutManager(32); - Detail::FormatInManager(bufferOutManager, false, std::forward(t)); - return bufferOutManager.GetLastGeneratedString(); - } -} diff --git a/src/StreamFormat/FMT/Context/ParserExecutor/BasicParserExecutor.h b/src/StreamFormat/FMT/Context/ParserExecutor/BasicParserExecutor.h deleted file mode 100644 index dde08703..00000000 --- a/src/StreamFormat/FMT/Context/ParserExecutor/BasicParserExecutor.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" -#include "StreamFormat/FMT/Buffer/BufferManip.h" -#include "StreamFormat/FMT/Buffer/BufferTestManip.h" - -#include "StreamFormat/FMT/Context/BasicContext/BasicContext.h" - -#include "ParserType.h" - -#include "ParserArgs.h" - -#include "ParserTextPropertiesExecutor/ParserTextPropertiesExecutor.h" - -namespace StreamFormat::FMT::Context -{ - template - class BasicParserExecutor : public ContextExecutor - { - public: - using TChar = CharType; - private: - using M_Type = BasicParserExecutor; - - public: - BasicParserExecutor(Detail::BufferInfoView& bufferIn, Detail::ITextPropertiesExecutor& textPropertiesExecutor); - ~BasicParserExecutor() override = default; - - void Terminate(); - - public: - Detail::BufferInfoView& BufferIn; - - using ContextExecutor::Data; - using ContextExecutor::TextManager; - - protected: - Detail::BufferManipResult ExecRawString(std::basic_string_view sv) override { return Detail::BufferTestManip(BufferIn).IsSameForward(sv.data(), sv.size()); } - void ExecSettings() override {}; - - public: - template - void Run_(Detail::BufferInfoView format, Args&&... args); - template - void Run(Format&& format, Args&&... args); - - public: - template - inline void ReadType(Type& type, Rest&... rest) - { - ParserType>::Type, M_Type>::Parse(type, *this); - if constexpr (sizeof...(rest) > 0) - ReadType(std::forward(rest)...); - } - }; -} - -namespace StreamFormat::FMT::Context -{ - template - BasicParserExecutor::BasicParserExecutor(Detail::BufferInfoView& bufferIn, Detail::ITextPropertiesExecutor& textPropertiesExecutor) - : ContextExecutor(textPropertiesExecutor) - , BufferIn{bufferIn} - { - textPropertiesExecutor.LinkToExecutor(this); - } - - template - void BasicParserExecutor::Terminate() - { - } - - template - template - void BasicParserExecutor::Run_(Detail::BufferInfoView format, Args&&... args) - { - auto argsInterface = Detail::ParserArgsInterface, Args...>(*this, std::forward(args)...); - - Detail::TextProperties::Properties saveTextProperties = TextManager.Save(); - Context::BasicContext context(*this, format, argsInterface); - context.Run(); - TextManager.Reload(saveTextProperties); - } - - template - template - void BasicParserExecutor::Run(Format&& formatInput, Args&&... args) - { - Run_(Detail::BufferInfoView{formatInput}, std::forward(args)...); - } -} - -#include "ParseBasics-impl.h" -#include "ParseTextProperties-impl.h" diff --git a/src/StreamFormat/FMT/Context/ParserExecutor/ParseBasics-impl.h b/src/StreamFormat/FMT/Context/ParserExecutor/ParseBasics-impl.h deleted file mode 100644 index f011b315..00000000 --- a/src/StreamFormat/FMT/Context/ParserExecutor/ParseBasics-impl.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -#include "BasicParserExecutor.h" -#include "StreamFormat/FMT/Buffer/FMTBufferReadManip.h" - -namespace StreamFormat::FMT -{ - //----------------------------------------------// - //----------------- Forwarders -----------------// - //----------------------------------------------// - - //-----------------------------------------------// - //----------------- C/CXX Types -----------------// - //-----------------------------------------------// - - template - struct ParserType - { - static void Parse(bool& t, ParserExecutor& executor) - { - if (!executor.Data.PrefixSuffix) - { - if (Detail::BufferTestManip(executor.BufferIn).IsEqualToForward('t', 'T')) - { - if (Detail::BufferTestManip(executor.BufferIn).IsSameForward("rue")) - t = true; - } - else if (Detail::BufferTestManip(executor.BufferIn).IsEqualToForward('f', 'F')) - { - if (Detail::BufferTestManip(executor.BufferIn).IsSameForward("alse")) - t = false; - } - } - else - { - if (Detail::BufferTestManip(executor.BufferIn).IsEqualToForward('1')) - { t = true; return; } - else if (Detail::BufferTestManip(executor.BufferIn).IsEqualToForward('1')) - { t = false; return; } - } - - throw Detail::FMTParseError(); - } - }; - - template - requires (std::is_integral_v && !std::is_floating_point_v && !Detail::IsCharType::Value) - struct ParserType - { - static inline void Parse(T& t, ParserExecutor& executor) { Detail::FMTBufferReadManip(executor.BufferIn).ReadIntegerFormatData(t, executor.Data); } - }; - - template - requires std::is_floating_point_v - struct ParserType - { - static inline void Parse(T& t, ParserExecutor& executor) { Detail::FMTBufferReadManip(executor.BufferIn).ReadFloatFormatData(t, executor.Data); } - }; - - //-------------------------------------------------------// - //----------------- Pointers and Arrays -----------------// - //-------------------------------------------------------// - - template - struct ParserType - { - static inline void Parse(void*&, ParserExecutor&) - { - // FIXME - // TODO - } - }; - - template - struct ParserType - { - static inline void Parse(T*&, ParserExecutor&) - { - // FIXME - // TODO - } - }; - - template - struct ParserType - { - static inline void Parse(T (&)[SIZE], ParserExecutor&) - { - // FIXME - // TODO - } - }; -} diff --git a/src/StreamFormat/FMT/Context/ParserExecutor/ParseTextProperties-impl.h b/src/StreamFormat/FMT/Context/ParserExecutor/ParseTextProperties-impl.h deleted file mode 100644 index 219ce945..00000000 --- a/src/StreamFormat/FMT/Context/ParserExecutor/ParseTextProperties-impl.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include "BasicParserExecutor.h" - -namespace StreamFormat::FMT -{ - //------------------------------------------// - //----------------- Resets -----------------// - //------------------------------------------// - - template - struct ParserType - { - static void Parse(Detail::TextProperties::ResetProperties, ParserExecutor& executor) - { - executor.TextManager.AllPropertiesReset(); - } - }; - - template - struct ParserType - { - static void Parse(Detail::TextProperties::TextColor::ResetColor, ParserExecutor& executor) - { - executor.TextManager.ApplyColorReset(); - } - }; - - template - struct ParserType - { - static void Parse(Detail::TextProperties::TextStyle::ResetStyle, ParserExecutor& executor) - { - executor.TextManager.ApplyStyleReset(); - } - }; - - template - struct ParserType - { - static void Parse(Detail::TextProperties::TextFront::ResetFront, ParserExecutor& executor) - { - executor.TextManager.ApplyFrontReset(); - } - }; - - //---------------------------------------// - //----------------- Ask -----------------// - //---------------------------------------// - - template - requires Detail::TextPropertiesColorIsApply - struct ParserType - { - static void Parse(T& t, ParserExecutor& executor) - { - executor.TextManager.AskApplyColor(t); - } - }; - - template - requires Detail::TextPropertiesStyleIsApply - struct ParserType - { - static void Parse(T& t, ParserExecutor& executor) - { - executor.TextManager.AskApplyStyle(t); - } - }; - - template - requires Detail::TextPropertiesFrontIsApply - struct ParserType - { - static void Parse(T& t, ParserExecutor& executor) - { - executor.TextManager.AskApplyFront(t); - } - }; -} diff --git a/src/StreamFormat/FMT/Context/ParserExecutor/ParserArgs.h b/src/StreamFormat/FMT/Context/ParserExecutor/ParserArgs.h deleted file mode 100644 index a31ba017..00000000 --- a/src/StreamFormat/FMT/Context/ParserExecutor/ParserArgs.h +++ /dev/null @@ -1,154 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Context/BasicContext/BasicArgsInterface.h" -#include "StreamFormat/FMT/Detail/Detail.h" - -namespace StreamFormat::FMT::Detail -{ - template - struct ParserArgs; - - template <> - struct ParserArgs<> - { - public: - ParserArgs() = default; - - public: - static inline constexpr std::size_t Size() { return 0; } - - public: - template - inline void RunTypeAtIndex(FormatterExecutor&, std::int32_t) - { - throw Detail::FMTGivenIndexError(); - } - - template - inline std::int32_t GetIndexOfCurrentNamedArg(FormatterExecutor&, std::int32_t) - { - return std::int32_t{-1}; - } - - inline PointerID GetTypeAtIndex(std::int32_t) { return {.TypeInfo = typeid(void), .Ptr = nullptr}; } - - template - inline void GetTypeAtIndexConvert(T*, std::int32_t) - {} - }; - - template - struct ParserArgs : ParserArgs - { - private: - using TypeWithoutRef = std::remove_reference_t; - - public: - ParserArgs(TypeWithoutRef& t, Rest&... rest) - : ParserArgs(std::forward(rest)...) - , m_Value(t) - {} - - private: - TypeWithoutRef& m_Value; - - public: - static inline constexpr std::size_t Size() { return sizeof...(Rest) + 1; } - - public: - template - inline void RunTypeAtIndex(Executor& executor, std::int32_t idx) - { - if (idx == 0) return executor.ReadType(m_Value); - return ParserArgs::RunTypeAtIndex(executor, idx - 1); - } - - public: - template - inline std::int32_t GetIndexOfCurrentNamedArg(BufferInfoView& format, std::int32_t beginSearchIndex) - { - if constexpr (Detail::IsANamedArgs>::value) - { - if (Detail::FMTBufferParamsManip(format).NextIsNamedArgs(m_Value.GetName())) return beginSearchIndex; - } - return ParserArgs::GetIndexOfCurrentNamedArg(format, beginSearchIndex + 1); - } - - public: - inline PointerID GetTypeAtIndex(std::int32_t idx) - { - if (idx == 0) return PointerID{.TypeInfo = typeid(TypeWithoutRef), .Ptr = static_cast(&m_Value)}; - return ParserArgs::GetTypeAtIndex(idx - 1); - } - - public: - template - inline void GetTypeAtIndexConvert(T* value, std::int32_t idx) - { - if (idx == 0) - { - if constexpr (FMTCanContextConvert) - { - *value = FMTContextConvert::Convert(m_Value); - return; - } - else - { - // Warrning : Need to transmit : 'Could not convert' - return; - } - } - return ParserArgs::template GetTypeAtIndexConvert(value, idx - 1); - } - }; - - template - class ParserArgsInterface : public BasicArgsInterface - { - public: - using ContextArgsType = ParserArgs; - - public: - ParserArgsInterface(ParserExecutor& executor, Args&&... args) - : BasicArgsInterface() - , Executor(executor) - , ArgsInterface(std::forward(args)...) - {} - ~ParserArgsInterface() override = default; - - public: - std::size_t Size() override { return ArgsInterface.Size(); } - void RunTypeAtIndex(std::int32_t idx) override - { - return ArgsInterface.RunTypeAtIndex(Executor, idx); - } - std::int32_t GetIndexOfCurrentNamedArg(BufferInfoView& format) override - { - return ArgsInterface.GetIndexOfCurrentNamedArg(format, std::int32_t{0}); - } - PointerID GetTypeAt(std::int32_t idx) override - { - return ArgsInterface.GetTypeAtIndex(idx); - } - - public: - template - T GetTAtConvert(std::int32_t idx) - { - T res; - ArgsInterface.template GetTypeAtIndexConvert(&res, idx); - return res; - } - - std::int32_t GetFormatIndexAt(std::int32_t idx) override { return GetTAtConvert(idx); } - typename std::basic_string_view GetStringAt(std::int32_t idx) override - { - return GetTAtConvert>(idx); - } - int64_t GetIntAt(std::int32_t idx) override { return GetTAtConvert(idx); } - - protected: - ParserExecutor& Executor; - ContextArgsType ArgsInterface; - }; -} diff --git a/src/StreamFormat/FMT/Context/ParserExecutor/ParserTextPropertiesExecutor/ParserANSITextPropertiesExecutor.h b/src/StreamFormat/FMT/Context/ParserExecutor/ParserTextPropertiesExecutor/ParserANSITextPropertiesExecutor.h deleted file mode 100644 index 87be930a..00000000 --- a/src/StreamFormat/FMT/Context/ParserExecutor/ParserTextPropertiesExecutor/ParserANSITextPropertiesExecutor.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include "ParserTextPropertiesExecutor.h" - -namespace StreamFormat::FMT::Detail -{ - template - class ParserANSITextPropertiesExecutor : public IParserTextPropertiesExecutor - { - public: - ParserANSITextPropertiesExecutor() = default; - ~ParserANSITextPropertiesExecutor() override = default; - - using IParserTextPropertiesExecutor::Buffer; - - public: - void AllPropertiesReset() override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', 0, 'm');*/ - } - - public: - void ResetColor() override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', 39, ';', 49, 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColorFG&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColorBG&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColor&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t.Fg) , ';', static_cast(t.Bg), 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::Color24bFG&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[38;2;", t.R, ';', t.G, ';', t.B, 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::Color24bBG&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[48;2;", t.R, ';', t.G, ';', t.B, 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::Color24b&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[38;2;", t.Fg.R, ';', t.Fg.G, ';', t.Fg.B, "; 48; 2;", t.Bg.R, ';', t.Bg.G, ';', t.Bg.B, 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCubeFG&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[38;5;", t.GetColorRef(), 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCubeBG&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[48;5;", t.GetColorRef(), 'm');*/ - } - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCube&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[48;5;", t.Fg.GetColorRef(), ";48;5;", t.Bg.GetColorRef(), 'm');*/ - } - - public: - void ResetFront() override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', Detail::TextProperties::TextFront::FrontID::DefaultFrontID, 'm');*/ - } - void ExecuteFront(const Detail::TextProperties::TextFront::FrontID&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', t.ID, 'm');*/ - } - - public: - void ResetStyle() override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', 0, 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Intensity&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Italic&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Underline&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::Color&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[59m");*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::ColorCube&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[58;5;", t.GetColorRef(), 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::Color24b&) override - { - /*BufferReadManip(Buffer).BasicReadType("\033[58;2;", t.R, ';', t.G, ';', t.B, 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Blink&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Inverted&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Ideogram&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - void ExecuteStyle(const Detail::TextProperties::TextStyle::Script&) override - { - /*BufferReadManip(Buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ - } - }; -} diff --git a/src/StreamFormat/FMT/Context/ParserExecutor/ParserTextPropertiesExecutor/ParserTextPropertiesExecutor.h b/src/StreamFormat/FMT/Context/ParserExecutor/ParserTextPropertiesExecutor/ParserTextPropertiesExecutor.h deleted file mode 100644 index 57fd4cdf..00000000 --- a/src/StreamFormat/FMT/Context/ParserExecutor/ParserTextPropertiesExecutor/ParserTextPropertiesExecutor.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Context/BasicContext/ITextPropertiesExecutor.h" -#include "StreamFormat/FMT/Detail/Detail.h" -#include "StreamFormat/FMT/Context/ParserExecutor/BasicParserExecutor.h" - -namespace StreamFormat::FMT::Detail -{ - template - class IParserTextPropertiesExecutor : public ITextPropertiesExecutor - { - public: - IParserTextPropertiesExecutor() = default; - ~IParserTextPropertiesExecutor() override = default; - - void LinkToExecutor(void* executor) override - { - Buffer = &reinterpret_cast*>(executor)->BufferIn; - } - - protected: - BufferInfoView* Buffer{nullptr}; - }; -} - -namespace StreamFormat::FMT::Detail -{ - template - class ParserNOTextPropertiesExecutor : public IParserTextPropertiesExecutor - { - public: - ParserNOTextPropertiesExecutor() = default; - ~ParserNOTextPropertiesExecutor() override = default; - - using IParserTextPropertiesExecutor::Buffer; - - public: - void AllPropertiesReset() override {} - - public: - void ResetColor() override {} - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColorFG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColorBG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::BasicColor&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::Color24bFG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::Color24bBG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::Color24b&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCubeFG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCubeBG&) override {} - void ExecuteColor(const Detail::TextProperties::TextColor::ColorCube&) override {} - - public: - void ResetFront() override {} - void ExecuteFront(const Detail::TextProperties::TextFront::FrontID&) override {} - - public: - void ResetStyle() override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Intensity&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Italic&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Underline&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::Color&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::ColorCube&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::UnderlineColor::Color24b&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Blink&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Inverted&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Ideogram&) override {} - void ExecuteStyle(const Detail::TextProperties::TextStyle::Script&) override {} - }; -} diff --git a/src/StreamFormat/FMT/Context/ParserExecutor/ParserType.h b/src/StreamFormat/FMT/Context/ParserExecutor/ParserType.h deleted file mode 100644 index f234db17..00000000 --- a/src/StreamFormat/FMT/Context/ParserExecutor/ParserType.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/Detail.h" - -#define STREAMFORMAT_PARSER_DECLARED -namespace StreamFormat::FMT -{ - template > - struct ParserType - { - static inline bool Parse(T&, ParserExecutor&) - { -#ifdef UNKOWN_TYPE_MESSAGE - // FIXME - throw Detail::FMTShouldNotEndHere{}; -#endif -#ifdef UNKOWN_TYPE_THROW - throw Detail::FMTShouldNotEndHere{}; -#endif -#ifdef UNKOWN_TYPE_FAIL - // FIXME - throw Detail::FMTShouldNotEndHere{}; -#endif -#ifdef UNKOWN_TYPE_DEBUG - STREAMFORMAT_DEBUGBREAK(); -#endif - return false; - } - }; - -} - -#define STREAMFORMAT_AUTO_PARSER(Type, fmt, ...) \ - template \ - struct StreamFormat::FMT::ParserType \ - { \ - static bool Parse(Type& value, ParserExecutor& executor) { return executor.Run(fmt, __VA_ARGS__); } \ - }; diff --git a/src/StreamFormat/FMT/Context/ParserExecutor/UtilityFunctions.h b/src/StreamFormat/FMT/Context/ParserExecutor/UtilityFunctions.h deleted file mode 100644 index c214b600..00000000 --- a/src/StreamFormat/FMT/Context/ParserExecutor/UtilityFunctions.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "BasicParserExecutor.h" - -#include "StreamFormat/FMT/Buffer/BufferOutManager/GivenBufferOutManager.h" -#include "StreamFormat/FMT/Buffer/BufferOutManager/StaticBufferOutManager.h" - -#include "ParserTextPropertiesExecutor/ParserANSITextPropertiesExecutor.h" - -namespace StreamFormat::FMT -{ - template - void Parse(Buffer&& bufferInput, Format&& formatInput, Args&&... args) - { - Detail::BufferInfoView buffer{bufferInput}; - Detail::BufferInfoView format{formatInput}; - using TChar = typename decltype(format)::TChar; - - Detail::ParserANSITextPropertiesExecutor> textPropertiesExecutor; - Context::BasicParserExecutor> executor(buffer, textPropertiesExecutor); - executor.Run(format, std::forward(args)...); - executor.Terminate(); - } -} diff --git a/src/StreamFormat/FMT/Context/Utils/ContextFunctions.h b/src/StreamFormat/FMT/Context/Utils/ContextFunctions.h deleted file mode 100644 index d514d24d..00000000 --- a/src/StreamFormat/FMT/Context/Utils/ContextFunctions.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/Specifiers.h" - -namespace StreamFormat::FMT::Detail -{ - template - struct FunctionApplyNextOverride - { - inline explicit FunctionApplyNextOverride(FormatterExecutor& executor) - : Executor(executor) - , FormatData(executor.Data) - { - Executor.FormatDataApplyNextOverride(); - } - - inline ~FunctionApplyNextOverride() { Executor.Data = FormatData; } - - FormatterExecutor& Executor; - Detail::FormatData FormatData; - }; -} diff --git a/src/StreamFormat/FMT/Detail/ConvertTraits.h b/src/StreamFormat/FMT/Detail/ConvertTraits.h deleted file mode 100644 index c270d309..00000000 --- a/src/StreamFormat/FMT/Detail/ConvertTraits.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include "Detail.h" - -namespace StreamFormat::FMT::Detail -{ - template - struct FormatTypeForwardAs - { - using Type = T; - }; - - template - struct FMTContextConvert - { - static constexpr bool IsConvertible = false; - }; - - template - requires(std::is_convertible_v&& std::is_convertible_v) struct FMTContextConvert - { - static constexpr bool IsConvertible = true; - static constexpr To Convert(const From& from) { return static_cast(from); } - }; - - template - requires(std::is_convertible_v&& - std::is_convertible_v) struct FMTContextConvert - { - static constexpr bool IsConvertible = true; - static constexpr std::int32_t Convert(const From& from) { return std::int32_t(static_cast(from)); } - }; - - template - concept FMTCanContextConvert = requires(const From& from) - { - requires FMTContextConvert::IsConvertible; - { - FMTContextConvert::Convert(from) - } -> std::same_as; - }; - - template - struct FMTContextSame - { - static constexpr bool SameAs = false; - }; - - template - requires(std::is_same_v, Detail::GetBaseType>) struct FMTContextSame - { - static constexpr bool SameAs = true; - }; - - template - concept FMTIsContextSame = requires(To* to, const From& from) - { - requires FMTContextSame::SameAs; - *to = from; - }; -} diff --git a/src/StreamFormat/FMT/Detail/Exception.h b/src/StreamFormat/FMT/Detail/Exception.h deleted file mode 100644 index e0405ed2..00000000 --- a/src/StreamFormat/FMT/Detail/Exception.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "StreamFormat/Core/Core.h" - -#include - -// TODO: Better error msg -namespace StreamFormat::FMT::Detail -{ - class FMTException : public std::exception - { - }; - class FMTError : public FMTException - { - public: - const char* what() const noexcept override { return "FMTError"; } - }; - - class FMTParseError : public FMTError - { - public: - const char* what() const noexcept override { return "FMTParseError"; } - }; - class FMTGivenTypeError : public FMTParseError - { - public: - const char* what() const noexcept override { return "FMTGivenTypeError"; } - }; - class FMTGivenIndexError : public FMTParseError - { - public: - const char* what() const noexcept override { return "FMTGivenIndexError"; } - }; - - class FMTImplError : public FMTError - { - public: - const char* what() const noexcept override { return "FMTImplError"; } - }; - class FMTShouldNotEndHere : public FMTImplError - { - public: - const char* what() const noexcept override { return "FMTShouldNotEndHere"; } - }; - class FMTNotImplYet : public FMTImplError - { - public: - const char* what() const noexcept override { return "FMTNotImplYet"; } - }; -} diff --git a/src/StreamFormat/FMT/Detail/IndentHandlers.h b/src/StreamFormat/FMT/Detail/IndentHandlers.h deleted file mode 100644 index 4bbefa46..00000000 --- a/src/StreamFormat/FMT/Detail/IndentHandlers.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Detail/Detail.h" -#include "StreamFormat/FMT/Buffer/FMTBufferOutManip.h" - -namespace StreamFormat::FMT::Detail -{ - template - struct NoStrideFunction - { - inline explicit NoStrideFunction(FMTBufferOutInfo& buffer) - : Buffer(buffer) - , SizeBuffer(BufferAccess(buffer).GetBufferCurrentSize()) - {} - - ~NoStrideFunction() { FMTBufferOutManip(Buffer).AddNoStride(BufferAccess(Buffer).GetBufferCurrentSize() - SizeBuffer); } - - FMTBufferOutInfo& Buffer; - std::size_t SizeBuffer; - }; -} diff --git a/src/StreamFormat/FMT/Detail/Specifiers.h b/src/StreamFormat/FMT/Detail/Specifiers.h deleted file mode 100644 index 13120cbe..00000000 --- a/src/StreamFormat/FMT/Detail/Specifiers.h +++ /dev/null @@ -1,248 +0,0 @@ -#pragma once - -#include "StreamFormat/Core/Core.h" - -#include -#include -#include - -namespace StreamFormat::FMT::Detail -{ - enum class IntegerPrintBase : char - { - Dec = 'd', - Bin = 'b', - BinUpper = 'B', - Hex = 'x', - HexUpper = 'X', - Oct = 'o', - OctUpper = 'O', - }; - - struct ShiftInfo - { - public: - enum class ShiftType : std::int8_t - { - Nothing, - Right, - Left, - CenterRight, - CenterLeft, - Default = Nothing - }; - - struct ShiftPrint - { - public: - constexpr ShiftPrint() - : Before(' ') - , After(' ') - {} - - constexpr ShiftPrint(char c) - : Before(c) - , After(c) - {} - - constexpr ShiftPrint(char before, char after) - : Before(before) - , After(after) - {} - - public: - char Before; - char After; - - public: - constexpr bool BeforeIsADigit() const { return Before >= '0' && Before <= '9'; } - - constexpr void ValidateForNumber() - { - if (After >= '0' && After <= '9') After = ' '; - } - }; - - public: - ShiftType Type = ShiftType::Default; // < - > - ^ - ShiftPrint Print = ShiftPrint{}; // 0 - ' ' - * ..... - std::int32_t Size = -1; // ? - ^? - }; -} - -namespace StreamFormat::FMT::Detail -{ - template - struct FormatSpecifier - { - FormatSpecifier() - : Name(nullptr, 0) - , AsText(nullptr, 0) - , AsNumber(0) - , HasText(false) - , HasNumber(false) - {} - - FormatSpecifier(std::basic_string_view name) - : Name(name) - , AsText(nullptr, 0) - , AsNumber(0) - , HasText(false) - , HasNumber(false) - {} - - FormatSpecifier(std::basic_string_view name, std::basic_string_view value) - : Name(name) - , AsText(value) - , AsNumber(0) - , HasText(true) - , HasNumber(false) - {} - - FormatSpecifier(std::basic_string_view name, const std::int32_t value) - : Name(name) - , AsText(nullptr, 0) - , AsNumber(value) - , HasText(false) - , HasNumber(true) - {} - - FormatSpecifier(std::basic_string_view name, const std::int32_t valueAsNumber, std::basic_string_view valueAsText) - : Name(name) - , AsText(valueAsText) - , AsNumber(valueAsNumber) - , HasText(true) - , HasNumber(true) - {} - - std::basic_string_view Name = ""; - std::basic_string_view AsText = ""; - std::int32_t AsNumber = 0; - bool HasText = false; - bool HasNumber = false; - }; - - template - struct FormatSpecifierList - { - public: - std::uint8_t SpecifierCount = 0; - std::array, SIZE> Specifier{}; - - struct Constraint - { - bool HasText = false; - bool HasNumber = false; - }; - - public: - static inline constexpr std::uint8_t NotFound() { return (std::numeric_limits::max)(); } - - FormatSpecifier* Get(std::basic_string_view name, const Constraint& constraint = Constraint{}) - { - STREAMFORMAT_ASSERT(SpecifierCount <= SIZE); - for (std::uint8_t i = 0; i < SpecifierCount; ++i) - if (Specifier[i].Name == name) - { - bool textContraintsatisfied = !constraint.HasText || Specifier[i].HasText; - bool numberContraintsatisfied = !constraint.HasNumber || Specifier[i].HasNumber; - if (textContraintsatisfied && numberContraintsatisfied) - return &Specifier[i]; - } - return nullptr; - } - - const FormatSpecifier* Get(std::basic_string_view name, const Constraint& constraint = Constraint{}) const - { - STREAMFORMAT_ASSERT(SpecifierCount <= SIZE); - for (std::uint8_t i = 0; i < SpecifierCount; ++i) - if (Specifier[i].Name == name) - { - bool textContraintsatisfied = !constraint.HasText || Specifier[i].HasText; - bool numberContraintsatisfied = !constraint.HasNumber || Specifier[i].HasNumber; - if (textContraintsatisfied && numberContraintsatisfied) - return &Specifier[i]; - } - return nullptr; - } - - bool Has(std::basic_string_view name) const { return Get(name) != nullptr; } - - std::int32_t GetAsNumber(std::basic_string_view name, std::int32_t defaultValue) const - { - const FormatSpecifier* get = Get(name, Constraint{.HasNumber = true}); - if (get == nullptr || !get->HasNumber) - return defaultValue; - return get->AsNumber; - } - - std::basic_string_view GetAsText(std::basic_string_view name, std::basic_string_view defaultValue) const - { - const FormatSpecifier* get = Get(name, Constraint{.HasText = true}); - if (get == nullptr || !get->HasText) - return defaultValue; - return get->AsText; - } - - public: - void Pushback(const FormatSpecifier& specifier) - { - if (SpecifierCount < SIZE) - Specifier[SpecifierCount++] = specifier; - } - - void Concat(const FormatSpecifier& specifier) - { - FormatSpecifier* local = Get(specifier.Name); - if (local == nullptr) - return Pushback(specifier); - - if (specifier.HasText) - { local->HasText = true; local->AsText = specifier.AsText; } - if (specifier.HasNumber) - { local->HasNumber = true; local->AsNumber = specifier.AsNumber; } - } - }; - - template - struct FormatData - { - public: - bool HasSpec = false; - bool KeepNewStyle = false; // W - - bool PrefixSuffix = false; // # - IntegerPrintBase IntegerPrint = IntegerPrintBase::Dec; // B - X - O - D - std::int32_t FloatPrecision = -1; // . - ShiftInfo Shift; - - FormatSpecifierList Specifiers; - - std::basic_string_view NextOverride = std::basic_string_view(nullptr, 0); - - public: - void Apply(const FormatData& given) { *this = given; } - - void Apply(const IntegerPrintBase& given) { IntegerPrint = given; } - void Apply(const ShiftInfo& given) { Shift = given; } - void Apply(const FormatSpecifier& given) { Specifiers.Concat(given); } - - template - bool TestApply(const T* given) - requires requires(const T& value, FormatData& data) - { - data.Apply(value); - } - { - if (given == nullptr) return false; - Apply(*given); - return true; - } - }; - - template - concept FormatDataCanApply = requires(const T& value, FormatData& data) - { - data.Apply(value); - }; -} diff --git a/src/StreamFormat/FMT/Detail/TypesTraits.h b/src/StreamFormat/FMT/Detail/TypesTraits.h deleted file mode 100644 index d2147ac4..00000000 --- a/src/StreamFormat/FMT/Detail/TypesTraits.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "StreamFormat/Core/Core.h" - -#include - -namespace StreamFormat::FMT::Detail -{ - //--------------------------------------------// - //----------------- BaseType -----------------// - //--------------------------------------------// - - template - using GetBaseType = std::remove_cv_t>; - - //------------------------------------------------------// - //----------------- CXX Types Concepts -----------------// - //------------------------------------------------------// - - template - struct IsCharType - { - using BaseType = GetBaseType; - static constexpr bool Value = std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v; - }; -} diff --git a/src/StreamFormat/FMT/Serializers/CompilationData.h b/src/StreamFormat/FMT/Serializers/CompilationData.h deleted file mode 100644 index 6d7d7825..00000000 --- a/src/StreamFormat/FMT/Serializers/CompilationData.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include "StreamFormat/Core/Core.h" -#include "StreamFormat/FLog.h" - -namespace StreamFormat::FMT::Detail -{ - struct FileLocation - { - FileLocation(std::string_view fileName, int fileLine = 0) - : FileName(fileName) - , FileLine(fileLine) - {} - - std::string_view FileName; // __FILE__ - int FileLine; // __LINE__ - }; - - struct FunctionProperties - { - FunctionProperties(std::string_view fileName, int fileLine = 0, std::string_view functionName = "", std::string_view functionSignature = "", - std::string_view functionAssemblyName = "") - : Location(fileName, fileLine) - , FunctionName(functionName) - , FunctionSignature(functionSignature) - , FunctionAssemblyName(functionAssemblyName) - {} - - FunctionProperties(FileLocation location, std::string_view functionName = "", std::string_view functionSignature = "", std::string_view functionAssemblyName = "") - : Location(location) - , FunctionName(functionName) - , FunctionSignature(functionSignature) - , FunctionAssemblyName(functionAssemblyName) - {} - - FileLocation Location; - std::string_view FunctionName; // __FUNCTION__ - std::string_view FunctionSignature; // __FUNCSIG__ -- __PRETTY_FUNCTION__ - std::string_view FunctionAssemblyName; // __FUNCDNAME__ - }; -} - -#define STREAMFORMAT_FMT_FILE_LOCATION() StreamFormat::FMT::Detail::FileLocation(__FILE__, __LINE__) -#define STREAMFORMAT_FMT_FUNCTION_PROPERTIES() StreamFormat::FMT::Detail::FunctionProperties(STREAMFORMAT_FMT_FILE_LOCATION(), __FUNCTION__, __FUNCSIG__, __FUNCDNAME__) - -namespace StreamFormat::FMT -{ - template - struct FormatterType - { - static void Format(const Detail::FileLocation& t, FormatterExecutor& executor) - { - executor.WriteType(t.FileName); - executor.BufferOut.Pushback(':'); - executor.WriteType(t.FileLine); - } - }; - - template - struct FormatterType - { - static void Format(const Detail::FunctionProperties& t, FormatterExecutor& executor) - { - executor.WriteType(t.Location); - executor.BufferOut.WriteCharArray(" @ "); - executor.WriteType(t.FunctionName); - } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/FormatChrono.h b/src/StreamFormat/FMT/Serializers/FormatChrono.h deleted file mode 100644 index b6d34660..00000000 --- a/src/StreamFormat/FMT/Serializers/FormatChrono.h +++ /dev/null @@ -1,157 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferTestManip.h" -#include "StreamFormat/FMT/Buffer/BufferWriteManip.h" -#include "StreamFormat/FMT/Buffer/BufferReadManip.h" -#include "StreamFormat/FMT/Buffer/FMTBufferWriteManip.h" - -#include "StreamFormat/FMT/Context/FormatterExecutor/BasicFormatterExecutor.h" - -#include - -namespace StreamFormat::FMT::Detail -{ - enum class TimePrintMode : std::uint8_t - { - FullTime, - Mod, - Sub, - }; - - template - BufferManipResult WriteSubTime_(const std::chrono::time_point& value, BufferInfoView& pattern, FMTBufferOutInfo& buffer, TimePrintMode mode) - { - ShiftInfo shift; - shift.Type = Detail::ShiftInfo::ShiftType::Right; - shift.Print = Detail::ShiftInfo::ShiftPrint('0', ' '); - BufferReadManip(pattern).FastReadInteger(shift.Size); - - if (mode == TimePrintMode::Mod && shift.Size < 0) - shift.Size = 3; - - if (BufferTestManip(pattern).IsSameForward("ns", 2)) - { - std::uint32_t ns = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); - if (mode == TimePrintMode::Mod) - ns = ns % 1000; - FMTBufferWriteManip(buffer).WriteInteger(static_cast(ns) % 1000, shift); - } - else if (BufferTestManip(pattern).IsSameForward("us", 2)) - { - std::uint32_t us = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); - if (mode == TimePrintMode::Mod) - us = us % 1000; - else if (mode == TimePrintMode::Sub) - us = us / 1000; - FMTBufferWriteManip(buffer).WriteInteger(static_cast(us) % 1000, shift); - } - else if (BufferTestManip(pattern).IsSameForward("ms", 2)) - { - std::uint32_t ms = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); - if (mode == TimePrintMode::Mod) - ms = ms % 1000; - else if (mode == TimePrintMode::Sub) - ms = ms / 1000000; - FMTBufferWriteManip(buffer).WriteInteger(static_cast(ms) % 1000, shift); - } - else if (BufferTestManip(pattern).IsEqualToForward('s')) - { - std::uint32_t sec = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); - if (mode == TimePrintMode::Mod) - sec = sec % 60; - else if (mode == TimePrintMode::Sub) - sec = sec / 1000000000; - FMTBufferWriteManip(buffer).WriteInteger(static_cast(sec) % 1000, shift); - } - else if (BufferTestManip(pattern).IsEqualToForward('m')) - { - std::uint32_t min = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); - if (mode == TimePrintMode::Mod) - min = min % 60; - FMTBufferWriteManip(buffer).WriteInteger(static_cast(min) % 1000, shift); - } - else if (BufferTestManip(pattern).IsEqualToForward('h')) - { - std::uint32_t min = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); - if (mode == TimePrintMode::Mod) - min = min % 24; - FMTBufferWriteManip(buffer).WriteInteger(static_cast(min) % 1000, shift); - } - - return true; - } - - template - BufferManipResult WriteTime(const std::chrono::time_point& value, BufferInfoView pattern, FMTBufferOutInfo& buffer) - { - BufferWriteManip(buffer).FastWriteString( - BufferTestManip(pattern).ViewExec( - [&]{FMTBufferParamsManip(pattern).ParamGoTo('%', '#', '/'); } - ) - ); - - while (!BufferAccess(pattern).IsEndOfString()) - { - TimePrintMode mode; - if (BufferTestManip(pattern).IsEqualToForward('%')) - mode = TimePrintMode::Mod; - else if (BufferTestManip(pattern).IsEqualToForward('#')) - mode = TimePrintMode::FullTime; - else if (BufferTestManip(pattern).IsEqualToForward('/')) - mode = TimePrintMode::Sub; - - WriteSubTime_(value, pattern, buffer, mode); - - BufferWriteManip(buffer).FastWriteString( - BufferTestManip(pattern).ViewExec( - [&]{FMTBufferParamsManip(pattern).ParamGoTo('%', '#', '/'); } - ) - ); - } - - return true; - } -} - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::chrono::time_point& t, FormatterExecutor& executor) - { - Detail::WriteTime(t, Detail::BufferInfoView(executor.Data.Specifiers.GetAsText("pattern", "%h:%m:%s.%ms")), executor.BufferOut); - } - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::chrono::duration& t, FormatterExecutor& executor) - { - if (executor.Data.Specifiers.Has("pattern")) - { - Detail::WriteTime( - std::chrono::time_point>(t), - Detail::BufferInfoView(executor.Data.Specifiers.GetAsText("pattern", "%h:%m:%s.%ms")), - executor.BufferOut - ); - return; - } - Detail::BufferWriteManip(executor.BufferOut).FastWriteInteger(t.count()); - - if constexpr (std::is_same_v, std::chrono::seconds>) - Detail::BufferOutManip(executor.BufferOut).Pushback('s'); - else if constexpr (std::is_same_v, std::chrono::minutes>) - Detail::BufferOutManip(executor.BufferOut).Pushback('m'); - else if constexpr (std::is_same_v, std::chrono::hours>) - Detail::BufferOutManip(executor.BufferOut).Pushback('h'); - else if constexpr (std::is_same_v, std::chrono::milliseconds>) - Detail::BufferOutManip(executor.BufferOut).Pushback('m', 's'); - else if constexpr (std::is_same_v, std::chrono::microseconds>) - Detail::BufferOutManip(executor.BufferOut).Pushback('u', 's'); - else if constexpr (std::is_same_v, std::chrono::nanoseconds>) - Detail::BufferOutManip(executor.BufferOut).Pushback('n', 's'); - } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/FormatSTDLib.h b/src/StreamFormat/FMT/Serializers/FormatSTDLib.h deleted file mode 100644 index 945a7e25..00000000 --- a/src/StreamFormat/FMT/Serializers/FormatSTDLib.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Context/FormatterExecutor/BasicFormatterExecutor.h" - -#include -#include -#include -#include - -namespace StreamFormat::FMT -{ - //------------------------------------------// - //----------------- String -----------------// - //------------------------------------------// - - template - struct FormatterType, FormatterExecutor> - { - static inline void Format(const std::basic_string& t, FormatterExecutor& executor) { Detail::BufferWriteManip(executor.BufferOut).FastWriteString(t); } - }; - - template - struct FormatterType, FormatterExecutor> - { - static inline void Format(std::basic_string_view t, FormatterExecutor& executor) { Detail::BufferWriteManip(executor.BufferOut).FastWriteString(t); } - }; - - template - struct FormatterType, FormatterExecutor> - { - static inline void Format(const std::basic_stringstream& t, FormatterExecutor& executor) { Detail::BufferWriteManip(executor.BufferOut).FastWriteCharArray(t.str(), t.size()); } - }; - - //------------------------------------------// - //----------------- Memory -----------------// - //------------------------------------------// - - // UniquePtr - template - struct FormatterType, FormatterExecutor> - { - static inline void Format(const std::unique_ptr& t, FormatterExecutor& executor) - { - if (executor.Data.TrueValue) - FormatterType::Format(t.get(), executor); - else - FormatterType::Format(*t, executor); - } - }; - - // SharedPtr - template - struct FormatterType, FormatterExecutor> - { - static inline void Format(const std::shared_ptr& t, FormatterExecutor& executor) - { - if (executor.Data.TrueValue) - FormatterType::Format(t.get(), executor); - else - FormatterType::Format(*t, executor); - } - }; - - // WeakPtr - template - struct FormatterType, FormatterExecutor> - { - static inline void Format(const std::weak_ptr& t, FormatterExecutor& executor) { FormatterType, FormatterExecutor>::Format(t.lock(), executor); } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/ParseChrono.h b/src/StreamFormat/FMT/Serializers/ParseChrono.h deleted file mode 100644 index ecc98536..00000000 --- a/src/StreamFormat/FMT/Serializers/ParseChrono.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/ParserExecutor/BasicParserExecutor.h" - -namespace StreamFormat::FMT::Detail -{ - -} - -namespace StreamFormat::FMT -{ - -} diff --git a/src/StreamFormat/FMT/Serializers/ParseSTDLib.h b/src/StreamFormat/FMT/Serializers/ParseSTDLib.h deleted file mode 100644 index 3ffdf841..00000000 --- a/src/StreamFormat/FMT/Serializers/ParseSTDLib.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Context/ParserExecutor/BasicParserExecutor.h" - -#include -#include -#include - -namespace StreamFormat::FMT -{ - // TODO: -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_array.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_array.h deleted file mode 100644 index 867b10cc..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_array.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::array& t, FormatterExecutor& executor) - { - FormatterType>, FormatterExecutor>::Format(t, executor); - } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_deque.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_deque.h deleted file mode 100644 index 4aca7324..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_deque.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::deque& t, FormatterExecutor& executor) { FormatterType>, FormatterExecutor>::Format(t, executor); } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_forward_list.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_forward_list.h deleted file mode 100644 index 3b7224c0..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_forward_list.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::forward_list& t, FormatterExecutor& executor) - { - FormatterType>, FormatterExecutor>::Format(t, executor); - } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_list.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_list.h deleted file mode 100644 index 807d0d3e..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_list.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::list& t, FormatterExecutor& executor) { FormatterType>, FormatterExecutor>::Format(t, executor); } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_map.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_map.h deleted file mode 100644 index 4fca5892..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_map.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -#include "FMT_tuple.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::map& t, FormatterExecutor& executor) { FormatterType>, FormatterExecutor>::Format(t, executor); } - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::multimap& t, FormatterExecutor& executor) - { - FormatterType>, FormatterExecutor>::Format(t, executor); - } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_queue.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_queue.h deleted file mode 100644 index ec5e4901..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_queue.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::queue& t, FormatterExecutor& executor) {} - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_set.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_set.h deleted file mode 100644 index abe66fbf..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_set.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::set& t, FormatterExecutor& executor) { FormatterType>, FormatterExecutor>::Format(t, executor); } - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::multiset& t, FormatterExecutor& executor) { FormatterType>, FormatterExecutor>::Format(t, executor); } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_tuple.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_tuple.h deleted file mode 100644 index c5010805..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_tuple.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT::TupleDetail -{ - template - using NthTypeOf = typename std::tuple_element>::type; - - template - constexpr NthTypeOf& Get(Args&&... args) - { - std::tuple tuple(args...); - return std::get(tuple); - } - - template - static void TupleFormatRec(FormatterExecutor& executor) - {} - - template - static void TupleFormatRec(FormatterExecutor& executor, const T& t) - { - executor.WriteType(t); - } - - template - static void TupleFormatRec(FormatterExecutor& executor, const T& t, Args&&... args) - { - executor.WriteType(t); - executor.BufferOut.Pushback(','); - executor.BufferOut.Pushback(' '); - TupleFormatRec(context, args...); - } -} - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::tuple& t, FormatterExecutor& executor) - { - executor.BufferOut.Pushback('<'); - std::apply([&context](auto&&... args) { TupleDetail::TupleFormatRec(context, args...); }, t); - executor.BufferOut.Pushback('>'); - } - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::pair& t, FormatterExecutor& executor) - { - executor.BufferOut.Pushback('<'); - executor.WriteType(t.first); - executor.BufferOut.Pushback(':'); - executor.WriteType(t.second); - executor.BufferOut.Pushback('>'); - } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_unordered_map.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_unordered_map.h deleted file mode 100644 index a5843f51..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_unordered_map.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -#include -#include "FMT_tuple.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::unordered_map& t, FormatterExecutor& executor) - { - FormatterType>, FormatterExecutor>::Format(t, executor); - } - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::unordered_multimap& t, FormatterExecutor& executor) - { - FormatterType>, FormatterExecutor>::Format(t, executor); - } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_unordered_set.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_unordered_set.h deleted file mode 100644 index fd113ae0..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_unordered_set.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::unordered_set& t, FormatterExecutor& executor) - { - FormatterType>, FormatterExecutor>::Format(t, executor); - } - }; - - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::unordered_multiset& t, FormatterExecutor& executor) - { - FormatterType>, FormatterExecutor>::Format(t, executor); - } - }; -} diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_vector.h b/src/StreamFormat/FMT/Serializers/STDContainer/FMT_vector.h deleted file mode 100644 index acbc42c1..00000000 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_vector.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" - -namespace StreamFormat::FMT -{ - template - struct FormatterType, FormatterExecutor> - { - static void Format(const std::vector& t, FormatterExecutor& executor) { FormatterType>, FormatterExecutor>::Format(t, executor); } - }; -} diff --git a/src/StreamFormat/FMT/TextProperties/TextProperties.h b/src/StreamFormat/FMT/TextProperties/TextProperties.h deleted file mode 100644 index aa52ea13..00000000 --- a/src/StreamFormat/FMT/TextProperties/TextProperties.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "TextPropertiesColor.h" -#include "TextPropertiesFront.h" -#include "TextPropertiesStyle.h" - -namespace StreamFormat::FMT::Detail -{ - struct TextProperties::Properties - { - TextProperties::TextColor::Color Color; - TextProperties::TextStyle::Style Style; - TextProperties::TextFront::Front Front; - }; - - inline bool operator==(const TextProperties::Properties& lhs, const TextProperties::Properties& rhs) - { - return lhs.Color == rhs.Color && lhs.Style == rhs.Style && lhs.Front == rhs.Front; - } -} diff --git a/src/StreamFormat/FMT/TextProperties/TextPropertiesFront.h b/src/StreamFormat/FMT/TextProperties/TextPropertiesFront.h deleted file mode 100644 index 21c5bdfc..00000000 --- a/src/StreamFormat/FMT/TextProperties/TextPropertiesFront.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#include "BaseTextProperties.h" - -namespace StreamFormat::FMT::Detail -{ - struct TextProperties::TextFront - { - struct ResetFront - { - }; - - struct FrontID; - struct Front; - }; - - struct TextProperties::TextFront::FrontID - { - public: - static inline constexpr std::uint8_t DefaultFrontID = 10; - static inline constexpr std::uint8_t MinFrontID = 10; - static inline constexpr std::uint8_t MaxFrontID = 19; - - public: - std::uint8_t ID; - - constexpr FrontID() - : ID(DefaultFrontID) - {} - constexpr FrontID(std::uint8_t id) - : ID(id) - {} - - public: - constexpr bool operator==(const TextProperties::TextFront::FrontID& other) const { return ID == other.ID; } - constexpr bool IsValid() const { return ID > MinFrontID && ID < MaxFrontID; } - }; - - bool operator==(const TextProperties::TextFront::Front& lhs, const TextProperties::TextFront::Front& rhs); - - struct TextProperties::TextFront::Front - { - public: - constexpr Front(const TextProperties::TextFront::FrontID frontId = TextProperties::TextFront::FrontID::DefaultFrontID) - : CurrentID(frontId.IsValid() ? frontId : TextProperties::TextFront::FrontID::DefaultFrontID) - {} - - public: - FrontID CurrentID; - - public: - void ModifyReset() { *this = Front{}; } - - void Apply(const TextProperties::TextFront::ResetFront&) { ModifyReset(); } - void Apply(const TextProperties::TextFront::Front& given) { *this = given; } - void Apply(const TextProperties::TextFront::FrontID& given) { CurrentID = given; } - - public: - bool NeedModif(const TextProperties::TextFront::ResetFront&) { return true; } - bool NeedModif(const TextProperties::TextFront::Front& given) { return *this != given; } - bool NeedModif(const TextProperties::TextFront::FrontID& given) { return CurrentID != given; } - }; - - inline bool operator==(const TextProperties::TextFront::Front& lhs, const TextProperties::TextFront::Front& rhs) - { - return lhs.CurrentID == rhs.CurrentID; - } - - template - concept TextPropertiesFrontCanApply = requires(const T& value, TextProperties::TextFront::Front& data) - { - data.Apply(value); - }; - - template - struct TextPropertiesFrontIsApplyType - { - using BaseType = GetBaseType; - static constexpr bool Value = std::is_same_v || std::is_same_v || - std::is_same_v; - }; - - template - concept TextPropertiesFrontIsApply = TextPropertiesFrontIsApplyType::Value; -} diff --git a/src/StreamFormat/FMT/TextProperties/TextPropertiesStyle.h b/src/StreamFormat/FMT/TextProperties/TextPropertiesStyle.h deleted file mode 100644 index 1b41be54..00000000 --- a/src/StreamFormat/FMT/TextProperties/TextPropertiesStyle.h +++ /dev/null @@ -1,293 +0,0 @@ -#pragma once - -#include "BaseTextProperties.h" -#include "TextPropertiesColor.h" - -namespace StreamFormat::FMT::Detail -{ - struct TextProperties::TextStyle - { - struct ResetStyle - { - }; - - enum class Intensity : std::uint8_t; - enum class Italic : std::uint8_t; - enum class Blink : std::uint8_t; - enum class Inverted : std::uint8_t; - enum class Ideogram : std::uint8_t; - enum class Script : std::uint8_t; - enum class Underline : std::uint8_t; - struct UnderlineColor; - - struct Style; - }; - - enum class TextProperties::TextStyle::Intensity : std::uint8_t - { - Bold = 1, - Dim = 2, - Normal = 22 - }; - - enum class TextProperties::TextStyle::Italic : std::uint8_t - { - Enable = 3, - Disable = 23 - }; - - enum class TextProperties::TextStyle::Underline : std::uint8_t - { - Underlined = 4, - DoubleUnerlined = 21, // may only disable bold - Disable = 24, - - SelectUnderlinedColor = 254 - }; - - enum class TextProperties::TextStyle::Blink : std::uint8_t - { - SlowBlink = 5, - FastBlink = 6, - Disable = 25 - }; - - enum class TextProperties::TextStyle::Inverted : std::uint8_t - { - Enable = 7, - Disable = 27 - }; - - enum class TextProperties::TextStyle::Ideogram : std::uint8_t - { - Underlined = 60, - DoubleUnderlined = 61, - Overlined = 62, - DoubleOverlined = 63, - StressMarking = 64, - AllDisable = 65 - }; - - enum class TextProperties::TextStyle::Script : std::uint8_t - { - Superscript = 74, - Subscript = 75, - AllDisable = 76 - }; - - struct TextProperties::TextStyle::UnderlineColor - { - struct ColorCube; - struct Color24b; - enum class ColorType : std::uint8_t; - union ColorData; - struct Color; - }; - - // No need of virtual destructor since Color24b is purely a renaming of BaseColor24b - struct TextProperties::TextStyle::UnderlineColor::Color24b : public TextProperties::TextColor::BaseColor24b - { - constexpr Color24b(std::uint8_t r = 0, std::uint8_t g = 0, std::uint8_t b = 0) - : TextProperties::TextColor::BaseColor24b(r, g, b) - {} - }; - - // No need of virtual destructor since ColorCube is purely a renaming of BaseColorCube - struct TextProperties::TextStyle::UnderlineColor::ColorCube : public TextProperties::TextColor::BaseColorCube - { - constexpr ColorCube() - : TextProperties::TextColor::BaseColorCube() - {} - constexpr ColorCube(const std::uint8_t color) - : TextProperties::TextColor::BaseColorCube(color) - {} - constexpr ColorCube(const TextProperties::TextColor::BaseColorCube& color) - : TextProperties::TextColor::BaseColorCube(color) - {} - - public: - static ColorCube MakeNormalColor(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeNormalColor(value)); } - - static ColorCube MakeBrightColor(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeBrightColor(value)); } - - static ColorCube Make666CubeColor255(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) - { - return static_cast(TextProperties::TextColor::BaseColorCube::Make666CubeColor255(r, g, b)); - } - - static ColorCube Make666CubeColor5(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) - { - return static_cast(TextProperties::TextColor::BaseColorCube::Make666CubeColor5(r, g, b)); - } - - static ColorCube MakeGrayscaleColor255(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeGrayscaleColor255(value)); } - - static ColorCube MakeGrayscaleColor24(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeGrayscaleColor24(value)); } - }; - - enum class TextProperties::TextStyle::UnderlineColor::ColorType : std::uint8_t - { - Default, - ColorCube, - Color24b - }; - - union TextProperties::TextStyle::UnderlineColor::ColorData - { - constexpr ColorData() - : ColorCube() - {} - - TextProperties::TextStyle::UnderlineColor::ColorCube ColorCube; - TextProperties::TextStyle::UnderlineColor::Color24b Color24b; - }; - - struct TextProperties::TextStyle::UnderlineColor::Color - { - TextProperties::TextStyle::UnderlineColor::ColorData Data; - TextProperties::TextStyle::UnderlineColor::ColorType Type = TextProperties::TextStyle::UnderlineColor::ColorType::Default; - }; - - inline bool operator==(const TextProperties::TextStyle::UnderlineColor::Color& lhs, const TextProperties::TextStyle::UnderlineColor::Color& rhs) - { - if (lhs.Type != rhs.Type) return false; - switch (lhs.Type) - { - case TextProperties::TextStyle::UnderlineColor::ColorType::Default: - return true; - case TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube: - return lhs.Data.ColorCube == rhs.Data.ColorCube; - case TextProperties::TextStyle::UnderlineColor::ColorType::Color24b: - return lhs.Data.Color24b == rhs.Data.Color24b; - } - return false; - } - - bool operator==(const TextProperties::TextStyle::Style& lhs, const TextProperties::TextStyle::Style& rhs); - - struct TextProperties::TextStyle::Style - { - public: - constexpr Style() {} - - TextProperties::TextStyle::Intensity Intensity = TextProperties::TextStyle::Intensity::Normal; - TextProperties::TextStyle::Italic Italic = TextProperties::TextStyle::Italic::Disable; - TextProperties::TextStyle::Blink Blink = TextProperties::TextStyle::Blink::Disable; - TextProperties::TextStyle::Inverted Inverted = TextProperties::TextStyle::Inverted::Disable; - TextProperties::TextStyle::Ideogram Ideogram = TextProperties::TextStyle::Ideogram::AllDisable; - TextProperties::TextStyle::Script Script = TextProperties::TextStyle::Script::AllDisable; - - TextProperties::TextStyle::Underline Underline = TextProperties::TextStyle::Underline::Disable; - TextProperties::TextStyle::UnderlineColor::Color UnderlineColor; - - public: - void ModifyReset() { *this = Style{}; } - - void Apply(const TextProperties::TextStyle::ResetStyle&) { ModifyReset(); } - void Apply(const TextProperties::TextStyle::Style& given) { *this = given; } - void Apply(const TextProperties::TextStyle::Intensity& given) { Intensity = given; } - void Apply(const TextProperties::TextStyle::Italic& given) { Italic = given; } - void Apply(const TextProperties::TextStyle::Underline& given) { Underline = given; } - void Apply(const TextProperties::TextStyle::Blink& given) { Blink = given; } - void Apply(const TextProperties::TextStyle::Inverted& given) { Inverted = given; } - void Apply(const TextProperties::TextStyle::Ideogram& given) { Ideogram = given; } - void Apply(const TextProperties::TextStyle::Script& given) { Script = given; } - - void Apply(const TextProperties::TextStyle::UnderlineColor::Color& given) { UnderlineColor = given; } - void Apply(const TextProperties::TextStyle::UnderlineColor::ColorCube& given) - { - UnderlineColor.Type = TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube; - UnderlineColor.Data.ColorCube = given; - } - void Apply(const TextProperties::TextStyle::UnderlineColor::Color24b& given) - { - UnderlineColor.Type = TextProperties::TextStyle::UnderlineColor::ColorType::Color24b; - UnderlineColor.Data.Color24b = given; - } - - public: - bool NeedModif(const TextProperties::TextStyle::ResetStyle&) { return true; } - bool NeedModif(const TextProperties::TextStyle::Style& given) { return *this != given; } - bool NeedModif(const TextProperties::TextStyle::Intensity& given) { return Intensity != given; } - bool NeedModif(const TextProperties::TextStyle::Italic& given) { return Italic != given; } - bool NeedModif(const TextProperties::TextStyle::Underline& given) { return Underline != given; } - bool NeedModif(const TextProperties::TextStyle::Blink& given) { return Blink != given; } - bool NeedModif(const TextProperties::TextStyle::Inverted& given) { return Inverted != given; } - bool NeedModif(const TextProperties::TextStyle::Ideogram& given) { return Ideogram != given; } - bool NeedModif(const TextProperties::TextStyle::Script& given) { return Script != given; } - - bool NeedModif(const TextProperties::TextStyle::UnderlineColor::Color& given) { return UnderlineColor != given; } - bool NeedModif(const TextProperties::TextStyle::UnderlineColor::ColorCube& given) - { - return UnderlineColor.Type != TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube || UnderlineColor.Data.ColorCube != given; - } - bool NeedModif(const TextProperties::TextStyle::UnderlineColor::Color24b& given) - { - return UnderlineColor.Type != TextProperties::TextStyle::UnderlineColor::ColorType::Color24b || UnderlineColor.Data.Color24b != given; - } - }; - - inline bool operator==(const TextProperties::TextStyle::Style& lhs, const TextProperties::TextStyle::Style& rhs) - { - return lhs.Intensity == rhs.Intensity && lhs.Italic == rhs.Italic && lhs.Blink == rhs.Blink && lhs.Inverted == rhs.Inverted && lhs.Ideogram == rhs.Ideogram && - lhs.Script == rhs.Script && lhs.Underline == rhs.Underline && lhs.UnderlineColor == rhs.UnderlineColor; - } - - template - concept TextPropertiesStyleCanApply = requires(const T& value, TextProperties::TextStyle::Style& data) - { - data.Apply(value); - }; - - template - struct TextPropertiesStyleIsApplyType - { - using BaseType = GetBaseType; - static constexpr bool Value = std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v || - std::is_same_v || - std::is_same_v; - }; - - template - concept TextPropertiesStyleIsApply = TextPropertiesStyleIsApplyType::Value; -} - -namespace StreamFormat::FMT::Detail::OLD -{ - enum class BasicStyle : std::uint8_t - { - Intensity_Bold = static_cast(TextProperties::TextStyle::Intensity::Bold), - Intensity_Dim = static_cast(TextProperties::TextStyle::Intensity::Dim), - Intensity_Normal = static_cast(TextProperties::TextStyle::Intensity::Normal), - - Italic_Enable = static_cast(TextProperties::TextStyle::Italic::Enable), - Italic_Disable = static_cast(TextProperties::TextStyle::Italic::Disable), - - Underline_Underlined = static_cast(TextProperties::TextStyle::Underline::Underlined), - Underline_DoubleUnerlined = static_cast(TextProperties::TextStyle::Underline::DoubleUnerlined), // may only disable bold - Underline_Disable = static_cast(TextProperties::TextStyle::Underline::Disable), - Underline_SelectColor = 255, - - Blink_SlowBlink = static_cast(TextProperties::TextStyle::Blink::SlowBlink), - Blink_FastBlink = static_cast(TextProperties::TextStyle::Blink::FastBlink), - Blink_Disable = static_cast(TextProperties::TextStyle::Blink::Disable), - - Inverted_Enable = static_cast(TextProperties::TextStyle::Inverted::Enable), - Inverted_Disable = static_cast(TextProperties::TextStyle::Inverted::Disable), - - Ideogram_Underlined = static_cast(TextProperties::TextStyle::Ideogram::Underlined), - Ideogram_DoubleUnderlined = static_cast(TextProperties::TextStyle::Ideogram::DoubleUnderlined), - Ideogram_Overlined = static_cast(TextProperties::TextStyle::Ideogram::Overlined), - Ideogram_DoubleOverlined = static_cast(TextProperties::TextStyle::Ideogram::DoubleOverlined), - Ideogram_StressMarking = static_cast(TextProperties::TextStyle::Ideogram::StressMarking), - Ideogram_AllDisable = static_cast(TextProperties::TextStyle::Ideogram::AllDisable), - - Script_Superscript = static_cast(TextProperties::TextStyle::Script::Superscript), - Script_Subscript = static_cast(TextProperties::TextStyle::Script::Subscript), - Script_AllDisable = static_cast(TextProperties::TextStyle::Script::AllDisable) - }; -} diff --git a/src/StreamFormat/Json.h b/src/StreamFormat/Json.h deleted file mode 100644 index d8baa93a..00000000 --- a/src/StreamFormat/Json.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "Json/JsonFactory.h" -#include "Json/JsonObjects.h" - -#include "Json/JsonSerializer.h" -#include "Json/Serializers/Serializers.h" diff --git a/src/StreamFormat/Json/Detail.h b/src/StreamFormat/Json/Detail.h deleted file mode 100644 index cf0e05a1..00000000 --- a/src/StreamFormat/Json/Detail.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace StreamFormat::JSON::Detail -{ - class JsonError : public std::exception - { - public: - JsonError(std::string&& msg) - : m_What(std::move(msg)) - {} - JsonError(const std::string_view msg) - : m_What(msg) - {} - const char* what() const noexcept override { return m_What.c_str(); } - - protected: - std::string m_What; - }; - - class JsonIndexingError : public JsonError - { - public: - JsonIndexingError(std::string&& msg = "") - : JsonError(std::string("JsonIndexingError") + std::move(msg)) - {} - JsonIndexingError(const std::string& msg) - : JsonError(std::string("JsonIndexingError") + msg) - {} - }; - class JsonTypeSerializerNotImpl : public JsonError - { - public: - JsonTypeSerializerNotImpl(std::string&& msg = "") - : JsonError(std::string("JsonTypeSerializerNotImpl") + std::move(msg)) - {} - JsonTypeSerializerNotImpl(const std::string& msg) - : JsonError(std::string("JsonTypeSerializerNotImpl") + msg) - {} - }; - class JsonGivenTypeError : public JsonError - { - public: - JsonGivenTypeError(std::string&& msg = "") - : JsonError(std::string("JsonGivenTypeError") + std::move(msg)) - {} - JsonGivenTypeError(const std::string& msg) - : JsonError(std::string("JsonGivenTypeError") + msg) - {} - }; - class JsonCastError : public JsonError - { - public: - JsonCastError(std::string&& msg = "") - : JsonError(std::string("JsonCastError") + std::move(msg)) - {} - JsonCastError(const std::string& msg) - : JsonError(std::string("JsonCastError") + msg) - {} - }; -} - -namespace StreamFormat::JSON -{ - template - struct JsonObjectSerializer; - template - struct JsonSerializer; -} diff --git a/src/StreamFormat/Json/JsonFactory.h b/src/StreamFormat/Json/JsonFactory.h deleted file mode 100644 index 004d5156..00000000 --- a/src/StreamFormat/Json/JsonFactory.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include "JsonFormatter-inl.h" -#include "JsonFormatter.h" -#include "JsonObjects.h" -#include "JsonParser.h" -#include "JsonSerializer.h" -#include "Serializers/JsonObjectsSerializer.h" -#include "Serializers/Serializers.h" - -#include -#include - -namespace StreamFormat::JSON -{ - class JsonFactory - { - public: - template > - static T FromPath(const std::filesystem::path& path); - template - static void SaveToPath(T& json, const std::filesystem::path& path, Detail::JsonFormatter::FormatSettings settings); - }; -} - -#include "StreamFormat/FMT.h" -namespace StreamFormat::FMT -{ - template - struct FormatterType - { - static void Format(const JSON::JsonObject& object, FormatterExecutor& executor) { executor.WriteType(JSON::FormatAsJson(object)); } - }; -} - -#include -#include -#include "StreamFormat//FMT/Buffer/BufferOutManager/DynamicBufferOutManager.h" -#include "Serializers/JsonObjectsSerializer.h" -namespace StreamFormat::JSON -{ - template - T JsonFactory::FromPath(const std::filesystem::path& path) - { - std::ifstream file(path.string(), std::ios::in); - - if (file.is_open() == false) throw std::runtime_error("unable to open file"); - - std::string buffer; - - file.seekg(0, std::ios::end); - std::streamsize size = file.tellg(); - file.seekg(0, std::ios::beg); - buffer.resize(static_cast(size)); - file.read(buffer.data(), size); - file.close(); - - FMT::Detail::BufferInfoView input(buffer.data(), buffer.size()); - Detail::JsonParser parser(input); - T res; - JsonSerializer::Parse(res, parser); - return res; - } - - template - void JsonFactory::SaveToPath(T& json, const std::filesystem::path& path, Detail::JsonFormatter::FormatSettings settings) - { - std::ofstream file(path.string(), std::ios::out); - - if (file.is_open() == false) throw std::runtime_error("unable to open file"); - - FMT::Detail::DynamicBufferOutManager BufferOutManager(256); - FMT::Detail::BufferOutInfo bufferOut{BufferOutManager}; - Detail::JsonFormatter formatter(bufferOut, settings); - JsonSerializer::Format(json, formatter); - - file.write(BufferOutManager.GetBuffer(), static_cast(BufferOutManager.GetLastGeneratedDataSize())); - file.flush(); - file.close(); - } -} diff --git a/src/StreamFormat/Json/JsonFormatter.h b/src/StreamFormat/Json/JsonFormatter.h deleted file mode 100644 index 1005520a..00000000 --- a/src/StreamFormat/Json/JsonFormatter.h +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once - -#include "JsonObjects.h" -#include "StreamFormat/FMT/Buffer/BufferOutManip.h" - -namespace StreamFormat::JSON::Detail -{ - class JsonFormatter - { - public: - struct FormatSettings - { - std::size_t IndentSize = 4; - bool IndentWithSpaces = true; - bool OneLine = false; - bool OrderedStruct = false; - std::int32_t FloatPrecision = 7; - }; - - public: - JsonFormatter(StreamFormat::FMT::Detail::BufferOutInfo& bufferOut) - : BufferOut(bufferOut) - , Settings() - , m_Indent(0) - {} - JsonFormatter(StreamFormat::FMT::Detail::BufferOutInfo& bufferOut, FormatSettings settings) - : BufferOut(bufferOut) - , Settings(settings) - , m_Indent(0) - {} - - public: - template - void Format(const T& t); - - struct StructIntermediate; - struct ArrayIntermediate; - StructIntermediate GetStructIntermediate(); - ArrayIntermediate GetArrayIntermediate(); - - public: - void Indent() - { - if (Settings.OneLine) return; - - if (Settings.IndentWithSpaces) - FMT::Detail::BufferOutManip(BufferOut).Pushback(' ', m_Indent * Settings.IndentSize); - else - FMT::Detail::BufferOutManip(BufferOut).Pushback('\t', m_Indent * Settings.IndentSize); - } - - void NewLine() - { - if (Settings.OneLine) return; - FMT::Detail::BufferOutManip(BufferOut).Pushback('\n'); - Indent(); - } - void BeginNewObject() { ++m_Indent; } - void EndNewObject() { --m_Indent; } - - public: - StreamFormat::FMT::Detail::BufferOutInfo& BufferOut; - FormatSettings Settings; - - protected: - std::size_t m_Indent; - }; -} - -namespace StreamFormat::JSON::Detail -{ - struct JsonFormatter::StructIntermediate - { - public: - StructIntermediate(JsonFormatter& formatter); - ~StructIntermediate(); - - public: - template - void Format(const std::string_view name, const T& t); - - public: - JsonFormatter& Formatter; - std::uint32_t Idx; - }; - - struct JsonFormatter::ArrayIntermediate - { - public: - ArrayIntermediate(JsonFormatter& formatter); - ~ArrayIntermediate(); - - public: - template - void Format(const T& t); - - public: - JsonFormatter& Formatter; - std::uint32_t Idx; - }; - - inline JsonFormatter::StructIntermediate JsonFormatter::GetStructIntermediate() - { - return JsonFormatter::StructIntermediate(*this); - } - - inline JsonFormatter::ArrayIntermediate JsonFormatter::GetArrayIntermediate() - { - return JsonFormatter::ArrayIntermediate(*this); - } -} diff --git a/src/StreamFormat/Json/JsonObjects.cpp b/src/StreamFormat/Json/JsonObjects.cpp deleted file mode 100644 index 45a154f5..00000000 --- a/src/StreamFormat/Json/JsonObjects.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "JsonObjects.h" -#include "Serializers/JsonObjectsSerializer.h" - -namespace StreamFormat::JSON -{ - void JsonStringObject::ParserExecute(Detail::JsonParser& parser) - { - JsonSerializer::Parse(*this, parser); - } - void JsonStringObject::FormatterExecute(Detail::JsonFormatter& formatter) const - { - JsonSerializer::Format(*this, formatter); - } - - void JsonNumberObject::ParserExecute(Detail::JsonParser& parser) - { - JsonSerializer::Parse(*this, parser); - } - void JsonNumberObject::FormatterExecute(Detail::JsonFormatter& formatter) const - { - JsonSerializer::Format(*this, formatter); - } - - void JsonBooleanObject::ParserExecute(Detail::JsonParser& parser) - { - JsonSerializer::Parse(*this, parser); - } - void JsonBooleanObject::FormatterExecute(Detail::JsonFormatter& formatter) const - { - JsonSerializer::Format(*this, formatter); - } - - void JsonStructObject::ParserExecute(Detail::JsonParser& parser) - { - JsonSerializer::Parse(*this, parser); - } - void JsonStructObject::FormatterExecute(Detail::JsonFormatter& formatter) const - { - JsonSerializer::Format(*this, formatter); - } - - void JsonArrayObject::ParserExecute(Detail::JsonParser& parser) - { - JsonSerializer::Parse(*this, parser); - } - void JsonArrayObject::FormatterExecute(Detail::JsonFormatter& formatter) const - { - JsonSerializer::Format(*this, formatter); - } - - void JsonNullObject::ParserExecute(Detail::JsonParser& parser) - { - JsonSerializer::Parse(*this, parser); - } - void JsonNullObject::FormatterExecute(Detail::JsonFormatter& formatter) const - { - JsonSerializer::Format(*this, formatter); - } -} diff --git a/src/StreamFormat/Json/JsonObjects.h b/src/StreamFormat/Json/JsonObjects.h deleted file mode 100644 index 142addf6..00000000 --- a/src/StreamFormat/Json/JsonObjects.h +++ /dev/null @@ -1,231 +0,0 @@ -#pragma once - -#include "Detail.h" -#include "StreamFormat/FMT.h" - -#include -#include -#include -#include -#include - -namespace StreamFormat::JSON::Detail -{ - class JsonParser; - class JsonFormatter; -} - -namespace StreamFormat::JSON -{ - struct JsonObject - { - public: - enum class ObjectType - { - String, - Number, - Boolean, - Struct, - Array, - Null, - Undefined - }; - - public: - JsonObject() {} - JsonObject(ObjectType type) - : m_Type(type) - {} - - virtual ~JsonObject() = default; - - private: - ObjectType m_Type = ObjectType::Undefined; - - public: - ObjectType GetType() { return m_Type; } - - JsonObject& operator[](const std::size_t index) { return Get(index); } - JsonObject& operator[](const std::string_view subObject) { return Get(subObject); } - - virtual JsonObject& Get(const std::size_t) { throw Detail::JsonIndexingError{}; } - virtual JsonObject& Get(const std::string_view) { throw Detail::JsonIndexingError{}; } - - public: - template - requires std::is_base_of_v T& As() - { - T* t = dynamic_cast(this); - if (t == nullptr) throw Detail::JsonCastError{}; - return *t; - } - - template - requires std::is_base_of_v - const T& As() const - { - const T* t = dynamic_cast(this); - if (t == nullptr) throw Detail::JsonCastError{}; - return *t; - } - - template - T Read() - { - T value; - JsonObjectSerializer::ReadObject(value, *this); - return value; - } - - template - void Write(const T& t) - { - JsonObjectSerializer::WriteObject(t, *this); - } - - std::string ToString() { return FMT::FormatString(*this); } - - public: - virtual void ParserExecute(Detail::JsonParser& parser) = 0; - virtual void FormatterExecute(Detail::JsonFormatter& formatter) const = 0; - }; - - struct JsonStringObject final : public JsonObject - { - JsonStringObject() - : JsonObject(ObjectType::String) - {} - JsonStringObject(const std::string_view value) - : JsonObject(ObjectType::String) - , String(value) - {} - JsonStringObject(std::string&& value) - : JsonObject(ObjectType::String) - , String(std::move(value)) - {} - ~JsonStringObject() override = default; - - public: - std::string String; - - public: - static std::unique_ptr Create() { return std::make_unique(); } - static std::unique_ptr Create(const std::string_view value) { return std::make_unique(value); } - static std::unique_ptr Create(std::string&& value) { return std::make_unique(std::move(value)); } - - public: - void ParserExecute(Detail::JsonParser& parser) override; - void FormatterExecute(Detail::JsonFormatter& formatter) const override; - }; - - struct JsonNumberObject final : public JsonObject - { - JsonNumberObject(double value = 0.0) - : JsonObject(ObjectType::Number) - , Number(value) - {} - ~JsonNumberObject() override = default; - - public: - double Number; - - public: - static std::unique_ptr Create(double value = 0.0) { return std::make_unique(value); } - - public: - void ParserExecute(Detail::JsonParser& parser) override; - void FormatterExecute(Detail::JsonFormatter& formatter) const override; - }; - - struct JsonBooleanObject final : public JsonObject - { - JsonBooleanObject(bool value = false) - : JsonObject(ObjectType::Boolean) - , Boolean(value) - {} - ~JsonBooleanObject() override = default; - - public: - bool Boolean; - - public: - static std::unique_ptr Create(bool value = false) { return std::make_unique(value); } - - public: - void ParserExecute(Detail::JsonParser& parser) override; - void FormatterExecute(Detail::JsonFormatter& formatter) const override; - }; - - struct JsonStructObject final : public JsonObject - { - public: - JsonStructObject() - : JsonObject(ObjectType::Struct) - {} - ~JsonStructObject() override = default; - - public: - static std::unique_ptr Create() { return std::make_unique(); } - - public: - std::unordered_map> Objects; - - public: - void Add(const std::string& name, std::unique_ptr&& object) { Objects.insert({name, std::move(object)}); } - void Add(std::string&& name, std::unique_ptr&& object) { Objects.insert({std::move(name), std::move(object)}); } - JsonObject& Get(const std::string_view subObject) override - { - try - { - return *Objects.at(std::string(subObject)); - } - catch (...) - { - throw Detail::JsonIndexingError{}; - } - } - - public: - void ParserExecute(Detail::JsonParser& parser) override; - void FormatterExecute(Detail::JsonFormatter& formatter) const override; - }; - - struct JsonArrayObject final : public JsonObject - { - public: - JsonArrayObject() - : JsonObject(ObjectType::Array) - {} - ~JsonArrayObject() override = default; - - public: - static std::unique_ptr Create() { return std::make_unique(); } - - public: - std::vector> Objects; - - public: - void Add(std::unique_ptr&& object) { Objects.emplace_back(std::move(object)); } - JsonObject& Get(const std::size_t index) override { return *Objects[index]; } - - public: - void ParserExecute(Detail::JsonParser& parser) override; - void FormatterExecute(Detail::JsonFormatter& formatter) const override; - }; - - struct JsonNullObject final : public JsonObject - { - public: - JsonNullObject() - : JsonObject(ObjectType::Null) - {} - ~JsonNullObject() override = default; - - public: - static std::unique_ptr Create() { return std::make_unique(); } - - public: - void ParserExecute(Detail::JsonParser& parser) override; - void FormatterExecute(Detail::JsonFormatter& formatter) const override; - }; -} diff --git a/src/StreamFormat/Json/JsonParser.cpp b/src/StreamFormat/Json/JsonParser.cpp deleted file mode 100644 index b1ec4537..00000000 --- a/src/StreamFormat/Json/JsonParser.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "Detail.h" - -#include -#include -#include - -#include "JsonSerializer.h" - -namespace StreamFormat::JSON::Detail -{ - void JsonParser::Intermediate::Parse(Detail::JsonParser& parser) - { - FMT::Detail::BufferTestAccess access(parser.BufferIn); - FMT::Detail::BufferTestManip manip(parser.BufferIn); - - manip.SkipAllBlanks(); - const char* begin = parser.BufferIn.CurrentPos; - - if (parser.IsJsonStringBegin()) - { - manip.Skip('"'); - while (true) - { - manip.GoTo('"'); - if (FMT::Detail::BufferTestAccess(parser.BufferIn).PrevIsNotEqualTo('\\')) break; - } - manip.Skip('"'); - } - else if (parser.IsJsonNumberBegin()) - { - float k; - JsonNumberSerializer::ParseFloat(k, parser); - } - else if (parser.IsJsonBooleanBegin()) - { - bool k; - JsonBooleanSerializer::ParseBool(k, parser); - } - else if (parser.IsJsonStructBegin()) - { - JsonStructSerializer::LoadAllSubObjects(*this, parser, [](JsonParser::Intermediate&, std::size_t, std::string&&, JsonParser& jsonParser) { - JsonParser::Intermediate intermediate; - intermediate.Parse(jsonParser); - }); - } - else if (parser.IsJsonArrayBegin()) - { - JsonArraySerializer::LoadAllSubObjects(*this, parser, [](JsonParser::Intermediate&, std::size_t, JsonParser& jsonParser) { - JsonParser::Intermediate intermediate; - intermediate.Parse(jsonParser); - }); - } - else if (parser.IsJsonNullBegin()) - { - JsonNullSerializer::ParseNull(parser); - } - - const char* end = parser.BufferIn.CurrentPos; - Data = std::string_view(begin, end); - }; - - void JsonParser::StructIntermediate::Parse(Detail::JsonParser& parser) - { - JsonStructSerializer::LoadAllSubObjects(*this, parser, - [](JsonParser::StructIntermediate& t, std::size_t, std::string&& name, JsonParser& jsonParser) { - JsonParser::Intermediate intermediate; - intermediate.Parse(jsonParser); - t.Objects.insert({std::move(name), std::move(intermediate)}); - }); - }; - - void JsonParser::ArrayIntermediate::Parse(Detail::JsonParser& parser) - { - JsonArraySerializer::LoadAllSubObjects(*this, parser, [](JsonParser::ArrayIntermediate& t, std::size_t, JsonParser& jsonParser) { - JsonParser::Intermediate intermediate; - intermediate.Parse(jsonParser); - t.Objects.emplace_back(std::move(intermediate)); - }); - }; -} diff --git a/src/StreamFormat/Json/JsonParser.h b/src/StreamFormat/Json/JsonParser.h deleted file mode 100644 index 3672345e..00000000 --- a/src/StreamFormat/Json/JsonParser.h +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once - -#include "StreamFormat/FMT/Buffer/BufferInfo.h" - -#include "JsonObjects.h" - -namespace StreamFormat::JSON::Detail -{ - class JsonParser - { - public: - JsonParser() - : BufferIn() - {} - - JsonParser(FMT::Detail::BufferInfoView& input) - : BufferIn(input) - {} - - public: - inline FMT::Detail::BufferManipResult IsJsonStringBegin() const { return FMT::Detail::BufferTestAccess(BufferIn).IsEqualTo('"'); } - inline FMT::Detail::BufferManipResult IsJsonNumberBegin() const { return FMT::Detail::BufferTestAccess(BufferIn).IsADigit() || FMT::Detail::BufferTestAccess(BufferIn).IsEqualTo('+', '-', '.'); } - inline FMT::Detail::BufferManipResult IsJsonBooleanBegin() const { return FMT::Detail::BufferTestAccess(BufferIn).IsEqualTo('t', 'f'); } - inline FMT::Detail::BufferManipResult IsJsonStructBegin() const { return FMT::Detail::BufferTestAccess(BufferIn).IsEqualTo('{'); } - inline FMT::Detail::BufferManipResult IsJsonArrayBegin() const { return FMT::Detail::BufferTestAccess(BufferIn).IsEqualTo('['); } - inline FMT::Detail::BufferManipResult IsJsonNullBegin() const { return FMT::Detail::BufferTestAccess(BufferIn).IsEqualTo('n'); } - - public: - FMT::Detail::BufferInfo BufferIn; - - public: - struct Intermediate; - - public: - template - void Parse(T& t); - - struct StructIntermediate; - struct ArrayIntermediate; - StructIntermediate GetStructIntermediate(); - ArrayIntermediate GetArrayIntermediate(); - }; -} - -namespace StreamFormat::JSON::Detail -{ - struct JsonParser::Intermediate - { - std::string_view Data; - - void Parse(Detail::JsonParser& parser); - - template - void Parse(T& t) - { - JsonParser parser; - parser.Parse(t); - } - }; - - struct JsonParser::StructIntermediate - { - public: - friend JsonParser; - - private: - std::unordered_map Objects; - - void Parse(Detail::JsonParser& parser); - - public: - template - void Parse(const std::string& name, T& t) - { - if (Objects.contains(name) == false) throw Detail::JsonGivenTypeError{}; - Objects[name].Parse(t); - } - }; - - struct JsonParser::ArrayIntermediate - { - public: - friend JsonParser; - - private: - std::vector Objects; - - void Parse(Detail::JsonParser& parser); - - public: - template - void Parse(const std::size_t idx, T& t) - { - if (idx >= Objects.size()) throw Detail::JsonGivenTypeError{}; - Objects[idx].Parse(t); - } - }; - - inline JsonParser::StructIntermediate JsonParser::GetStructIntermediate() - { - JsonParser::StructIntermediate res; - res.Parse(*this); - return res; - } - inline JsonParser::ArrayIntermediate JsonParser::GetArrayIntermediate() - { - JsonParser::ArrayIntermediate res; - res.Parse(*this); - return res; - } -} diff --git a/src/StreamFormat/Json/JsonSerializer.h b/src/StreamFormat/Json/JsonSerializer.h deleted file mode 100644 index fb3c589d..00000000 --- a/src/StreamFormat/Json/JsonSerializer.h +++ /dev/null @@ -1,356 +0,0 @@ -#pragma once - -#include "JsonFormatter.h" -#include "JsonParser.h" - -#include "StreamFormat/FMT.h" -#include "StreamFormat/FMT/Buffer/BufferReadManip.h" -#include "StreamFormat/FMT/Buffer/BufferWriteManip.h" -#include "StreamFormat/FMT/Buffer/Utils/BufferUtils.h" - -#include -#include - -namespace StreamFormat::JSON -{ - template - struct JsonSerializer - { - static inline void Parse(T&, Detail::JsonParser&) - { -#ifdef UNKOWN_TYPE_MESSAGE - FMT::FilePrint(std::cerr, "{C:red}JsonSerializer::Parse<{}> not impl", typeid(T).name()); -#endif -#ifdef UNKOWN_TYPE_THROW - throw Detail::JsonTypeSerializerNotImpl{}; -#endif -#ifdef UNKOWN_TYPE_FAIL - // FIXME - throw Detail::JsonTypeSerializerNotImpl{}; -#endif -#ifdef UNKOWN_TYPE_DEBUG - STREAMFORMAT_DEBUGBREAK(); -#endif - } - - static inline void Format(const T&, Detail::JsonFormatter& formatter) - { - FMT::Detail::BufferWriteManip(formatter.BufferOut).FastWriteString(std::string_view("Unknown JsonFormatter for type : ")); - FMT::Detail::BufferWriteManip(formatter.BufferOut).FastWriteString(std::string_view(typeid(T).name())); - -#ifdef UNKOWN_TYPE_MESSAGE - FMT::FilePrint(std::cerr, "{C:red}JsonSerializer::Format<{}> not impl", typeid(T).name()); -#endif -#ifdef UNKOWN_TYPE_THROW - throw Detail::JsonTypeSerializerNotImpl{}; -#endif -#ifdef UNKOWN_TYPE_FAIL - // FIXME - throw Detail::JsonTypeSerializerNotImpl{}; -#endif -#ifdef UNKOWN_TYPE_DEBUG - STREAMFORMAT_DEBUGBREAK(); -#endif - } - }; - - template - struct JsonObjectSerializer - { - static inline void ReadObject(T&, const JsonObject&) - { -#ifdef UNKOWN_TYPE_MESSAGE - FMT::FilePrint(std::cerr, "{C:red}JsonObjectSerializer::ReadObject<{}> not impl", typeid(T).name()); -#endif -#ifdef UNKOWN_TYPE_THROW - throw Detail::JsonTypeSerializerNotImpl{}; -#endif -#ifdef UNKOWN_TYPE_FAIL - // FIXME - throw Detail::JsonTypeSerializerNotImpl{}; -#endif -#ifdef UNKOWN_TYPE_DEBUG - STREAMFORMAT_DEBUGBREAK(); -#endif - } - - static inline void WriteObject(const T&, JsonObject&) - { -#ifdef UNKOWN_TYPE_MESSAGE - FMT::FilePrint(std::cerr, "{C:red}JsonObjectSerializer::WriteObject<{}> not impl", typeid(T).name()); -#endif -#ifdef UNKOWN_TYPE_THROW - throw Detail::JsonTypeSerializerNotImpl{}; -#endif -#ifdef UNKOWN_TYPE_FAIL - // FIXME - throw Detail::JsonTypeSerializerNotImpl{}; -#endif -#ifdef UNKOWN_TYPE_DEBUG - STREAMFORMAT_DEBUGBREAK(); -#endif - } - }; - - struct JsonStringSerializer - { - static inline void ParseSTDString(std::string& t, Detail::JsonParser& parser) - { - FMT::Detail::DynamicBufferOutManager bufferData; - FMT::Detail::BufferOutInfo buffer(bufferData); - FMT::Detail::BufferUtils::ParseEscapedQuotedString(parser.BufferIn, buffer); - FMT::Detail::BufferOutManip(buffer).ComputeGeneratedSize(); - t = bufferData.GetLastGeneratedString(); - } - - static inline void FormatSTDString(const std::string_view t, Detail::JsonFormatter& formatter) - { - FMT::Detail::BufferInfo buffer(t.data(), t.size()); - FMT::Detail::BufferUtils::FormatEscapedQuotedString(formatter.BufferOut, buffer); - } - }; - - struct JsonNumberSerializer - { - template - static inline void ParseFloat(FloatType& t, Detail::JsonParser& parser) - { - FMT::Detail::BufferReadManip(parser.BufferIn).FastReadFloat(t); - } - - template - static inline void ParseInteger(IntType& t, Detail::JsonParser& parser) - { - const char* begin = parser.BufferIn.CurrentPos; - float tmp = 0; - FMT::Detail::BufferReadManip(parser.BufferIn).FastReadFloat(tmp); - const char* end = parser.BufferIn.CurrentPos; - - parser.BufferIn.CurrentPos = begin; - FMT::Detail::BufferReadManip(parser.BufferIn).FastReadInteger(t); - parser.BufferIn.CurrentPos = end; - } - - template - static inline void FormatFloat(const FloatType& t, Detail::JsonFormatter& formatter) - { - FMT::Detail::BufferWriteManip(formatter.BufferOut).FastWriteFloat(t, formatter.Settings.FloatPrecision); - } - - template - static inline void FormatInteger(const IntType& t, Detail::JsonFormatter& formatter) - { - FMT::Detail::BufferWriteManip(formatter.BufferOut).FastWriteInteger(t); - } - }; - - struct JsonBooleanSerializer - { - static inline void ParseBool(bool& t, Detail::JsonParser& parser) - { - if (FMT::Detail::BufferTestManip(parser.BufferIn).IsSameForward("true", 5)) - t = true; - else if (FMT::Detail::BufferTestManip(parser.BufferIn).IsSameForward("false", 5)) - t = false; - } - - static inline void FormatBool(const bool& t, Detail::JsonFormatter& formatter) - { - if (t) - FMT::Detail::BufferWriteManip(formatter.BufferOut).FastWriteCharArray("true", 5); - else - FMT::Detail::BufferWriteManip(formatter.BufferOut).FastWriteCharArray("false", 5); - } - }; - - struct JsonStructSerializer - { - template - static inline void LoadAllSubObjects(T& t, Detail::JsonParser& parser, std::function subObjectParsingFunction) - { - FMT::Detail::BufferTestAccess access(parser.BufferIn); - FMT::Detail::BufferTestManip manip(parser.BufferIn); - - manip.Skip('{'); - std::size_t idx = 0; - - while (FMT::Detail::BufferAccess(parser.BufferIn).IsEndOfString() == false) - { - manip.GoTo('"', '}'); - if (access.IsEqualTo('}')) break; - - std::string name; - JsonStringSerializer::ParseSTDString(name, parser); - - manip.SkipAllBlanks(); - manip.Skip(':'); - manip.SkipAllBlanks(); - - subObjectParsingFunction(t, idx++, std::move(name), parser); - - manip.GoTo(',', '}'); - manip.Skip(','); - } - - manip.Skip('}'); - } - - template - static inline void LoadAllSubObjects(T& t, Detail::JsonParser& parserObject) - { - LoadAllSubObjects(t, parserObject, [](T& mainObject, std::size_t idx, std::string&& name, Detail::JsonParser& parser) { - typename JsonSerializer::StructSubObjectType subObject; - parser.Parse(subObject); - JsonSerializer::AddStructSubObject(mainObject, idx, std::move(name), std::move(subObject)); - }); - } - - static inline void FormatBegin(Detail::JsonFormatter& formatter) { FMT::Detail::BufferOutManip(formatter.BufferOut).Pushback('{'); } - - static inline void FormatEnd(Detail::JsonFormatter& formatter) - { - formatter.NewLine(); - FMT::Detail::BufferOutManip(formatter.BufferOut).Pushback('}'); - } - - template - static inline void FormatObject(const std::string_view name, const SubObject& subObject, const std::size_t idx, Detail::JsonFormatter& formatter) - { - if (idx != 0) FMT::Detail::BufferOutManip(formatter.BufferOut).Pushback(','); - - formatter.BeginNewObject(); - formatter.NewLine(); - JsonStringSerializer::FormatSTDString(name, formatter); - FMT::Detail::BufferOutManip(formatter.BufferOut).Pushback(':'); - FMT::Detail::BufferOutManip(formatter.BufferOut).Pushback(' '); - formatter.Format(subObject); - formatter.EndNewObject(); - } - }; - - struct JsonArraySerializer - { - template - static inline void LoadAllSubObjects(T& t, Detail::JsonParser& parser, std::function subObjectParsingFunction) - { - FMT::Detail::BufferTestAccess access(parser.BufferIn); - FMT::Detail::BufferTestManip manip(parser.BufferIn); - - manip.Skip('['); - std::size_t idx = 0; - - while (FMT::Detail::BufferAccess(parser.BufferIn).IsEndOfString() == false) - { - manip.SkipAllBlanks(); - - if (access.IsEqualTo(']')) break; - - subObjectParsingFunction(t, idx++, parser); - - manip.GoTo(',', ']'); - manip.Skip(','); - } - - manip.Skip(']'); - } - - template - static inline void LoadAllSubObjects(T& t, Detail::JsonParser& parser) - { - LoadAllSubObjects(t, parser, [](T& mainObject, std::size_t idx, Detail::JsonParser& jsonParser) { - typename JsonSerializer::ArraySubObjectType subObject; - jsonParser.Parse(subObject); - JsonSerializer::AddArraySubObject(mainObject, idx, std::move(subObject)); - }); - } - - static inline void FormatBegin(Detail::JsonFormatter& formatter) { FMT::Detail::BufferOutManip(formatter.BufferOut).Pushback('['); } - - static inline void FormatEnd(Detail::JsonFormatter& formatter) - { - formatter.NewLine(); - FMT::Detail::BufferOutManip(formatter.BufferOut).Pushback(']'); - } - - template - static inline void FormatObject(const SubObject& subObject, const std::size_t idx, Detail::JsonFormatter& formatter) - { - if (idx != 0) FMT::Detail::BufferOutManip(formatter.BufferOut).Pushback(','); - - formatter.BeginNewObject(); - formatter.NewLine(); - formatter.Format(subObject); - formatter.EndNewObject(); - } - }; - - struct JsonNullSerializer - { - static inline void ParseNull(Detail::JsonParser& parser) { FMT::Detail::BufferTestManip(parser.BufferIn).IsSameForward("null", 4); } - - static inline void FormatNull(Detail::JsonFormatter& formatter) { FMT::Detail::BufferWriteManip(formatter.BufferOut).FastWriteCharArray("null", 4); } - }; -} - -namespace StreamFormat::JSON::Detail -{ - template - void JsonFormatter::Format(const T& t) - { - JsonSerializer::Format(t, *this); - } - - template - void JsonParser::Parse(T& t) - { - JsonSerializer::Parse(t, *this); - } -} - -namespace StreamFormat::JSON -{ - template - struct FormatAsJson - { - public: - FormatAsJson(const T& value) - : Value(value) - {} - - public: - const T& Value; - }; -} - -#include "StreamFormat/FMT.h" -namespace StreamFormat::FMT -{ -#ifdef STREAMFORMAT_FORMATTER_DECLARED - template - struct FormatterType, FormatterExecutor> - { - static void Format(const JSON::FormatAsJson& json, FormatterExecutor& executor) - { - bool ordered_struct = executor.Data.Specifiers.Has("ordered_struct"); - JSON::Detail::JsonFormatter::FormatSettings settings{.OrderedStruct = ordered_struct, .FloatPrecision = executor.Data.FloatPrecision}; - JSON::Detail::JsonFormatter jsonFormatter(executor.BufferOut, settings); - JSON::JsonSerializer::Format(json.Value, jsonFormatter); - } - }; -#endif - -#ifdef STREAMFORMAT_PARSER_DECLARED - template - struct ParserType, ParserExecutor> - { - static inline void Parse(T& json, ParserExecutor& executor) - { - JSON::Detail::JsonParser jsonParser(*executor.BufferIn.Manager); - jsonParser.BufferIn.CurrentPos = executor.BufferIn.CurrentPos; - // TODO: - // JSON::JsonSerializer::Parse(json.Value, jsonParser); - executor.BufferIn.CurrentPos = jsonParser.BufferIn.CurrentPos; - } - }; -#endif -} diff --git a/src/StreamFormat/Json/Serializers/BaseSerializers.h b/src/StreamFormat/Json/Serializers/BaseSerializers.h deleted file mode 100644 index d30fb32e..00000000 --- a/src/StreamFormat/Json/Serializers/BaseSerializers.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include "../JsonObjects.h" -#include "../JsonSerializer.h" - -#include - -namespace StreamFormat::JSON -{ - template - requires (std::is_integral_v && !std::is_floating_point_v) - struct JsonSerializer - { - static inline void Parse(T& t, Detail::JsonParser& parser) { JsonNumberSerializer::ParseInteger(t, parser); } - static inline void Format(const T t, Detail::JsonFormatter& formatter) { JsonNumberSerializer::FormatInteger(t, formatter); } - }; - - template - requires std::is_floating_point_v - struct JsonSerializer - { - static inline void Parse(T& t, Detail::JsonParser& parser) { JsonNumberSerializer::ParseFloat(t, parser); } - static inline void Format(const T t, Detail::JsonFormatter& formatter) { JsonNumberSerializer::FormatFloat(t, formatter); } - }; - - template - struct JsonSerializer - { - using ArraySubObjectType = T; - static inline void AddArraySubObject(T (&t)[SIZE], std::size_t idx, ArraySubObjectType&& subObject) { t[idx] = std::move(subObject); } - - static inline void Parse(T (&t)[SIZE], Detail::JsonParser& parser) - { - if constexpr (FMT::Detail::IsCharType::Value) - { - // TODO - } - else - { - JsonArraySerializer::LoadAllSubObjects(t, parser); - } - } - - static inline void Format(const T (&t)[SIZE], Detail::JsonFormatter& formatter) - { - if constexpr (FMT::Detail::IsCharType::Value) - { - // TODO - } - else - { - JsonArraySerializer::FormatBegin(formatter); - for (std::size_t idx = 0; idx < SIZE; ++idx) - JsonArraySerializer::FormatObject(t[idx], idx, formatter); - JsonArraySerializer::FormatEnd(formatter); - } - } - }; - template - struct JsonSerializer - { - static inline void Parse([[maybe_unused]] T* t, Detail::JsonParser& parser) - { - if (t == nullptr) throw Detail::JsonGivenTypeError{}; - // TODO - } - static inline void Format([[maybe_unused]] const T* t, Detail::JsonFormatter& formatter) - { - if (t == nullptr) throw Detail::JsonGivenTypeError{}; - // TODO - } - }; -} diff --git a/src/StreamFormat/Json/Serializers/JsonObjectsSerializer.h b/src/StreamFormat/Json/Serializers/JsonObjectsSerializer.h deleted file mode 100644 index 247b465c..00000000 --- a/src/StreamFormat/Json/Serializers/JsonObjectsSerializer.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include "../JsonObjects.h" -#include "../JsonSerializer.h" - -#include "STDSerializers/JSON_unordered_map.h" -#include "STDSerializers/JSON_vector.h" - -#include - -namespace StreamFormat::JSON -{ - template <> - struct JsonSerializer> - { - static inline void Parse(std::unique_ptr& t, Detail::JsonParser& parser) - { - FMT::Detail::BufferTestManip(parser.BufferIn).SkipAllBlanks(); - if (parser.IsJsonStringBegin()) - t = std::make_unique(); - else if (parser.IsJsonNumberBegin()) - t = std::make_unique(); - else if (parser.IsJsonBooleanBegin()) - t = std::make_unique(); - else if (parser.IsJsonStructBegin()) - t = std::make_unique(); - else if (parser.IsJsonArrayBegin()) - t = std::make_unique(); - else if (parser.IsJsonNullBegin()) - t = std::make_unique(); - - t->ParserExecute(parser); - } - - static inline void Format(const std::unique_ptr& t, Detail::JsonFormatter& formatter) { t->FormatterExecute(formatter); } - }; - - template <> - struct JsonSerializer - { - static inline void Format(const JsonObject& t, Detail::JsonFormatter& formatter) { t.FormatterExecute(formatter); } - }; - - template <> - struct JsonSerializer - { - static inline void Parse(JsonStringObject& t, Detail::JsonParser& parser) - { - t.String.clear(); - JsonStringSerializer::ParseSTDString(t.String, parser); - } - - static inline void Format(const JsonStringObject& t, Detail::JsonFormatter& formatter) { JsonStringSerializer::FormatSTDString(t.String, formatter); } - }; - - template <> - struct JsonSerializer - { - static inline void Parse(JsonNumberObject& t, Detail::JsonParser& parser) { JsonNumberSerializer::ParseFloat(t.Number, parser); } - - static inline void Format(const JsonNumberObject& t, Detail::JsonFormatter& formatter) { JsonNumberSerializer::FormatFloat(t.Number, formatter); } - }; - - template <> - struct JsonSerializer - { - static inline void Parse(JsonBooleanObject& t, Detail::JsonParser& parser) { JsonBooleanSerializer::ParseBool(t.Boolean, parser); } - - static inline void Format(const JsonBooleanObject& t, Detail::JsonFormatter& formatter) { JsonBooleanSerializer::FormatBool(t.Boolean, formatter); } - }; - - template <> - struct JsonSerializer - { - static inline void Parse(JsonNullObject&, Detail::JsonParser& parser) { JsonNullSerializer::ParseNull(parser); } - - static inline void Format(const JsonNullObject&, Detail::JsonFormatter& formatter) { JsonNullSerializer::FormatNull(formatter); } - }; - - template <> - struct JsonSerializer - { - static inline void Parse(JsonStructObject& t, Detail::JsonParser& parser) { parser.Parse(t.Objects); } - static inline void Format(const JsonStructObject& t, Detail::JsonFormatter& formatter) - { - if (formatter.Settings.OrderedStruct == false) - { - formatter.Format(t.Objects); - return; - } - - std::map objectsOrdered; - for (auto& [name, objects] : t.Objects) - objectsOrdered.insert({name, objects.get()}); - formatter.Format(objectsOrdered); - } - }; - - template <> - struct JsonSerializer - { - static inline void Parse(JsonArrayObject& t, Detail::JsonParser& parser) { parser.Parse(t.Objects); } - static inline void Format(const JsonArrayObject& t, Detail::JsonFormatter& formatter) { formatter.Format(t.Objects); } - }; -} diff --git a/src/StreamFormat/Json/Serializers/STDSerializers/BasicSTDSerializers.h b/src/StreamFormat/Json/Serializers/STDSerializers/BasicSTDSerializers.h deleted file mode 100644 index 881f418b..00000000 --- a/src/StreamFormat/Json/Serializers/STDSerializers/BasicSTDSerializers.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "StreamFormat/Json/JsonSerializer.h" - -#include - -namespace StreamFormat::JSON -{ - template <> - struct JsonSerializer - { - static inline void Parse(std::string& t, Detail::JsonParser& parser) { JsonStringSerializer::ParseSTDString(t, parser); } - static inline void Format(const std::string& t, Detail::JsonFormatter& formatter) { JsonStringSerializer::FormatSTDString(t, formatter); } - }; - - template <> - struct JsonSerializer - { - static inline void Parse(std::string_view& t, Detail::JsonParser& parser) - { - // TODO: - } - static inline void Format(const std::string_view& t, Detail::JsonFormatter& formatter) { JsonStringSerializer::FormatSTDString(t, formatter); } - }; -} diff --git a/src/StreamFormat/Json/Serializers/STDSerializers/JSON_map.h b/src/StreamFormat/Json/Serializers/STDSerializers/JSON_map.h deleted file mode 100644 index 498104dd..00000000 --- a/src/StreamFormat/Json/Serializers/STDSerializers/JSON_map.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "StreamFormat/Json/JsonSerializer.h" - -#include - -namespace StreamFormat::JSON -{ - template - struct JsonSerializer> - { - using KeyType = K; - using StructSubObjectType = T; - - static inline void Parse(std::map& t, Detail::JsonParser& parser) { JsonStructSerializer::LoadAllSubObjects>(t, parser); } - static inline void AddStructSubObject(std::map& t, std::size_t, std::string&& name, StructSubObjectType&& subObject) - { - t.insert({std::move(name), std::move(subObject)}); - } - - static inline void Format(const std::map& t, Detail::JsonFormatter& formatter) - { - JsonStructSerializer::FormatBegin(formatter); - std::size_t idx = 0; - for (const auto& [name, object] : t) - JsonStructSerializer::FormatObject(name, object, idx++, formatter); - JsonStructSerializer::FormatEnd(formatter); - } - }; - - template - struct JsonSerializer> - { - using KeyType = K; - using StructSubObjectType = T; - - static inline void Parse(std::multimap& t, Detail::JsonParser& parser) { JsonStructSerializer::LoadAllSubObjects>(t, parser); } - static inline void AddStructSubObject(std::multimap& t, std::size_t, std::string&& name, StructSubObjectType&& subObject) - { - t.insert({std::move(name), std::move(subObject)}); - } - - static inline void Format(const std::multimap& t, Detail::JsonFormatter& formatter) - { - JsonStructSerializer::FormatBegin(formatter); - std::size_t idx = 0; - for (const auto& [name, object] : t) - JsonStructSerializer::FormatObject(name, object, idx++, formatter); - JsonStructSerializer::FormatEnd(formatter); - } - }; -} diff --git a/src/StreamFormat/Json/Serializers/STDSerializers/JSON_vector.h b/src/StreamFormat/Json/Serializers/STDSerializers/JSON_vector.h deleted file mode 100644 index 7b9426b4..00000000 --- a/src/StreamFormat/Json/Serializers/STDSerializers/JSON_vector.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "StreamFormat/Json/JsonObjects.h" -#include "StreamFormat/Json/JsonSerializer.h" - -#include - -namespace StreamFormat::JSON -{ - template - struct JsonSerializer> - { - using ArraySubObjectType = T; - - static inline void Parse(std::vector& t, Detail::JsonParser& parser) { JsonArraySerializer::LoadAllSubObjects>(t, parser); } - static inline void AddArraySubObject(std::vector& t, std::size_t, ArraySubObjectType&& subObject) { t.emplace_back(std::move(subObject)); } - - static inline void Format(const std::vector& t, Detail::JsonFormatter& formatter) - { - JsonArraySerializer::FormatBegin(formatter); - std::size_t idx = 0; - for (const ArraySubObjectType& subObject : t) - JsonArraySerializer::FormatObject(subObject, idx++, formatter); - JsonArraySerializer::FormatEnd(formatter); - } - }; -} diff --git a/src/StreamFormat/Json/Serializers/Serializers.h b/src/StreamFormat/Json/Serializers/Serializers.h deleted file mode 100644 index 619981f0..00000000 --- a/src/StreamFormat/Json/Serializers/Serializers.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "BaseSerializers.h" -#include "JsonObjectsSerializer.h" -#include "STDSerializers/BasicSTDSerializers.h" diff --git a/src/StreamFormat/ProfilerManager.h b/src/StreamFormat/ProfilerManager.h deleted file mode 100644 index 1f005310..00000000 --- a/src/StreamFormat/ProfilerManager.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "ProfilerManager/Profiler.h" -#include "ProfilerManager/ProfilerFactory.h" diff --git a/src/StreamFormat/ProfilerManager/AllEvents.h b/src/StreamFormat/ProfilerManager/AllEvents.h deleted file mode 100644 index e964438a..00000000 --- a/src/StreamFormat/ProfilerManager/AllEvents.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "Event.h" - -namespace StreamFormat::ProfilerManager -{ - class DurationEvent : public Event - { - public: - DurationEvent(const std::string& name, const std::string& category = "DurationEvent") - : Event(name, category, EventType::Complete) - {} - - DurationEvent(std::string&& name, std::string&& category = "DurationEvent") - : Event(std::move(name), std::move(category), EventType::Complete) - {} - - ~DurationEvent() override = default; - - public: - void Start() { Trigger(); } - void Stop() { Info.Duration = ProfilerManager::GetMicroseconds() - Info.TimeOfEvent; } - }; - - class SampleEvent : public Event - { - public: - SampleEvent(const std::string& name, const std::string& category = "SampleEvent") - : Event(name, category, EventType::Sample) - {} - - SampleEvent(std::string&& name, std::string&& category) - : Event(std::move(name), std::move(category), EventType::Sample) - {} - - ~SampleEvent() override = default; - }; -} diff --git a/src/StreamFormat/ProfilerManager/Detail.h b/src/StreamFormat/ProfilerManager/Detail.h deleted file mode 100644 index af796c37..00000000 --- a/src/StreamFormat/ProfilerManager/Detail.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -namespace StreamFormat::ProfilerManager -{ - inline double GetMicroseconds() - { - return (double)std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()).time_since_epoch().count() / 1000; - } -}; diff --git a/src/StreamFormat/ProfilerManager/Event.h b/src/StreamFormat/ProfilerManager/Event.h deleted file mode 100644 index 57cca1d0..00000000 --- a/src/StreamFormat/ProfilerManager/Event.h +++ /dev/null @@ -1,134 +0,0 @@ -#pragma once - -#include "Detail.h" -#include "EventData.h" -#include "StreamFormat/Core/Core.h" -#include "StreamFormat/FMT.h" - -#include -#include -#include - -// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview - -namespace StreamFormat::ProfilerManager -{ - int GetPid(); - - enum class EventType : char - { - Unknow = '.', - - DurationBegin = 'B', - DurationEnd = 'E', - - AsyncStart = 'b', - AsyncInstant = 'n', - AsyncEnd = 'e', - - FlowStart = 's', - FlowStep = 't', - FlowEnd = 'f', - - ObjectCreated = 'N', - ObjectSnapshot = 'O', - ObjectDestroyed = 'D', - - MemoryDumpGlobal = 'V', - MemoryDumpProcess = 'v', - - Complete = 'X', - Instant = 'i', - Counter = 'C', - Sample = 'P', - MetaData = 'M', - Mark = 'R', - ClockSyncEvents = 'c', - Context = ',' // '(' ')' - }; - - struct EventInfo - { - public: - EventInfo() - : Name("Unknow") - , Category("Unknow") - , Type(EventType::Unknow) - , Id(0) - , TimeOfEvent(ProfilerManager::GetMicroseconds()) - , ThreadTimeOfEvent(0) - , Duration(0) - , PID(GetPid()) - , TID(std::hash{}(std::this_thread::get_id())) - , Data(nullptr) - {} - - EventInfo(const std::string& name, const std::string& category, EventType type, EventData* data = nullptr) - : Name(name) - , Category(category) - , Type(type) - , Id(0) - , TimeOfEvent(ProfilerManager::GetMicroseconds()) - , ThreadTimeOfEvent(0) - , Duration(0) - , PID(GetPid()) - , TID(std::hash{}(std::this_thread::get_id())) - , Data(data) - {} - - EventInfo(std::string&& name, std::string&& category, EventType type, EventData* data = nullptr) - : Name(std::move(name)) - , Category(std::move(category)) - , Type(type) - , Id(0) - , TimeOfEvent(ProfilerManager::GetMicroseconds()) - , ThreadTimeOfEvent(0) - , Duration(0) - , PID(GetPid()) - , TID(std::hash{}(std::this_thread::get_id())) - , Data(data) - {} - - public: - std::string Name; - std::string Category; - EventType Type; - std::size_t Id; - double TimeOfEvent, ThreadTimeOfEvent; - double Duration; - int PID; - std::size_t TID; - std::shared_ptr Data; - }; - - struct Event - { - public: - Event() = default; - - Event(const std::string& name, const std::string& category, EventType type, EventData* data = nullptr) - : Info(name, category, type, data) - {} - - Event(std::string&& name, std::string&& category, EventType type, EventData* data = nullptr) - : Info(std::move(name), std::move(category), type, data) - {} - - virtual ~Event() = default; - - public: - void Trigger() { Info.TimeOfEvent = ProfilerManager::GetMicroseconds(); } - - public: - EventInfo Info; - }; -} - -namespace StreamFormat::FMT -{ - template - struct FormatterType - { - static void Format(const StreamFormat::ProfilerManager::EventType& t, FormatterExecutor& executor) { executor.BufferOut.Pushback(static_cast(t)); } - }; -} diff --git a/src/StreamFormat/ProfilerManager/EventData.h b/src/StreamFormat/ProfilerManager/EventData.h deleted file mode 100644 index cd7dc794..00000000 --- a/src/StreamFormat/ProfilerManager/EventData.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "StreamFormat/Json.h" - -namespace StreamFormat::ProfilerManager -{ - class EventData - { - public: - virtual ~EventData() = default; - - public: - virtual void ToJson(JSON::Detail::JsonFormatter& formatter) const = 0; - virtual void FromJson(JSON::Detail::JsonParser& parser) = 0; - }; - - class EventDataJsonObject final : public EventData - { - public: - ~EventDataJsonObject() override = default; - - public: - void ToJson(JSON::Detail::JsonFormatter& formatter) const override { JSON::JsonSerializer::Format(Data, formatter); } - void FromJson(JSON::Detail::JsonParser& parser) override { JSON::JsonSerializer::Parse(Data, parser); } - JSON::JsonStructObject Data; - }; -} diff --git a/src/StreamFormat/ProfilerManager/Profiler.h b/src/StreamFormat/ProfilerManager/Profiler.h deleted file mode 100644 index d5a20e2f..00000000 --- a/src/StreamFormat/ProfilerManager/Profiler.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "StreamFormat/Core/Core.h" -#include "StreamFormat/FLog.h" - -#include "AllEvents.h" -#include "Event.h" -#include "ProfilerEventCreator.h" - -namespace StreamFormat::ProfilerManager -{ - class Profiler - { - public: - explicit Profiler(std::string&& name) - : Name(name) - , Logger(name) - , ProfilerDuration(name) - { - Events.clear(); - Events.push_back(EventInfo{}); - ProfilerDuration.Start(); - } - - ~Profiler() {} - - public: - void AddEvent(const Event& event) { AddEventInfo(event.Info); } - void AddEventInfo(const EventInfo& eventInfo) { Events.push_back(eventInfo); } - inline StreamFormat::FLog::BasicLogger& GetLogger() { return Logger; } - - public: - static Profiler& GetInstance() - { - static Profiler profiler("Profiler"); - return profiler; - } - - public: - std::string Name; - FLog::BasicLogger Logger; - DurationEvent ProfilerDuration; - std::vector Events; - }; -} diff --git a/src/StreamFormat/ProfilerManager/ProfilerEventCreator.cpp b/src/StreamFormat/ProfilerManager/ProfilerEventCreator.cpp deleted file mode 100644 index 4114b2b2..00000000 --- a/src/StreamFormat/ProfilerManager/ProfilerEventCreator.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "ProfilerEventCreator.h" -#include "Profiler.h" - -namespace StreamFormat::ProfilerManager -{ - ScopeProfile::~ScopeProfile() - { - Stop(); - - double millis = Info.Duration / 1000; - double sec = millis / 1000; - - if (sec > 1.5) - m_Profiler.GetLogger().Trace("{} : {} seconds", Info.Name, sec); - else if (millis > 5.0) - m_Profiler.GetLogger().Trace("{} : {} ms", Info.Name, millis); - else - m_Profiler.GetLogger().Trace("{} : {} us", Info.Name, Info.Duration); - - m_Profiler.AddEvent(*this); - } - - ObjectTracker::ObjectTracker(Profiler& profiler, const std::string& name, const std::string& category) - : m_Profiler(profiler) - , m_Name(name) - , m_Category(category) - { - Event created(m_Name, m_Category, EventType::ObjectCreated); - m_Profiler.AddEvent(created); - } - - ObjectTracker::ObjectTracker(Profiler& profiler, std::string&& name, std::string&& category) - : m_Profiler(profiler) - , m_Name(std::move(name)) - , m_Category(std::move(category)) - { - Event created(m_Name, m_Category, EventType::ObjectCreated); - created.Info.Id = 10; - m_Profiler.AddEvent(created); - } - - ObjectTracker::~ObjectTracker() - { - Event destroyed(m_Name, m_Category, EventType::ObjectDestroyed); - destroyed.Info.Id = 10; - m_Profiler.AddEvent(destroyed); - } - - void ObjectTracker::Snapshot() - { - Event snapshot(m_Name, m_Category, EventType::ObjectSnapshot); - snapshot.Info.Id = 10; - m_Profiler.AddEvent(snapshot); - } - - void EventCounter::Snapshot() - { - m_Idx++; - Event snapshot(m_Name, m_Category, EventType::Counter); - m_Profiler.AddEvent(snapshot); - } -} diff --git a/src/StreamFormat/ProfilerManager/ProfilerEventCreator.h b/src/StreamFormat/ProfilerManager/ProfilerEventCreator.h deleted file mode 100644 index 6bf6b7da..00000000 --- a/src/StreamFormat/ProfilerManager/ProfilerEventCreator.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include "AllEvents.h" - -namespace StreamFormat::ProfilerManager -{ - class Profiler; - - class ScopeProfile : public DurationEvent - { - public: - ScopeProfile(Profiler& profiler, const std::string& name, const std::string& category = "ScopeProfiler") - : DurationEvent(name, category) - , m_Profiler(profiler) - { - Start(); - } - - ScopeProfile(Profiler& profiler, std::string&& name, std::string&& category = "ScopeProfiler") - : DurationEvent(std::move(name), std::move(category)) - , m_Profiler(profiler) - { - Start(); - } - - ~ScopeProfile() override; - - private: - Profiler& m_Profiler; - }; - - class ObjectTracker - { - public: - ObjectTracker(Profiler& profiler, const std::string& name, const std::string& category = "Tracker"); - ObjectTracker(Profiler& profiler, std::string&& name, std::string&& category = "Tracker"); - virtual ~ObjectTracker(); - - public: - void Snapshot(); - - private: - Profiler& m_Profiler; - std::string m_Name; - std::string m_Category; - }; - - class EventCounter - { - public: - EventCounter(Profiler& profiler, const std::string& name, const std::string& category = "EventCounter") - : m_Profiler(profiler) - , m_Name(name) - , m_Category(category) - , m_Idx(0) - {} - - EventCounter(Profiler& profiler, std::string&& name, std::string&& category = "EventCounter") - : m_Profiler(profiler) - , m_Name(std::move(name)) - , m_Category(std::move(category)) - , m_Idx(0) - {} - - public: - void Snapshot(); - - private: - Profiler& m_Profiler; - std::string m_Name; - std::string m_Category; - std::uint64_t m_Idx; - }; -} diff --git a/src/StreamFormat/ProfilerManager/ProfilerFactory.cpp b/src/StreamFormat/ProfilerManager/ProfilerFactory.cpp deleted file mode 100644 index c5a3e13b..00000000 --- a/src/StreamFormat/ProfilerManager/ProfilerFactory.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "ProfilerFactory.h" -#include "ProfilerJsonSerializers.h" - -#include - -namespace StreamFormat::ProfilerManager -{ - void ProfilerFactory::ToJson(Profiler& profiler, std::filesystem::path path) - { - profiler.ProfilerDuration.Stop(); - profiler.Events[0] = profiler.ProfilerDuration.Info; - - if (path == "") path = std::string(profiler.Name) + ".json"; - - std::ofstream file(path.string(), std::ios::out); - JSON::FormatAsJson formatProfiler(profiler); - FMT::FilePrint(file, formatProfiler); - file.close(); - } -} diff --git a/src/StreamFormat/ProfilerManager/ProfilerFactory.h b/src/StreamFormat/ProfilerManager/ProfilerFactory.h deleted file mode 100644 index c363bf11..00000000 --- a/src/StreamFormat/ProfilerManager/ProfilerFactory.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "Profiler.h" - -#include - -namespace StreamFormat::ProfilerManager -{ - class ProfilerFactory - { - public: - static void ToJson(Profiler& profiler, std::filesystem::path path = ""); - }; -} diff --git a/src/StreamFormat/ProfilerManager/ProfilerJsonSerializers.h b/src/StreamFormat/ProfilerManager/ProfilerJsonSerializers.h deleted file mode 100644 index 8c432951..00000000 --- a/src/StreamFormat/ProfilerManager/ProfilerJsonSerializers.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include "ProfilerFactory.h" -#include "StreamFormat/Json.h" - -namespace StreamFormat::JSON -{ - template <> - struct JsonSerializer - { - static inline void Format(const ProfilerManager::Profiler& t, Detail::JsonFormatter& formatter) - { - auto intermediate = formatter.GetStructIntermediate(); - intermediate.Format("displayTimeUnit", "us"); - intermediate.Format("traceEvents", t.Events); - } - - static inline void Parse(ProfilerManager::Profiler& t, Detail::JsonParser& parser) - { - auto intermediate = parser.GetStructIntermediate(); - intermediate.Parse("traceEvents", t.Events); - } - }; - - template <> - struct JsonSerializer - { - static inline void Format(const ProfilerManager::EventType& t, Detail::JsonFormatter& formatter) { formatter.Format(static_cast(t)); } - - static inline void Parse(ProfilerManager::EventType& t, Detail::JsonParser& parser) { parser.Parse(reinterpret_cast(t)); } - }; - - template <> - struct JsonSerializer - { - static inline void Format(const ProfilerManager::EventData& t, Detail::JsonFormatter& formatter) { t.ToJson(formatter); } - - static inline void Parse(ProfilerManager::EventData& t, Detail::JsonParser& parser) { t.FromJson(parser); } - }; - - template <> - struct JsonSerializer - { - static inline void Format(const ProfilerManager::EventInfo& t, Detail::JsonFormatter& formatter) - { - auto intermediate = formatter.GetStructIntermediate(); - intermediate.Format("name", t.Name); - intermediate.Format("cat", t.Category); - intermediate.Format("ph", t.Type); - intermediate.Format("pid", t.PID); - intermediate.Format("tid", t.TID); - intermediate.Format("ts", t.TimeOfEvent); - intermediate.Format("dur", t.Duration); - intermediate.Format("id", t.Id); - if (t.Data != nullptr) intermediate.Format("args", *t.Data); - } - - static inline void Parse(ProfilerManager::EventInfo& t, Detail::JsonParser& parser) - { - auto intermediate = parser.GetStructIntermediate(); - intermediate.Parse("name", t.Name); - intermediate.Parse("cat", t.Category); - intermediate.Parse("ph", t.Type); - intermediate.Parse("pid", t.PID); - intermediate.Parse("tid", t.TID); - intermediate.Parse("ts", t.TimeOfEvent); - intermediate.Parse("dur", t.Duration); - intermediate.Parse("id", t.Id); - intermediate.Parse("args", *t.Data); - } - }; - - template <> - struct JsonSerializer - { - static inline void Format(const ProfilerManager::Event& t, Detail::JsonFormatter& formatter) - { - return JsonSerializer::Format(t.Info, formatter); - } - - static inline void Parse(ProfilerManager::Event& t, Detail::JsonParser& parser) { return JsonSerializer::Parse(t.Info, parser); } - }; -} diff --git a/src/StreamFormat/ProfilerManager/ProfilerMacro.h b/src/StreamFormat/ProfilerManager/ProfilerMacro.h deleted file mode 100644 index 5f6059f3..00000000 --- a/src/StreamFormat/ProfilerManager/ProfilerMacro.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#ifdef STREAMFORMAT_PROFILING_ENABLE - -#define PCP_PROFILE_FUNCTION() StreamFormat::ProfilerManager::ScopeProfile profile##__LINE__(StreamFormat::ProfilerManager::Profiler::GetInstance(), __FUNCSIG__, "Function") -#define PCP_PROFILE_FUNCTION_FMT(...) \ - StreamFormat::ProfilerManager::ScopeProfile profile##__LINE__(StreamFormat::ProfilerManager::Profiler::GetInstance(), \ - StreamFormat::ProfilerManager::FMT::FormatString(__VA_ARGS__), "Function") -#define PCP_SAVE_DEFAULT_PROFILER() StreamFormat::ProfilerManager::ProfilerFactory::ToJson(StreamFormat::ProfilerManager::Profiler::GetInstance()) - -#else // STREAMFORMAT_PROFILING_ENABLE - -#define PCP_PROFILE_FUNCTION() -#define PCP_PROFILE_FUNCTION_FMT(...) -#define PCP_SAVE_DEFAULT_PROFILER() - -#endif // STREAMFORMAT_PROFILING_ENABLE diff --git a/src/StreamFormat/Tester/CopyMoveCheck.h b/src/StreamFormat/Tester/CopyMoveCheck.h deleted file mode 100644 index a953ae4c..00000000 --- a/src/StreamFormat/Tester/CopyMoveCheck.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include "StreamFormat/FLog.h" - -namespace StreamFormat::Tester -{ - class CopyMoveCheck - { - public: - static inline FLog::BasicLogger Logger; - - public: - CopyMoveCheck(const std::string& name) - : m_Name(name) - { - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Default (copy string) Constructor", "TestCopy(const std::string& name)"); - } - - CopyMoveCheck(std::string&& name) - : m_Name(std::move(name)) - { - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Default (move string) Constructor", "TestCopy(std::string&& name)"); - } - - CopyMoveCheck(CopyMoveCheck& other) - : m_Name("Copy of " + other.m_Name) - { - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Copy Constructor", "TestCopy(TestCopy&)"); - } - - CopyMoveCheck(const CopyMoveCheck& other) - : m_Name("Copy of " + other.m_Name) - { - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Const Copy Constructor", "TestCopy(const TestCopy&)"); - } - - CopyMoveCheck(CopyMoveCheck&& other) noexcept - : m_Name("Move of " + other.m_Name) - { - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Move Constructor", "TestCopy(TestCopy&&)"); - } - - CopyMoveCheck(const CopyMoveCheck&& other) noexcept - : m_Name("Move of " + other.m_Name) - { - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Const Move Constructor", "TestCopy(const TestCopy&&)"); - } - - CopyMoveCheck& operator=(CopyMoveCheck& other) - { - m_Name = "Copy Of " + other.m_Name; - - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Copy Assignment", "TestCopy& operator=(TestCopy&)"); - return *this; - } - - CopyMoveCheck& operator=(const CopyMoveCheck& other) - { - m_Name = "Copy Of " + other.m_Name; - - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Const Copy Assignment", "TestCopy& operator=(const TestCopy&)"); - return *this; - } - - CopyMoveCheck& operator=(CopyMoveCheck&& other) noexcept - { - m_Name = "Move Of " + other.m_Name; - - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Move Assignment", "TestCopy& operator=(TestCopy&&)"); - return *this; - } - - CopyMoveCheck& operator=(const CopyMoveCheck&& other) noexcept - { - m_Name = "Move Of " + other.m_Name; - - Logger.Info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", m_Name, "Const Move Assignment", "TestCopy& operator=(const TestCopy&&)"); - return *this; - } - - private: - std::string m_Name; - }; -} diff --git a/src/StreamFormat/Tester/TestSuite/AllTestSuite.h b/src/StreamFormat/Tester/TestSuite/AllTestSuite.h deleted file mode 100644 index a2fa9582..00000000 --- a/src/StreamFormat/Tester/TestSuite/AllTestSuite.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "BasicTest.h" -#include "TestSuite.h" diff --git a/src/StreamFormat/Tester/TestSuite/BasicTest.h b/src/StreamFormat/Tester/TestSuite/BasicTest.h deleted file mode 100644 index d3bfeef6..00000000 --- a/src/StreamFormat/Tester/TestSuite/BasicTest.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -#include "TestSuite.h" - -namespace StreamFormat::Tester::Detail -{ - struct TestFunction : public Test - { - public: - using FuncType = std::function; - - public: - TestFunction(std::string&& name, TestSuite& link, FuncType func, const FMT::Detail::FileLocation& location) - : Test(std::move(name), link, location) - , Func(func) - { - Link.Tests.insert({Name, this}); - } - - ~TestFunction() override = default; - - protected: - TestStatus RunImpl() override - { - Func(*this); - return TestStatus::Ok; - } - - public: - void TestAssert(bool assert, const std::string_view assertView, int line); - template - void TestEq(T result, std::convertible_to auto expected, std::string_view testView, int line); - template - void TestNotEq(T result, std::convertible_to auto notExpected, std::string_view testView, int line); - - public: - FuncType Func; - }; - - template - void TestFunction::TestEq(T result, std::convertible_to auto expected, std::string_view testView, [[maybe_unused]] int line) - { - T expected_as_T = static_cast(expected); - if (result != expected_as_T) - { - Link.TestLogger.Error("{C:red}{} return {} instead of {}", testView, result, expected, FORMAT_SV("test_name", Name)); - throw TestFailure{}; - } - - Link.TestLogger.Trace("{C:green}{} return {}", testView, result, FORMAT_SV("test_name", Name)); - } - - template - void TestFunction::TestNotEq(T result, std::convertible_to auto notExpected, std::string_view testView, [[maybe_unused]] int line) - { - if (result == static_cast(notExpected)) - { - Link.TestLogger.Error("{C:red}{} return {} but this result was prohibited", testView, result, FORMAT_SV("test_name", Name)); - throw TestFailure{}; - } - - Link.TestLogger.Trace("{C:green}{} return {}", testView, result, FORMAT_SV("test_name", Name)); - } - - inline void TestFunction::TestAssert(bool assert, std::string_view assertView, [[maybe_unused]] int line) - { - if (assert == false) - { - Link.TestLogger.Error("{C:red}ASSERT FAILED : {}", assertView, FORMAT_SV("test_name", Name)); - throw TestFailure{}; - } - - Link.TestLogger.Trace("{C:green}ASSERT SUCCED : {}", assertView, FORMAT_SV("test_name", Name)); - } -} - -#define STREAMFORMAT_TESTINTERNAL_FUNC_DECLARE_EXEC(TestSuiteName, TestName) \ - void STREAMFORMAT_TESTINTERNAL_FUNC_EXEC_NAME(TestSuiteName, TestName)(StreamFormat::Tester::Detail::TestFunction & link); -#define STREAMFORMAT_TESTINTERNAL_FUNC_CREATE(TestSuiteName, TestName, ...) \ - volatile StreamFormat::Tester::Detail::TestFunction STREAMFORMAT_TESTINTERNAL_FUNC_NAME(TestSuiteName, TestName)( \ - #TestName, STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName), STREAMFORMAT_TESTINTERNAL_FUNC_EXEC_NAME(TestSuiteName, TestName), STREAMFORMAT_FMT_FILE_LOCATION()) - -#define PCT_TEST_FUNC(TestSuiteName, TestName) \ - STREAMFORMAT_TESTINTERNAL_FUNC_DECLARE_EXEC(TestSuiteName, TestName) \ - STREAMFORMAT_TESTINTERNAL_FUNC_CREATE(TestSuiteName, TestName); \ - void STREAMFORMAT_TESTINTERNAL_FUNC_EXEC_NAME(TestSuiteName, TestName)(StreamFormat::Tester::Detail::TestFunction & link) - -#define PCT_ASSERT(Test) link.TestAssert(Test, #Test, __LINE__) -#define PCT_EQ(Test, Expected) link.TestEq(Test, Expected, #Test, __LINE__) -#define PCT_NEQ(Test, NotExpected) link.TestNotEq(Test, NotExpected, #Test, __LINE__) diff --git a/src/StreamFormat/Tester/TestSuite/TestSuite.cpp b/src/StreamFormat/Tester/TestSuite/TestSuite.cpp deleted file mode 100644 index c4188cb9..00000000 --- a/src/StreamFormat/Tester/TestSuite/TestSuite.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include "TestSuite.h" - -#include "StreamFormat/ProfilerManager.h" - -namespace StreamFormat::Tester -{ - bool TestSuitesManager::ExecAllTestSuites() - { - Detail::TestStatusBank status; - - for (auto& [name, testSuite] : TestSuites) - status.Add(testSuite->ExecAllTests()); - - FLog::BasicLogger logger("TestSuite"); - if (status.IsAllOk()) - logger.Info("{C:white}RESULT => {C:+black}{}", status); - else - logger.Error("{C:white}RESULT => {C:+black}{}", status); - - return status.ErrorStatus(); - } -} - -namespace StreamFormat::Tester::Detail -{ - TestStatusBank TestSuite::ExecAllTests() - { - if (Parent == nullptr) Profiler = new ProfilerManager::Profiler("TestSuite_" + Name); - InitLogger(); - - ProfilerManager::Profiler& profiler = GetProfiler(); - Logger.Info("{C:+black}{}", "BEGIN"); - ProfilerManager::DurationEvent testSuiteDuration(GetFullName(), "Profile"); - testSuiteDuration.Start(); - bool firstTestSuite = true; - TestStatusBank testSuiteStatus; - ProfilerManager::DurationEvent testsDuration("Tests", "Profile"); - testsDuration.Start(); - for (auto& [name, test] : Tests) - { - firstTestSuite = false; - ProfilerManager::DurationEvent currentTestDuration(test->Name, "Profile"); - TestStatus testStatus = TestStatus::Fail; - currentTestDuration.Start(); - if (TestSuitesManager::PerformanceTest.Enable == false) - testStatus = test->Run(); - else - { - for (std::uint32_t i = 0; i < TestSuitesManager::PerformanceTest.NbSamples; ++i) - { - testStatus = test->Run(); - if (testStatus != TestStatus::Ok) break; - } - } - currentTestDuration.Stop(); - if (testStatus != TestStatus::Ok) - {} - testSuiteStatus.AddTestStatus(testStatus); - Logger.Debug("{} -> {}", testStatus, name); - profiler.AddEvent(currentTestDuration); - } - testsDuration.Stop(); - - ProfilerManager::DurationEvent groupsDuration("Groups", "Profile"); - groupsDuration.Start(); - for (auto& [name, testSuite] : TestSuitesLinked) - { - if (firstTestSuite) - firstTestSuite = false; - else - std::cout << std::endl; - testSuiteStatus.Add(testSuite->ExecAllTests()); - } - groupsDuration.Stop(); - testSuiteDuration.Stop(); - profiler.AddEvent(testsDuration); - profiler.AddEvent(groupsDuration); - profiler.AddEvent(testSuiteDuration); - - if (testSuiteStatus.IsAllOk()) - Logger.Info("{C:+black}{}", testSuiteStatus); - else - Logger.Error("{C:+black}{}", testSuiteStatus); - - if (Parent == nullptr) - { - ProfilerManager::ProfilerFactory::ToJson(*Profiler); - delete Profiler; - } - - return testSuiteStatus; - } - - void TestSuite::InitLogger() - { - if (TestSuitesManager::Verbose == false) - { - Logger.SetSeverity(FLog::LogSeverity::Debug); - TestLogger.SetSeverity(FLog::LogSeverity::Debug); - } - else - { - Logger.SetSeverity(FLog::LogSeverity::Trace); - TestLogger.SetSeverity(FLog::LogSeverity::Trace); - } - - std::string timePattern = ""; - if (TestSuitesManager::PrintTime) timePattern = "[{T:pattern='%h:%m:%s:%ms'}] "; - - if (Parent == nullptr) - { - Logger.SetName(Name); - Logger.SetRealPattern("{C:+black}" + timePattern + "{name} >> {color}{data}"); - TestLogger.SetName(Name + ".{test_name}"); - TestLogger.SetRealPattern("{C:+black}" + timePattern + "{name} >> {color}{data}"); - } - else - { - std::string correctedName = GetCorrectedSizeName(); - Logger.SetName(correctedName); - Logger.SetRealPatternStrmv("{C:+black}" + timePattern + "{name} >> {color}{data}"); - TestLogger.SetName(correctedName + ".{test_name}"); - TestLogger.SetRealPatternStrmv("{C:+black}" + timePattern + "{name} >> {color}{data}"); - } - } - - std::string TestSuite::GetFullName() - { - if (Parent == nullptr) return Name; - return Parent->GetFullName() + "::" + Name; - } - - std::string TestSuite::GetCorrectedSizeName() - { - if (Parent == nullptr) return Name; - std::size_t biggestName = 0; - for (auto& [name, testSuite] : Parent->TestSuitesLinked) - { - std::size_t tmp = testSuite->Name.size(); - if (tmp > biggestName) biggestName = tmp; - } - std::string res = GetFullName(); - biggestName -= Name.size(); - res.reserve(res.size() + biggestName); - for (std::uint32_t i = 0; i < biggestName; ++i) - res.push_back(' '); - return res; - } - - ProfilerManager::Profiler& TestSuite::GetProfiler() - { - if (Parent == nullptr) return *Profiler; - return Parent->GetProfiler(); - } -} diff --git a/src/StreamFormat/Tester/TestSuite/TestSuite.h b/src/StreamFormat/Tester/TestSuite/TestSuite.h deleted file mode 100644 index 959ea00a..00000000 --- a/src/StreamFormat/Tester/TestSuite/TestSuite.h +++ /dev/null @@ -1,279 +0,0 @@ -#pragma once - -#include "StreamFormat/FLog.h" -#include "StreamFormat/FMT.h" -#include "StreamFormat/ProfilerManager.h" - -#include "StreamFormat/FMT/Serializers/CompilationData.h" - -#include -#include -#include - -namespace StreamFormat::Tester -{ - class TestFailure - { - }; - - enum class TestStatus : int - { - Ok, - Fail, - Crash - }; -} - -namespace StreamFormat::Tester::Detail -{ - class TestSuite; - class Test - { - public: - Test(std::string&& name, TestSuite& link, const FMT::Detail::FileLocation& location) - : Name(std::move(name)) - , Link(link) - , Location(location) - , LastStatus(TestStatus::Ok) - {} - - virtual ~Test() = default; - - protected: - virtual TestStatus RunImpl() = 0; - - public: - TestStatus Run() - { - try - { - return LastStatus = RunImpl(); - } - catch (const TestFailure&) - { - return LastStatus = TestStatus::Fail; - } - catch (...) - { - return LastStatus = TestStatus::Crash; - } - } - - public: - std::string Name; - TestSuite& Link; - FMT::Detail::FileLocation Location; - TestStatus LastStatus; - }; - - struct TestStatusBank - { - void Reset() - { - TestsDone = 0; - TestsOk = 0; - TestsFail = 0; - TestsCrash = 0; - } - - void AddTestStatus(TestStatus status) - { - TestsDone++; - switch (status) - { - case TestStatus::Ok: - TestsOk++; - break; - case TestStatus::Fail: - TestsFail++; - break; - case TestStatus::Crash: - TestsCrash++; - break; - } - } - - void Add(TestStatusBank status) - { - TestsDone += status.TestsDone; - TestsOk += status.TestsOk; - TestsFail += status.TestsFail; - TestsCrash += status.TestsCrash; - } - - bool IsAllOk() { return TestsDone == TestsOk && TestsCrash == 0 && TestsFail == 0; } - - std::uint32_t ErrorStatus() { return TestsDone - TestsOk; } - - std::uint32_t TestsDone = 0; - std::uint32_t TestsOk = 0; - std::uint32_t TestsFail = 0; - std::uint32_t TestsCrash = 0; - }; - - class TestSuite; -} -namespace StreamFormat::Tester -{ - struct PerformanceTestData - { - bool Enable = false; - std::uint32_t NbSamples = 10; - }; - - struct ConcurenceSpecificationData - { - bool Enable = false; - }; - - class TestSuitesManager - { - public: - static bool ExecAllTestSuites(); - static inline std::unordered_map TestSuites; - - public: - static inline bool Verbose = false; - static inline bool PrintTime = false; - static inline PerformanceTestData PerformanceTest = PerformanceTestData{}; - static inline ConcurenceSpecificationData ConcurenceSpecification = ConcurenceSpecificationData{}; - }; -} -namespace StreamFormat::Tester::Detail -{ - struct TestSuiteData - { - bool Redirect_stdout = false; - bool Redirect_stdin = false; - bool Redirect_stderr = false; - }; - - class TestSuite - { - public: - TestSuite(std::string&& name, TestSuiteData extra = TestSuiteData{}, TestSuite* parent = nullptr) - : Name(std::move(name)) - , Tests() - , Extra(extra) - , Logger() - , TestLogger() - , Profiler(nullptr) - , Parent(parent) - { - if (parent == nullptr) - TestSuitesManager::TestSuites.insert({Name, this}); - else - Parent->TestSuitesLinked.insert({Name, this}); - } - - std::string Name; - std::unordered_map Tests; - std::unordered_map TestSuitesLinked; - - TestSuiteData Extra; - FLog::BasicLogger Logger; - FLog::BasicLogger TestLogger; - ProfilerManager::Profiler* Profiler; - - TestSuite* Parent; - - public: - void InitLogger(); - - private: - std::string GetFullName(); - std::string GetCorrectedSizeName(); - ProfilerManager::Profiler& GetProfiler(); - - public: - TestStatusBank ExecAllTests(); - }; -} - -namespace StreamFormat::FMT -{ - template - struct FormatterType - { - static void Format(const StreamFormat::Tester::Detail::TestSuite& t, FormatterExecutor& executor) { executor.BufferOut.FastWriteString(t.Name); } - }; - - template - struct FormatterType - { - static void Format(const StreamFormat::Tester::Detail::Test& t, FormatterExecutor& executor) - { - Detail::BufferWriteManip(executor.BufferOut).FastWriteString(t.Link.Name); - Detail::BufferWriteManip(executor.BufferOut).FastWriteStringLitteral("::"); - Detail::BufferWriteManip(executor.BufferOut).FastWriteString(t.Name); - } - }; - - template - struct FormatterType - { - static void Format(const StreamFormat::Tester::TestStatus& status, FormatterExecutor& executor) - { - switch (status) - { - case StreamFormat::Tester::TestStatus::Ok: - executor.Run("[ {C:green}OK{C} ]"); - break; - case StreamFormat::Tester::TestStatus::Fail: - executor.Run("[ {C:red}FAIL{C} ]"); - break; - case StreamFormat::Tester::TestStatus::Crash: - executor.Run("[{C:magenta}Crash{C} ]"); - break; - } - } - }; - - template - struct FormatterType - { - static void Format(const StreamFormat::Tester::Detail::TestStatusBank& statusBank, FormatterExecutor& executor) - { - Detail::BufferWriteManip(executor.BufferOut).FastWriteStringLitteral("TestsDone "); - executor.Run("{:C:white}", statusBank.TestsDone); - - Detail::BufferWriteManip(executor.BufferOut).FastWriteStringLitteral(" | TestsOK "); - if (statusBank.TestsOk == statusBank.TestsDone) - executor.Run("{:C:green}", statusBank.TestsOk); - else - executor.Run("{:C:yellow}", statusBank.TestsOk); - - Detail::BufferWriteManip(executor.BufferOut).FastWriteStringLitteral(" | TestsFAIL "); - if (statusBank.TestsFail == 0) - executor.Run("{:C:green}", statusBank.TestsFail); - else - executor.Run("{:C:red}", statusBank.TestsFail); - - Detail::BufferWriteManip(executor.BufferOut).FastWriteStringLitteral(" | TestCrash "); - if (statusBank.TestsCrash == 0) - executor.Run("{:C:green}", statusBank.TestsCrash); - else - executor.Run("{:C:magenta}", statusBank.TestsCrash); - } - }; -} - -//-------------------- Base --------------------// -#define STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName) TestSuite_##TestSuiteName -#define STREAMFORMAT_TESTINTERNAL_FUNC_NAME(TestSuiteName, TestName) TestSuite_##TestSuiteName##TestName -#define STREAMFORMAT_TESTINTERNAL_FUNC_EXEC_NAME(TestSuiteName, TestName) TestSuite_##TestSuiteName##TestName##_ExecMethod -#define STREAMFORMAT_TESTINTERNAL_SUITE_EXTRA(...) \ - StreamFormat::Tester::Detail::TestSuiteData \ - { \ - __VA_ARGS__ \ - } - -//-------------------- TestSuite --------------------// -#define PCT_TEST_SUITE(TestSuiteName, ...) \ - StreamFormat::Tester::Detail::TestSuite STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName)(#TestSuiteName, STREAMFORMAT_TESTINTERNAL_SUITE_EXTRA(__VA_ARGS__)) -#define PCT_TEST_GROUP(TestSuiteName, GroupName, ...) \ - StreamFormat::Tester::Detail::TestSuite STREAMFORMAT_TESTINTERNAL_SUITE_NAME(GroupName)(#GroupName, STREAMFORMAT_TESTINTERNAL_SUITE_EXTRA(__VA_ARGS__), \ - &STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName)) - -#define PCT_TEST_SUITE_DECLARATION(TestSuiteName, ...) StreamFormat::Tester::Detail::TestSuite STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName) -#define PCT_TEST_GROUP_DECLARATION(TestSuiteName, GroupName, ...) StreamFormat::Tester::Detail::TestSuite STREAMFORMAT_TESTINTERNAL_SUITE_NAME(GroupName) diff --git a/src/StreamFormat/Core/Core.h b/src/stream/core/prelude.hxx similarity index 58% rename from src/StreamFormat/Core/Core.h rename to src/stream/core/prelude.hxx index 3aa614c2..c8822796 100644 --- a/src/StreamFormat/Core/Core.h +++ b/src/stream/core/prelude.hxx @@ -1,7 +1,5 @@ #pragma once -#include "CompilerInfo.h" - #include #define STREAMFORMAT_DEBUG @@ -21,20 +19,16 @@ #define STREAMFORMAT_DEBUGBREAK() std::raise(SIGINT) #endif #include -#define STREAMFORMAT_ASSERT(x) \ - if (!(x)) \ - { \ +#define STREAMFORMAT_ASSERT(x) \ + if (!(x)) { \ std::cerr << "ASSERT FAILED! : " << #x << std::endl; \ - STREAMFORMAT_DEBUGBREAK(); \ + STREAMFORMAT_DEBUGBREAK(); \ } #else #define STREAMFORMAT_ASSERT(x) #define STREAMFORMAT_DEBUGBREAK() #endif -// NOT USED YET -#define STREAMFORMAT_NODISCARD [[nodiscard]] -#define STREAMFORMAT_INLINE inline - -#define UNKOWN_TYPE_MESSAGE -#define UNKOWN_TYPE_DEBUG +#include +#include +#include diff --git a/src/stream/default_logger.hxx b/src/stream/default_logger.hxx new file mode 100644 index 00000000..130ce007 --- /dev/null +++ b/src/stream/default_logger.hxx @@ -0,0 +1,38 @@ +#pragma once + +#include "flog/frontends/xlogger.hxx" + +#ifndef STREAMFORMAT_BASE_LOGGER_NAME +#undef STREAMFORMAT_BASE_LOGGER_NAME +#define STREAMFORMAT_BASE_LOGGER_NAME "APP" +#endif + +namespace stream::flog { + class DefaultLogger { + public: + [[maybe_unused]] static BasicLogger& core() { + static BasicLogger instance(STREAMFORMAT_BASE_LOGGER_NAME "-core", LogSeverity::Trace); + return instance; + } + [[maybe_unused]] static BasicLogger& client() { + static BasicLogger instance(STREAMFORMAT_BASE_LOGGER_NAME "-client", LogSeverity::Trace); + return instance; + } + }; +} // namespace stream::flog + +#ifdef STREAMFORMAT_LOGGER_ENABLE +#define CORE_TRACE(...) stream::flog::BasicLogger::core().trace(__VA_ARGS__) +#define CORE_DEBUG(...) stream::flog::BasicLogger::core().debug(__VA_ARGS__) +#define CORE_INFO(...) stream::flog::BasicLogger::core().info(__VA_ARGS__) +#define CORE_WARN(...) stream::flog::BasicLogger::core().warn(__VA_ARGS__) +#define CORE_ERROR(...) stream::flog::BasicLogger::core().error(__VA_ARGS__) +#define CORE_FATAL(...) stream::flog::BasicLogger::core().fatal(__VA_ARGS__) +#else +#define CORE_TRACE(...) +#define CORE_DEBUG(...) +#define CORE_INFO(...) +#define CORE_WARN(...) +#define CORE_ERROR(...) +#define CORE_FATAL(...) +#endif diff --git a/src/stream/flog.hxx b/src/stream/flog.hxx new file mode 100644 index 00000000..f6892b85 --- /dev/null +++ b/src/stream/flog.hxx @@ -0,0 +1,11 @@ +#pragma once + +#include "flog/backends/basic_logger.hxx" +#include "flog/backends/logger_multi_sink_fast.hxx" +#include "flog/backends/logger_multi_sink_safe.hxx" + +#include "flog/sinks/file_sink.hxx" + +#include "flog/frontends/xlogger.hxx" + +#include "flog/logger_factory.hxx" diff --git a/src/stream/flog/backends/basic_logger.hxx b/src/stream/flog/backends/basic_logger.hxx new file mode 100644 index 00000000..7794bd35 --- /dev/null +++ b/src/stream/flog/backends/basic_logger.hxx @@ -0,0 +1,103 @@ +#pragma once + +#include "stream/flog/detail/detail.hxx" +#include "stream/fmt/serializers/format_chrono.hxx" + +#include +#include + +namespace stream::flog::detail { + template + class BasicLoggerImpl { + public: + using SeverityValueType = typename Severity::Value; + + public: + BasicLoggerImpl() : name_("logger_"), severity_(Severity::Value::DefaultSeverity), stream_(std::cout), start_time_(std::chrono::high_resolution_clock::now()) { + reset_pattern(); + } + + explicit BasicLoggerImpl(const std::string_view& name, typename Severity::Value severity = Severity::Value::DefaultSeverity, std::ostream& stream = std::cout) + : name_(name), + severity_(severity), + stream_(stream), + pre_format_stream_io_manager_(64), + full_format_stream_io_manager_(64), + start_time_(std::chrono::high_resolution_clock::now()) { + reset_pattern(); + } + explicit BasicLoggerImpl(const std::string_view& name, const std::string_view& format, typename Severity::Value severity = Severity::Value::DefaultSeverity, + std::ostream& stream = std::cout) + : name_(name), + severity_(severity), + stream_(stream), + pre_format_stream_io_manager_(64), + full_format_stream_io_manager_(64), + start_time_(std::chrono::high_resolution_clock::now()) { + set_pattern(format); + } + + virtual ~BasicLoggerImpl() = default; + + public: + void set_severity(const SeverityValueType& severity) { + severity_ = severity; + } + void set_name(std::string name) { + name_ = std::move(name); + } + void set_real_pattern(std::string pattern) { + pattern_ = std::move(pattern); + } + void set_pattern(std::string_view pattern) { + pattern_ = "{color}"; + pattern_ += pattern; + } + void reset_pattern() { + set_pattern("[{logtime:pattern='default'}] {name} >> {data}"); + } + + private: + std::string name_; + SeverityValueType severity_; + std::ostream& stream_; + std::string pattern_; + fmt::buf::DynamicStreamIOManager pre_format_stream_io_manager_; + fmt::buf::DynamicStreamIOManager full_format_stream_io_manager_; + + std::chrono::time_point start_time_; + + public: + void NewLine() { + stream_.write("\n", 1); + } + + template + requires fmt::buf::convertible_to_buffer_info_view + void log(const SeverityValueType& severity, Format&& format, Args&&... args) { + if (severity < severity_) return; + + std::chrono::nanoseconds log_time = std::chrono::high_resolution_clock::now() - start_time_; + + fmt::detail::format_in_manager(pre_format_stream_io_manager_, false, fmt::buf::StreamView(pattern_), FORMAT_SV("logtime", log_time), FORMAT_SV("name", name_), + FORMAT_SV("data", flog::AddIndentInFormat(format))); + + fmt::detail::format_in_manager(full_format_stream_io_manager_, true, pre_format_stream_io_manager_.get_last_generated_buffer_info_view(), std::forward(args)..., + FORMAT_SV("color", severity)); + stream_.write(full_format_stream_io_manager_.get_buffer(), static_cast(full_format_stream_io_manager_.get_last_generated_data_size())); + stream_.flush(); + } + + template + void log(const SeverityValueType& severity, T&& t) { + if (severity < severity_) return; + + std::chrono::nanoseconds log_time = std::chrono::high_resolution_clock::now() - start_time_; + + fmt::detail::format_in_manager(full_format_stream_io_manager_, true, fmt::buf::StreamView(pattern_), FORMAT_SV("data", t), FORMAT_SV("color", severity), + FORMAT_SV("logtime", log_time), FORMAT_SV("name", name_)); + stream_.write(full_format_stream_io_manager_.get_buffer(), static_cast(full_format_stream_io_manager_.get_last_generated_data_size())); + stream_.flush(); + } + }; +} // namespace stream::flog::detail diff --git a/src/stream/flog/backends/logger_multi_sink.hxx b/src/stream/flog/backends/logger_multi_sink.hxx new file mode 100644 index 00000000..318f5845 --- /dev/null +++ b/src/stream/flog/backends/logger_multi_sink.hxx @@ -0,0 +1,50 @@ +#pragma once + +#include "stream/flog/detail/detail.hxx" +#include "stream/flog/sinks/logger_sink.hxx" + +namespace stream::flog::detail { + template + class BasicLoggerMultiSinkImpl { + public: + using SinkType = BasicLoggerSink; + using SeverityValueType = typename Severity::Value; + + public: + BasicLoggerMultiSinkImpl() : name_("logger_:{sink}"), start_time_(std::chrono::high_resolution_clock::now()) {} + + BasicLoggerMultiSinkImpl(std::basic_string&& name) + : name_(std::forward>(name)), start_time_(std::chrono::high_resolution_clock::now()) {} + + virtual ~BasicLoggerMultiSinkImpl() = default; + + public: + void set_name(std::basic_string&& name) { + name_ = std::forward>(name); + } + + std::basic_string& get_name() { + return name_; + } + std::vector>& get_sinks() { + return sinks_; + } + + protected: + std::basic_string name_; + std::vector> sinks_; + + std::chrono::time_point start_time_; + + public: + void add_sink(std::shared_ptr sink) { + sinks_.pushback(sink); + } + + template + void EmplaceSink(Args&&... args) { + std::shared_ptr sink = std::make_shared(std::forward(args)...); + add_sink(sink); + } + }; +} // namespace stream::flog::detail diff --git a/src/stream/flog/backends/logger_multi_sink_fast.hxx b/src/stream/flog/backends/logger_multi_sink_fast.hxx new file mode 100644 index 00000000..f8f752e4 --- /dev/null +++ b/src/stream/flog/backends/logger_multi_sink_fast.hxx @@ -0,0 +1,66 @@ +#pragma once + +#include "logger_multi_sink.hxx" + +namespace stream::flog::detail { + template + class BasicLoggerMultiSinkFastImpl : public BasicLoggerMultiSinkImpl { + public: + using Base = BasicLoggerMultiSinkImpl; + using Base::add_sink; + using Base::get_name; + using Base::get_sinks; + using Base::name_; + using Base::set_name; + using Base::sinks_; + + using Base::start_time_; + + using typename Base::SeverityValueType; + + public: + BasicLoggerMultiSinkFastImpl() : Base() {} + + BasicLoggerMultiSinkFastImpl(std::basic_string&& name) : Base(std::forward>(name)) {} + + ~BasicLoggerMultiSinkFastImpl() override = default; + + public: + void await(const SeverityValueType& severity) { + for (auto& sink : sinks_) + if (sink->need_to_log(severity)) sink->wait_until_finished_to_write(); + } + + public: + template + requires fmt::buf::convertible_to_buffer_info_view + void log(const SeverityValueType& severity, const Format& format, Args&&... args) { + std::chrono::nanoseconds log_time = std::chrono::high_resolution_clock::now() - start_time_; + + fmt::buf::DynamicStreamIOManager manager(256); + + auto format_buffer = fmt::detail::format_in_manager(manager, false, format, std::forward(args)...); + for (auto& sink : sinks_) + if (sink->need_to_log(severity)) { + sink->format_and_write_to_sink(sink->get_pattern(severity), log_time, name_, static_cast>(*format_buffer)); + } + + await(severity); + } + + template + void log(const SeverityValueType& severity, T&& t) { + std::chrono::nanoseconds log_time = std::chrono::high_resolution_clock::now() - start_time_; + + fmt::buf::DynamicStreamIOManager manager(256); + + auto format_buffer = fmt::detail::format_in_manager(manager, false, std::forward(t)); + for (auto& sink : sinks_) + if (sink->need_to_log(severity)) { + sink->format_and_write_to_sink(sink->get_pattern(severity), log_time, name_, static_cast>(*format_buffer)); + } + + await(severity); + } + }; +} // namespace stream::flog::detail diff --git a/src/stream/flog/backends/logger_multi_sink_safe.hxx b/src/stream/flog/backends/logger_multi_sink_safe.hxx new file mode 100644 index 00000000..a3e70190 --- /dev/null +++ b/src/stream/flog/backends/logger_multi_sink_safe.hxx @@ -0,0 +1,74 @@ +#pragma once + +#include "logger_multi_sink.hxx" + +namespace stream::flog::detail { + template + class BasicLoggerMultiSinkSafeImpl : public BasicLoggerMultiSinkImpl { + public: + using Base = BasicLoggerMultiSinkImpl; + using Base::add_sink; + using Base::get_name; + using Base::get_sinks; + using Base::name_; + using Base::set_name; + using Base::sinks_; + + using Base::start_time_; + + using typename Base::SeverityValueType; + + public: + BasicLoggerMultiSinkSafeImpl() : Base() {} + + BasicLoggerMultiSinkSafeImpl(std::basic_string&& name) : Base(std::forward>(name)) {} + + ~BasicLoggerMultiSinkSafeImpl() override = default; + + public: + void await(const SeverityValueType& severity) { + for (auto& sink : sinks_) + if (sink->need_to_log(severity)) sink->wait_until_finished_to_write(); + } + + public: + template + requires fmt::buf::convertible_to_buffer_info_view + void log(const SeverityValueType& severity, const Format& format, Args&&... args) { + std::chrono::nanoseconds log_time = std::chrono::high_resolution_clock::now() - start_time_; + + // FIXME maybe add : name ; indent ??? + for (auto& sink : sinks_) { + if (sink->need_to_log(severity)) { + fmt::buf::DynamicStreamIOManager manager_pattern(256); + fmt::buf::DynamicStreamIOManager manager_format(256); + + auto format_pattern_str = + fmt::detail::format_in_manager(manager_pattern, false, std::string_view(sink->get_pattern(severity)), FORMAT_SV("logtime", log_time), + FORMAT_SV("name", FutureConcatNameAndSinkName(name_)), FORMAT_SV("data", flog::AddIndentInFormat(format))); + auto format_format_str = fmt::detail::format_in_manager(manager_format, false, static_cast(*format_pattern_str), std::forward(args)..., + FORMAT_SV("sink", sink->get_name()), FORMAT_SV("color", severity)); + sink->WriteToSink(static_cast>(*format_format_str)); + } + } + + await(severity); + } + + template + void log(const SeverityValueType& severity, T&& t) { + std::chrono::nanoseconds log_time = std::chrono::high_resolution_clock::now() - start_time_; + + for (auto& sink : sinks_) { + if (sink->need_to_log(severity)) { + fmt::buf::DynamicStreamIOManager manager(256); + auto format_buffer = fmt::detail::format_in_manager(manager, false, std::string_view(sink->get_pattern(severity)), FORMAT_SV("logtime", log_time), + FORMAT_SV("name", ConcatNameAndSinkName(name_, sink->get_name())), FORMAT_SV("data", t)); + sink->WriteToSink(static_cast>(*format_buffer)); + } + } + + await(severity); + } + }; +} // namespace stream::flog::detail diff --git a/src/stream/flog/detail/detail.hxx b/src/stream/flog/detail/detail.hxx new file mode 100644 index 00000000..432b6822 --- /dev/null +++ b/src/stream/flog/detail/detail.hxx @@ -0,0 +1,51 @@ +#pragma once + +#include "stream/fmt.hxx" + +#include "stream/fmt/buf/manip.hxx" +#include "stream/fmt/buf/write_manip.hxx" + +namespace stream::flog { + template + struct AddIndentInFormat { + AddIndentInFormat(const FormatStr& format) : format(format) {} + const FormatStr& format; + }; + + template + struct ConcatNameAndSinkName { + ConcatNameAndSinkName(const std::basic_string& logger_name, const std::basic_string& sinkName) : LoggerName(logger_name), SinkName(sinkName) {} + const std::basic_string& LoggerName; + const std::basic_string& SinkName; + }; + + template + struct FutureConcatNameAndSinkName { + FutureConcatNameAndSinkName(const std::basic_string& logger_name) : LoggerName(logger_name) {} + const std::basic_string& LoggerName; + }; +} // namespace stream::flog + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const stream::flog::AddIndentInFormat& format, FormatterExecutor& executor) { + buf::WriteManip(executor.ostream).fast_write_literal("{K:indent}"); + return executor.write_type(format.format); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static void format(const stream::flog::ConcatNameAndSinkName& names, FormatterExecutor& executor) { + return executor.run(names.LoggerName, FORMAT_SV("sink", names.SinkName)); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static void format(const stream::flog::FutureConcatNameAndSinkName& names, FormatterExecutor& executor) { + return executor.run(names.LoggerName, "sink"); + } + }; +} // namespace stream::fmt diff --git a/src/stream/flog/frontends/xlogger.cxx b/src/stream/flog/frontends/xlogger.cxx new file mode 100644 index 00000000..ef2737dd --- /dev/null +++ b/src/stream/flog/frontends/xlogger.cxx @@ -0,0 +1,12 @@ +#include "xlogger.hxx" + +namespace stream::flog { + template class detail::XLogger>; + template class detail::XLogger>; + template class detail::XLogger>; +} // namespace stream::flog + +namespace stream::flog::Sinks { + template class BasicConsoleSink; + template class BasicFileSink; +} // namespace stream::flog::Sinks diff --git a/src/stream/flog/frontends/xlogger.hxx b/src/stream/flog/frontends/xlogger.hxx new file mode 100644 index 00000000..614b68b8 --- /dev/null +++ b/src/stream/flog/frontends/xlogger.hxx @@ -0,0 +1,195 @@ +#pragma once + +#include "stream/flog/detail/detail.hxx" +#include "stream/flog/backends/basic_logger.hxx" +#include "stream/flog/backends/logger_multi_sink_fast.hxx" +#include "stream/flog/backends/logger_multi_sink_safe.hxx" +#include "stream/flog/sinks/file_sink.hxx" + +namespace stream::flog { + struct LogSeverity { + public: + enum class Value : int { + Trace, + Debug, + Info, + Warn, + Error, + Fatal, + DefaultSeverity = Trace + }; + + public: + static constexpr Value Trace{Value::Trace}; + static constexpr Value Debug{Value::Debug}; + static constexpr Value Info{Value::Info}; + static constexpr Value Warn{Value::Warn}; + static constexpr Value Error{Value::Error}; + static constexpr Value Fatal{Value::Fatal}; + static constexpr Value DefaultSeverity = Trace; + + public: + class PatternOverride { + public: + std::basic_string trace_pattern = ""; + std::basic_string debug_pattern = ""; + std::basic_string info_pattern = ""; + std::basic_string warn_pattern = ""; + std::basic_string error_pattern = ""; + std::basic_string fatal_pattern = ""; + + std::basic_string_view get_pattern(const Value& severity) const { + switch (severity) { + case Value::Trace: + if (trace_pattern.empty() == false) return trace_pattern; + break; + case Value::Debug: + if (debug_pattern.empty() == false) return debug_pattern; + break; + case Value::Info: + if (info_pattern.empty() == false) return info_pattern; + break; + case Value::Warn: + if (warn_pattern.empty() == false) return warn_pattern; + break; + case Value::Error: + if (error_pattern.empty() == false) return error_pattern; + break; + case Value::Fatal: + if (fatal_pattern.empty() == false) return fatal_pattern; + break; + } + return std::basic_string_view{nullptr, 0}; + } + }; + }; +} // namespace stream::flog + +namespace stream::flog::detail { + template + class XLogger : public Master { + public: + template + XLogger(Args&&... args) : Master(std::forward(args)...) {} + + ~XLogger() override = default; + + public: + template + requires fmt::buf::convertible_to_buffer_info_view + void log(Severity status, Format&& format, Args&&... args) { + return Master::template log(status, format, std::forward(args)...); + } + + template + void log(Severity status, T&& t) { + return Master::template log(status, std::forward(t)); + } + + public: + /////---------- logger Severity with array as format ----------///// + template + requires fmt::buf::convertible_to_buffer_info_view + inline void trace(Format&& format, Args&&... args) { + return log(LogSeverity::Trace, format, std::forward(args)...); + } + template + requires fmt::buf::convertible_to_buffer_info_view + inline void debug(Format&& format, Args&&... args) { + return log(LogSeverity::Debug, format, std::forward(args)...); + } + template + requires fmt::buf::convertible_to_buffer_info_view + inline void info(Format&& format, Args&&... args) { + return log(LogSeverity::Info, format, std::forward(args)...); + } + template + requires fmt::buf::convertible_to_buffer_info_view + inline void warn(Format&& format, Args&&... args) { + return log(LogSeverity::Warn, format, std::forward(args)...); + } + template + requires fmt::buf::convertible_to_buffer_info_view + inline void error(Format&& format, Args&&... args) { + return log(LogSeverity::Error, format, std::forward(args)...); + } + template + requires fmt::buf::convertible_to_buffer_info_view + inline void fatal(Format&& format, Args&&... args) { + return log(LogSeverity::Fatal, format, std::forward(args)...); + } + + /////---------- NO-FORMAT logger Severity ----------///// + template + inline void trace(T&& t) { + return log(LogSeverity::Trace, std::forward(t)); + } + template + inline void debug(T&& t) { + return log(LogSeverity::Debug, std::forward(t)); + } + template + inline void info(T&& t) { + return log(LogSeverity::Info, std::forward(t)); + } + template + inline void warn(T&& t) { + return log(LogSeverity::Warn, std::forward(t)); + } + template + inline void error(T&& t) { + return log(LogSeverity::Error, std::forward(t)); + } + template + inline void fatal(T&& t) { + return log(LogSeverity::Fatal, std::forward(t)); + } + }; +} // namespace stream::flog::detail + +namespace stream::fmt { + template + struct FormatterType { + static void format(const stream::flog::LogSeverity::Value t, FormatterExecutor& executor) { + executor.data.keep_new_style = true; + switch (t) { + case stream::flog::LogSeverity::Trace: + return FormatterType::format(detail::TextProperties::TextColor::BasicColorFG::BrightBlack, + executor); + case stream::flog::LogSeverity::Debug: + return FormatterType::format(detail::TextProperties::TextColor::BasicColorFG::Blue, + executor); + case stream::flog::LogSeverity::Info: + return FormatterType::format(detail::TextProperties::TextColor::BasicColorFG::Green, + executor); + case stream::flog::LogSeverity::Warn: + return FormatterType::format(detail::TextProperties::TextColor::BasicColorFG::Yellow, + executor); + case stream::flog::LogSeverity::Error: + return FormatterType::format(detail::TextProperties::TextColor::BasicColorFG::Red, + executor); + case stream::flog::LogSeverity::Fatal: + return FormatterType::format(detail::TextProperties::TextColor::BasicColorFG::BrightMagenta, + executor); + } + } + }; +} // namespace stream::fmt + +namespace stream::flog { + using BasicLogger = detail::XLogger>; + using LoggerMultiSinkFast = detail::XLogger>; + using LoggerMultiSinkSafe = detail::XLogger>; + + extern template class detail::XLogger>; + extern template class detail::XLogger>; + extern template class detail::XLogger>; +} // namespace stream::flog + +namespace stream::flog::Sinks { + using ConsoleSink = BasicConsoleSink; + using FileSink = BasicFileSink; + + extern template class BasicConsoleSink; + extern template class BasicFileSink; +} // namespace stream::flog::Sinks diff --git a/src/stream/flog/logger_factory.hxx b/src/stream/flog/logger_factory.hxx new file mode 100644 index 00000000..cb313618 --- /dev/null +++ b/src/stream/flog/logger_factory.hxx @@ -0,0 +1,10 @@ +#pragma once + +#include "backends/basic_logger.hxx" +#include "backends/logger_multi_sink_fast.hxx" +#include "backends/logger_multi_sink_safe.hxx" + +// TODO: +namespace stream::flog { + class LoggerFactory {}; +} // namespace stream::flog diff --git a/src/stream/flog/sinks/file_sink.hxx b/src/stream/flog/sinks/file_sink.hxx new file mode 100644 index 00000000..9b729483 --- /dev/null +++ b/src/stream/flog/sinks/file_sink.hxx @@ -0,0 +1,70 @@ +#pragma once + +#include "logger_sink.hxx" + +#include +#include +#include + +namespace stream::flog::Sinks { + template + class BasicConsoleSink : public detail::BasicLoggerSink { + public: + using Base = detail::BasicLoggerSink; + using typename Base::BufferType; + using typename Base::NameType; + using typename Base::PatternType; + + public: + BasicConsoleSink(std::basic_ostream& stream, NameType&& name) : Base(std::forward(name)), stream_(stream) {} + + BasicConsoleSink(std::basic_ostream& stream, NameType&& name, detail::AsyncSink isAsync) : Base(std::forward(name), isAsync), stream_(stream) {} + + ~BasicConsoleSink() override = default; + + public: + std::basic_ostream& GetStream() { + return stream_; + } + + protected: + void WriteImpl(const BufferType& bufferToPrint) override { + stream_.write(bufferToPrint.data(), bufferToPrint.size()); + stream_.write("\n", 1); + stream_.flush(); + } + + private: + std::basic_ostream& stream_; + }; + + template + class BasicFileSink : public detail::BasicLoggerSink { + public: + using Base = detail::BasicLoggerSink; + using typename Base::BufferType; + using typename Base::NameType; + using typename Base::PatternType; + + public: + BasicFileSink(const std::filesystem::path& filePath, NameType&& name, detail::AsyncSink isAsync) + : Base(std::forward(name), isAsync), stream_(filePath, std::ios::out) {} + + ~BasicFileSink() override = default; + + public: + std::basic_ostream& GetStream() { + return stream_; + } + + protected: + void WriteImpl(const BufferType& bufferToPrint) override { + stream_.write(bufferToPrint.data(), bufferToPrint.size()); + stream_.write("\n", 1); + stream_.flush(); + } + + private: + std::basic_ofstream stream_; + }; +} // namespace stream::flog::Sinks diff --git a/src/stream/flog/sinks/logger_sink.hxx b/src/stream/flog/sinks/logger_sink.hxx new file mode 100644 index 00000000..00ec0d7a --- /dev/null +++ b/src/stream/flog/sinks/logger_sink.hxx @@ -0,0 +1,96 @@ +#pragma once + +#include "stream/flog/detail/detail.hxx" + +#include + +namespace stream::flog::detail { + enum class AsyncSink { + Sync, + Async + }; + + template + class BasicLoggerSink { + public: + using PatternType = std::basic_string; + using PatternTransferType = std::basic_string_view; + using NameType = std::basic_string; + using BufferType = std::basic_string_view; + + using SeverityValueType = typename Severity::Value; + + public: + BasicLoggerSink(NameType name) : name(std::move(name)), is_async(AsyncSink::Sync) {} + BasicLoggerSink(NameType name, AsyncSink isAsync) : name(std::move(name)), is_async(isAsync) {} + + virtual ~BasicLoggerSink() = default; + + public: + NameType name = ""; + PatternType pattern = "[{logtime:pattern='default'}] {name} >> {data}"; + SeverityValueType sink_severity{SeverityValueType::DefaultSeverity}; + typename Severity::PatternOverride severity_pattern_override; + AsyncSink is_async; + + protected: + std::future async_waiter_; + + public: + bool need_to_log(const SeverityValueType& severity) { + return severity >= sink_severity; + } + void WriteToSink(const SeverityValueType& severity, const BufferType& bufferToPrint) { + if (need_to_log(severity)) WriteToSink(bufferToPrint); + } + + public: + PatternTransferType get_pattern(const typename Severity::Value& severity) const { + PatternTransferType customPattern = severity_pattern_override.get_pattern(severity); + if (customPattern.data() == nullptr || customPattern.size() == 0) return pattern; + return customPattern; + } + + protected: + virtual void WriteImpl(const BufferType& bufferToPrint) = 0; + + public: + void WriteToSinkSync(const BufferType& bufferToPrint) { + WriteImpl(bufferToPrint); + } + void WriteToSinkAsync(const BufferType& bufferToPrint) { + async_waiter_ = std::async(std::launch::async, &BasicLoggerSink::WriteToSinkSync, this, bufferToPrint); + } + + void WriteToSink(const BufferType& bufferToPrint) { + if (is_async == AsyncSink::Sync) + WriteToSinkSync(bufferToPrint); + else + WriteToSinkAsync(bufferToPrint); + } + + public: + void wait_until_finished_to_write() { + if (is_async == AsyncSink::Async) return async_waiter_.get(); + } + + void FormatAndWriteToSinkSync(PatternTransferType pattern, const std::chrono::nanoseconds& log_time, const NameType& logger_name, const BufferType& format_buffer) { + fmt::buf::DynamicStreamIOManager manager(256); + + auto format_pattern_str = fmt::detail::format_in_manager(manager, false, pattern, FORMAT_SV("logtime", log_time), + FORMAT_SV("name", ConcatNameAndSinkName(logger_name, name)), FORMAT_SV("data", format_buffer)); + BufferType buffer(*format_pattern_str); + WriteToSinkSync(buffer); + } + + void FormatAndWriteToSinkAsync(PatternTransferType pattern, const std::chrono::nanoseconds& log_time, const NameType& logger_name, const BufferType& format_buffer) { + // TODO + async_waiter_ = std::async(std::launch::async, &BasicLoggerSink::FormatAndWriteToSinkSync, this, pattern, log_time, logger_name, format_buffer); + } + + void format_and_write_to_sink(PatternTransferType pattern, const std::chrono::nanoseconds& log_time, const NameType& logger_name, const BufferType& format_buffer) { + if (is_async == AsyncSink::Sync) return FormatAndWriteToSinkSync(pattern, log_time, logger_name, format_buffer); + return FormatAndWriteToSinkAsync(pattern, log_time, logger_name, format_buffer); + } + }; +} // namespace stream::flog::detail diff --git a/src/stream/fmt.hxx b/src/stream/fmt.hxx new file mode 100644 index 00000000..3eb2d6f6 --- /dev/null +++ b/src/stream/fmt.hxx @@ -0,0 +1,5 @@ +#pragma once + +#include "fmt/context/formatter_executor/utility_functions.hxx" + +#include "fmt/serializers/format_stdlib.hxx" diff --git a/src/stream/fmt/buf/fmt_manip_io.hxx b/src/stream/fmt/buf/fmt_manip_io.hxx new file mode 100644 index 00000000..7bc36ff7 --- /dev/null +++ b/src/stream/fmt/buf/fmt_manip_io.hxx @@ -0,0 +1,120 @@ +#pragma once + +#include "stream.hxx" +#include "manip_io.hxx" +#include "test_manip.hxx" + +namespace stream::fmt::buf { + template + class FMTStreamIO : public StreamIO { + public: + using typename StreamIO::TChar; + + using StreamIO::buffer; + using StreamIO::current_pos; + using StreamIO::buffer_end; + + using StreamIO::get; + using StreamIO::get_buffer_total_size; + using StreamIO::get_buffer_current_size; + using StreamIO::get_buffer_remaining_size; + using StreamIO::is_out_of_bound; + using StreamIO::is_empty; + using StreamIO::is_end_of_string; + + using StreamIO::manager; + + protected: + FMTStreamIO(BasicStreamIOManager& ostream_manager) noexcept : StreamIO(ostream_manager) {} + + public: + static FMTStreamIO create(BasicStreamIOManager& ostream_manager) { + FMTStreamIO res(ostream_manager); + StreamIO::init(res); + return res; + } + + public: + std::size_t no_stride = 0; + std::size_t indent = 0; + }; + + template + class FMTManipIO { + public: + FMTManipIO(FMTStreamIO& buffer) : buffer(buffer) {} + + public: + FMTStreamIO& buffer; + + public: + constexpr inline void add_no_stride(const std::size_t no_stride) noexcept { + buffer.no_stride += no_stride; + } + + constexpr inline void add_indent(const std::size_t indent) noexcept { + buffer.indent += indent; + } + constexpr inline void remove_indent(const std::size_t indent) noexcept { + buffer.indent -= indent; + } + constexpr inline void set_indent() noexcept { + buffer.indent = buffer.get_buffer_current_size() - buffer.no_stride; + } + + public: + constexpr inline void new_line_indent() { + ManipIO(buffer).pushback('\n'); + return ManipIO(buffer).pushback(' ', buffer.indent); + } + + constexpr inline void pushback_check_indent(const TChar c) { + ManipIO(buffer).pushback(c); + if (c == '\n') { + return ManipIO(buffer).pushback(' ', buffer.indent); + } + } + }; + + template + class FMTParamsManip { + public: + FMTParamsManip(Stream& buffer) : buffer(buffer) {} + + public: + Stream& buffer; + + public: + template + inline void param_go_to(const CharToTest... ele) { + TestManip(buffer).GoTo(ele..., '}'); + } + template + void param_go_to_forward(const CharToTest... ele) { + return TestManip(buffer).go_to_forward(ele..., '}'); + } + + inline bool is_begin_of_parameter() { + return TestAccess(buffer).is_equal_to('{'); + } + inline bool is_end_of_parameter() { + return TestAccess(buffer).is_equal_to('}'); + } + + public: + template + bool next_is_named_args(const std::basic_string_view& sv) { + TestAccess access(buffer); + TestManip manip(buffer); + + TChar* const oldpos = buffer.current_pos; + + auto is_same = manip.is_same_forward(sv); + if (is_same && (access.is_equal_to(':') || access.is_equal_to('}'))) { + return true; + } + buffer.current_pos = oldpos; + return false; + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/fmt_read_manip.hxx b/src/stream/fmt/buf/fmt_read_manip.hxx new file mode 100644 index 00000000..016b6925 --- /dev/null +++ b/src/stream/fmt/buf/fmt_read_manip.hxx @@ -0,0 +1,205 @@ +#pragma once + +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/utils/buffer_shift_manip.hxx" +#include "stream/fmt/buf/manip.hxx" +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/read_manip.hxx" + +namespace stream::fmt::buf { + template + class FMTReadManip { + public: + FMTReadManip(Stream& buffer) : buffer(buffer) {} + + public: + Stream& buffer; + + public: + template + void read_integer(T& i, detail::ShiftInfo shift = detail::ShiftInfo{}) { + ShiftReadManip shift_manip(buffer); + buf::TestManip manip(buffer); + + shift_manip.ignore_shift_begin_space(shift); + + bool sign = false; + if constexpr (std::is_signed_v) { + sign = manip.is_equal_to_forward('-'); + if (manip.is_equal_to_forward('-')) --shift.size; + } + + TestAccess(buffer).is_a_digit(); + + T res = (T)0; + while (TestAccess(buffer).is_a_digit()) { + res = res * 10 + (Manip(buffer).get_and_forward() - '0'); + --shift.size; + } + + shift_manip.ignore_shift_end(shift); + + i = sign ? -res : res; + } + + public: + template + void read_float(T& t, std::int32_t float_precision = -1, detail::ShiftInfo shift = detail::ShiftInfo{}) { + ShiftReadManip shift_manip(buffer); + buf::TestAccess access(buffer); + buf::TestManip manip(buffer); + + shift_manip.ignore_shift_begin_space(shift); + + bool sign = manip.is_equal_to_forward('-'); + if (sign) --shift.size; + + T intpart = static_cast(0); + if (access.is_a_digit()) { + while (access.is_a_digit()) { + intpart = intpart * 10 + (buffer.get() - '0'); + Manip(buffer).forward(); + --shift.size; + } + } else if (access.is_equal_to('.')) { + buf::Manip(buffer).forward(); + } else { + throw std::runtime_error("fmt error: Parse_NonValidDigit"); + } + + if (float_precision <= 0) + while (access.is_a_digit() && buffer.is_end_of_string() == false) { + Manip(buffer).forward_force(); + --shift.size; + } + else { + while (Access(buffer).is_a_digit() && float_precision > 0 && buffer.is_end_of_string() == false) { + Manip(buffer).forward_force(); + float_precision--; + --shift.size; + } + } + Manip(buffer).backward_force(); + + T dec = (T)0; + while (access.is_a_digit()) { + dec += static_cast(buffer.get() - '0'); + Manip(buffer).backward_force(); + dec /= 10; + } + + shift_manip.ignore_shift_end(shift); + + t = sign ? -intpart - dec : intpart + dec; + } + + public: + template + void read_integer_h(T& i, std::uint8_t digitsize, std::optional (&digit_lut)(TChar), TChar base_prefix = '\0', + detail::ShiftInfo shift = detail::ShiftInfo{}) { + ShiftReadManip shift_manip(buffer); + buf::TestAccess access(buffer); + buf::TestManip manip(buffer); + + shift.size -= sizeof(T) * 8; + if (base_prefix != '\0') shift.size -= 2; + + shift_manip.ignore_shift_begin_space(shift); + + if (base_prefix != '\0') { + manip.skip_one_of('0'); + manip.skip_one_of(base_prefix); + } + + T res = (T)0; + std::optional get_current = digit_lut(buffer.get()); + while (get_current.has_value()) { + res = res << digitsize; + res += get_current.value(); + get_current = digit_lut(buffer.get()); + Manip(buffer).forward_force(); + } + + shift_manip.ignore_shift_end(shift); + + i = res; + } + + protected: + static constexpr std::optional digit_lut_bin(TChar in) { + if (in == '0') return 0; + if (in == '1') return 1; + return std::nullopt; + } + static constexpr std::optional digit_lut_oct(TChar in) { + if (in >= '0' && in <= '7') return in - '0'; + return std::nullopt; + } + static constexpr std::optional digit_lut_dec(TChar in) { + if (in >= '0' && in <= '9') return in - '0'; + return std::nullopt; + } + static constexpr std::optional digit_lut_hexupper(TChar in) { + if (in >= '0' && in <= '9') return in - '0'; + if (in >= 'A' && in <= 'F') return in - 'A'; + return std::nullopt; + } + static constexpr std::optional digit_lut_hexlower(TChar in) { + if (in >= '0' && in <= '9') return in - '0'; + if (in >= 'a' && in <= 'f') return in - 'a'; + return std::nullopt; + } + + public: + template + void read_integer_format_data(T& i, const detail::FormatData& formatdata) { + if (formatdata.has_spec) { + switch (formatdata.integer_print) { + case detail::IntegerPrintBase::Dec: + if (formatdata.shift.type == detail::ShiftInfo::ShiftType::Nothing) + return ReadManip(buffer).fast_read_integer(i); + else + return read_integer(i, formatdata.shift); + case detail::IntegerPrintBase::Bin: + case detail::IntegerPrintBase::BinUpper: + return read_integer_h(i, 1, digit_lut_bin, formatdata.prefix_suffix ? (char)formatdata.integer_print : '\0', formatdata.shift); + case detail::IntegerPrintBase::Oct: + case detail::IntegerPrintBase::OctUpper: + return read_integer_h(i, 3, digit_lut_oct, formatdata.prefix_suffix ? (char)formatdata.integer_print : '\0', formatdata.shift); + case detail::IntegerPrintBase::Hex: + return read_integer_h(i, 4, digit_lut_hexlower, formatdata.prefix_suffix ? (char)formatdata.integer_print : '\0', formatdata.shift); + case detail::IntegerPrintBase::HexUpper: + return read_integer_h(i, 4, digit_lut_hexupper, formatdata.prefix_suffix ? (char)formatdata.integer_print : '\0', formatdata.shift); + } + } + return ReadManip(buffer).fast_read_integer(i); + } + template + void read_float_format_data(T& i, const detail::FormatData& formatdata) { + if (formatdata.has_spec) { + if (formatdata.ShiftType == detail::ShiftInfo::ShiftType::Nothing) + return ReadManip(buffer).fast_read_float(i, formatdata.float_precision); + else + return read_float(i, formatdata.float_precision, formatdata.shift); + } + return ReadManip(buffer).fast_read_float(i, formatdata.float_precision); + } + + public: + template + void read_char_ptr(const CharStr* str, std::size_t sizeContainer, std::size_t sizeToWrite, detail::ShiftInfo shift = detail::ShiftInfo{}) { + // FIXME + // TODO + throw std::runtime_error("fmt error: FunctionNotImpl"); + } + + template + void read_char_array(const CharStr (&str)[SIZE], detail::ShiftInfo shift = detail::ShiftInfo{}) { + return read_char_ptr(str, SIZE, 0, shift); + } + template + void read_char_bound(const CharStr* begin, const CharStr* end, detail::ShiftInfo shift = detail::ShiftInfo{}) { + return read_char_ptr(begin, end - begin, 0, shift); + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/fmt_write_manip.hxx b/src/stream/fmt/buf/fmt_write_manip.hxx new file mode 100644 index 00000000..4dc70544 --- /dev/null +++ b/src/stream/fmt/buf/fmt_write_manip.hxx @@ -0,0 +1,238 @@ +#pragma once + +#include "stream.hxx" +#include "fmt_manip_io.hxx" +#include "utils/buffer_shift_manip.hxx" +#include "manip_io.hxx" +#include "write_manip.hxx" + +#include + +namespace stream::fmt::buf { + template + class FMTWriteManip { + public: + FMTWriteManip(FMTStreamIO& buffer) : buffer(buffer) {} + + public: + FMTStreamIO& buffer; + + public: + template + void write_integer(T i, detail::ShiftInfo shift = detail::ShiftInfo{}) { + char old_after = shift.print.after; + if (shift.print.after >= '0' && shift.print.after <= '9') shift.print.after = ' '; + + std::int32_t nb_digit = WriteUtils::get_number_of_digit_dec(i); + + shift.size -= nb_digit; + if (i < 0) --shift.size; + + if (shift.size <= 0) { + return WriteManip(buffer).fast_write_integer(i); + } + + if (!shift.print.before_is_a_digit()) { + ShiftWriteManip(buffer).write_shift_begin(shift); + } + if (i < 0) { + ManipIO(buffer).pushback('-'); + i = -i; + } + if (shift.print.before_is_a_digit()) { + ShiftWriteManip(buffer).write_shift_right_all(shift); + } + + if (i == 0) { + ManipIO(buffer).pushback('0'); + } else { + ManipIO(buffer).forward(nb_digit); + std::int32_t nb_digit_ = nb_digit; + while (nb_digit_ > 0) { + Manip(buffer).backward_force(); + buffer.set(i % 10 + '0'); + i /= 10; + nb_digit_--; + } + ManipIO(buffer).forward(nb_digit); + } + + ShiftWriteManip(buffer).write_shift_end(shift); + + shift.print.after = old_after; + } + + public: + template + void write_float(T i, std::int32_t float_precision = 2, detail::ShiftInfo shift = detail::ShiftInfo{}) { + char old_before = shift.print.before; + if (shift.print.before >= '0' && shift.print.before <= '9') shift.print.before = ' '; + + std::int32_t nb_digit = WriteUtils::get_number_of_digit_dec(std::trunc(i)); + + shift.size -= nb_digit + float_precision + 1; + if (i < 0) --shift.size; + + if (shift.size <= 0) { + return WriteManip(buffer).fast_write_float(i, float_precision); + } + + if (!shift.print.before_is_a_digit()) { + ShiftWriteManip(buffer).write_shift_begin(shift); + } + if (i < 0) { + ManipIO(buffer).pushback('-'); + i = -i; + } + if (shift.print.before_is_a_digit()) { + ShiftWriteManip(buffer).write_shift_right_all(shift); + } + + T k = std::trunc(i); + if (k == 0) { + ManipIO(buffer).pushback('0'); + } else { + ManipIO(buffer).forward(nb_digit); + std::int32_t nb_digit_ = nb_digit; + while (nb_digit_ > 0) { + Manip(buffer).backward_force(); + buffer.set(char(std::fmod(i, 10)) + '0'); + k /= 10; + nb_digit_--; + } + ManipIO(buffer).forward(nb_digit); + } + + ManipIO(buffer).pushback('.'); + i -= k; + while (float_precision-- != 0) { + T decimal = std::trunc(i *= 10); + ManipIO(buffer).pushback((char)decimal + '0'); + i -= decimal; + } + + ShiftWriteManip(buffer).write_shift_end(shift); + + shift.print.before = old_before; + } + + public: + template + void write_integer_h(T i, std::uint8_t digitsize, const TChar* const lut, TChar base_prefix = '\0', detail::ShiftInfo shift = detail::ShiftInfo{}) { + ManipIO manip(buffer); + + std::int32_t digit_count = sizeof(T) * (8 / digitsize); + std::uint8_t mask = (1 << digitsize) - 1; + + if (i != 0) { + // Remove leading 0 + std::int32_t last_pos_with_data = digit_count; + std::int32_t k = digit_count; + T cpy_i = i; + while (--k != 0) { + if ((cpy_i & mask) != 0) { + last_pos_with_data = k; + } + cpy_i = cpy_i >> digitsize; + } + digit_count -= last_pos_with_data; + } + + if (base_prefix != '\0') { + ManipIO(buffer).pushback('0'); + ManipIO(buffer).pushback(base_prefix); + } + + if (i == 0) { + ManipIO(buffer).pushback('0'); + return; + } + + manip.forward(digit_count); + std::int32_t k = digit_count + 1; + while (--k != 0) { + Manip(buffer).backward_force(); + buffer.set(lut[i & mask]); + i = i >> digitsize; + } + manip.forward(digit_count); + } + + public: + template + void write_integer_format_data(T i, const detail::FormatData& formatdata) { + if (formatdata.has_spec) { + switch (formatdata.integer_print) { + case detail::IntegerPrintBase::Dec: + if (formatdata.shift.type == detail::ShiftInfo::ShiftType::Nothing) + return WriteManip(buffer).fast_write_integer(i); + else + return write_integer(i, formatdata.shift); + case detail::IntegerPrintBase::Bin: + case detail::IntegerPrintBase::BinUpper: + return write_integer_h(i, 1, WriteManip::BIN, formatdata.prefix_suffix ? (char)formatdata.integer_print : '\0', formatdata.shift); + case detail::IntegerPrintBase::Oct: + case detail::IntegerPrintBase::OctUpper: + return write_integer_h(i, 3, WriteManip::OCT, formatdata.prefix_suffix ? (char)formatdata.integer_print : '\0', formatdata.shift); + case detail::IntegerPrintBase::Hex: + return write_integer_h(i, 4, WriteManip::LOWER_HEX, formatdata.prefix_suffix ? (char)formatdata.integer_print : '\0', formatdata.shift); + case detail::IntegerPrintBase::HexUpper: + return write_integer_h(i, 4, WriteManip::UPPER_HEX, formatdata.prefix_suffix ? (char)formatdata.integer_print : '\0', formatdata.shift); + } + } + return WriteManip(buffer).fast_write_integer(i); + } + template + void write_float_formatdata(T i, const detail::FormatData& formatdata) { + if (formatdata.has_spec) { + if (formatdata.shift.type != detail::ShiftInfo::ShiftType::Nothing) return write_float(i, formatdata.float_precision, formatdata.shift); + } + + return WriteManip(buffer).fast_write_float(i, formatdata.float_precision); + } + + public: + void write_indent_char_ptr(const TChar* str, std::size_t size) { + while (size > 0) { + const TChar* const begin = str; + while (size > 0 && *str != '\n') { + ++str, --size; + } + const TChar* const end = str; + + WriteManip(buffer).fast_write_sv(std::basic_string_view(begin, end)); + + if (size > 0 && *str == '\n') { + FMTManipIO(buffer).new_line_indent(); + ++str; + --size; + } + } + } + void write_indent_sv(std::basic_string_view sv) { + return write_indent_char_ptr(sv.data(), sv.size()); + } + + void write_sv(std::basic_string_view sv, detail::ShiftInfo& shift) { + if (shift.size <= 0) { + return WriteManip(buffer).fast_write_sv(sv); + } + + if (ManipIO(buffer).reserve(std::max(static_cast(shift.size), sv.size())) == false) { + throw std::bad_alloc(); + } + + if (static_cast(shift.size) > sv.size()) { + shift.size -= static_cast(sv.size()); + + ShiftWriteManip(buffer).write_shift_begin(shift); + + WriteManip(buffer).fast_write_sv(sv); + + ShiftWriteManip(buffer).write_shift_end(shift); + } else { + WriteManip(buffer).fast_write_sv(sv); + } + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/manip.hxx b/src/stream/fmt/buf/manip.hxx new file mode 100644 index 00000000..9b840865 --- /dev/null +++ b/src/stream/fmt/buf/manip.hxx @@ -0,0 +1,94 @@ +#pragma once + +#include "stream.hxx" + +namespace stream::fmt::buf { + template + class Access { + public: + constexpr inline Access(const Stream& buffer) noexcept : buffer(buffer) {} + + public: + const Stream& buffer; + + public: + constexpr inline bool can_move_forward(const std::size_t count = 1) const noexcept { + return buffer.current_pos + count <= buffer.buffer_end; + } + constexpr inline bool can_move_backward(const std::size_t count = 1) const noexcept { + return buffer.current_pos - count >= buffer.buffer; + } + + constexpr inline std::remove_cv_t get_next(const std::size_t count = 1) const { + if (Access(buffer).can_move_forward(count) == false) throw std::runtime_error("fmt error: Buffer_OutOfBoundAccess"); + return get_next_force(count); + } + constexpr inline std::remove_cv_t get_prev(const std::size_t count = 1) const { + if (Access(buffer).can_move_backward(count) == false) throw std::runtime_error("fmt error: Buffer_OutOfBoundAccess"); + return get_prev_force(count); + } + constexpr inline TChar get_next_force(const std::size_t count = 1) const noexcept { + return *(buffer.current_pos + count); + } + constexpr inline TChar get_prev_force(const std::size_t count = 1) const noexcept { + return *(buffer.current_pos - count); + } + }; + + template + class Manip { + public: + constexpr inline Manip(Stream& buffer) noexcept : buffer(buffer) {} + + public: + Stream& buffer; + + public: + constexpr inline void reload(TChar* const buffer_, const std::size_t size_) noexcept { + buffer.buffer = buffer_; + buffer.current_pos = buffer_; + buffer.buffer_end = buffer_ + size_; + } + constexpr inline void reload(std::basic_string_view sv) noexcept { + buffer.buffer = sv.data(); + buffer.current_pos = sv.data(); + buffer.buffer_end = sv.data() + sv.size(); + } + + constexpr inline void reload(Stream& buffer_) noexcept { + buffer.buffer = buffer_.buffer; + buffer.current_pos = buffer_.current_pos; + buffer.buffer_end = buffer_.buffer_end; + } + + Access access() { + return Access(buffer); + } + + public: + constexpr inline void forward_force(const std::size_t count = 1) noexcept { + buffer.current_pos += count; + } + constexpr inline void forward(const std::size_t count = 1) { + if (!access().can_move_forward(count)) throw std::runtime_error("fmt error: Buffer_OutOfBoundAccess"); + buffer.current_pos += count; + } + + constexpr inline void backward_force(const std::size_t count = 1) noexcept { + buffer.current_pos -= count; + } + constexpr inline void backward(const std::size_t count = 1) { + if (!access().can_move_backward(count)) throw std::runtime_error("fmt error: Buffer_OutOfBoundAccess"); + buffer.current_pos -= count; + } + + constexpr inline std::remove_cv_t get_and_forward() { + if (Access(buffer).can_move_forward(1) == false) throw std::runtime_error("fmt error: Buffer_OutOfBoundAccess"); + return *buffer.current_pos++; + } + constexpr inline std::remove_cv_t get_and_backward() { + if (Access(buffer).can_move_backward(1) == false) throw std::runtime_error("fmt error: Buffer_OutOfBoundAccess"); + return *buffer.current_pos--; + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/manip_io.hxx b/src/stream/fmt/buf/manip_io.hxx new file mode 100644 index 00000000..ffd0814a --- /dev/null +++ b/src/stream/fmt/buf/manip_io.hxx @@ -0,0 +1,76 @@ +#pragma once + +#include "stream.hxx" +#include "streamio.hxx" +#include "manip.hxx" + +#include "streamio_manager/basic_streamio_manager.hxx" + +namespace stream::fmt::buf { + template + class ManipIO { + public: + constexpr inline ManipIO(StreamIO& buffer) noexcept : buffer(buffer) {} + + public: + StreamIO& buffer; + + public: + void compute_generated_size() noexcept { + buffer.manager.compute_generated_size(buffer.get_buffer_current_size()); + } + + public: + bool add_size(const std::size_t count) noexcept { + std::size_t currentSize = buffer.get_buffer_current_size(); + if (buffer.manager.add_size(count) == false) return false; + Manip(buffer).reload(buffer.manager.get_buffer(), buffer.manager.get_buffer_size()); + buffer.current_pos = buffer.manager.get_buffer() + currentSize; + return true; + } + + inline bool reserve(const std::size_t count = 1) noexcept { + if (buffer.current_pos + count <= buffer.buffer_end) return true; + return add_size(count); + } + + void forward(const std::size_t count = 1) { + if (reserve(count) == false) throw std::bad_alloc(); + buffer.current_pos += count; + } + + public: + inline void set(const TChar c) noexcept { + *buffer.current_pos = c; + } + + void pushback(const TChar c) { + if (reserve(1) == false) throw std::bad_alloc(); + *buffer.current_pos++ = c; + } + inline void pushback_force(const TChar c) noexcept { + *buffer.current_pos++ = c; + } + + public: + void pushback(const TChar c, auto count) { + if (reserve(count) == false) throw std::bad_alloc(); + while (count-- > 0) + pushback_force(c); + } + + private: + template + inline void pushback_seq_impl(const TChar c, const Rest... rest) noexcept { + force_pushback(c); + if constexpr (sizeof...(rest) > 0) pushback_seq_impl(rest...); + } + + public: + template + void pushback_seq(const CharToPush... ele) { + if (reserve(sizeof...(ele)) == false) throw std::bad_alloc(); + pushback_seq_impl(ele...); + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/read_manip.hxx b/src/stream/fmt/buf/read_manip.hxx new file mode 100644 index 00000000..53140bb9 --- /dev/null +++ b/src/stream/fmt/buf/read_manip.hxx @@ -0,0 +1,101 @@ +#pragma once + +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/manip.hxx" + +#include + +namespace stream::fmt::buf { + template + class ReadManip { + public: + constexpr inline ReadManip(Stream& buffer_) noexcept : buffer(buffer_) {} + + public: + Stream& buffer; + + public: + template + constexpr void fast_read_integer(T& t) { + bool sign = false; + if constexpr (std::is_signed_v) { + sign = TestManip(buffer).is_equal_to_forward('-'); + } + + if (!TestAccess(buffer).is_a_digit()) { + throw std::runtime_error("fmt error: Parse_NonValidDigit"); + } + + T value = static_cast(0); + while (TestAccess(buffer).is_a_digit()) { + value = value * static_cast(10) + static_cast(buffer.get() - static_cast('0')); + Manip(buffer).forward(); + } + + t = sign ? -value : value; + } + + public: + template + constexpr inline void fast_read_float(T& t, std::int32_t float_precision = -1) { + T intpart = static_cast(0); + + TestAccess access(buffer); + TestManip manip(buffer); + + bool sign = manip.is_equal_to_forward('-'); + + if (access.is_a_digit()) { + fast_read_integer(intpart); + } else if (access.is_equal_to('.')) { + buf::Manip(buffer).forward(); + } else { + throw std::runtime_error("fmt error: Parse_NonValidDigit"); + } + + if (float_precision < 0) { + while (access.is_a_digit() && buffer.is_end_of_string() == false) { + Manip(buffer).forward_force(); + } + } else { + while (access.is_a_digit() && float_precision > 0 && buffer.is_end_of_string() == false) { + Manip(buffer).forward_force(); + float_precision--; + } + } + Manip(buffer).backward_force(); + + T dec = static_cast(0); + while (access.is_a_digit()) { + dec += static_cast(buffer.get() - '0'); + Manip(buffer).backward_force(); + dec /= 10; + } + + t = sign ? -intpart - dec : intpart + dec; + } + + public: + template + void fast_read_char_ptr(const CharPtr* str, std::size_t size_to_copy, bool is_zero_ended = true) { + if (Access(buffer).can_move_forward(size_to_copy) == false) { + return ReadManip(buffer).fast_read_char_ptr(str, buffer.get_buffer_remaining_size(), is_zero_ended); + } + + std::copy_n(str, size_to_copy, buffer.current_pos); + buffer.current_pos += size_to_copy; + + if (is_zero_ended) { + *str = 0; + } + } + template + void fast_read_char_array(const CharStr (&str)[SIZE], bool is_zero_ended = true) { + return fast_read_char_ptr(str, SIZE); + } + template + void fast_read_char_bound(const CharStr* begin, const CharStr* end, bool is_zero_ended = true) { + return fast_read_char_ptr(begin, end - begin - (is_zero_ended ? 1 : 0), is_zero_ended); + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/stream.hxx b/src/stream/fmt/buf/stream.hxx new file mode 100644 index 00000000..1e85ecd6 --- /dev/null +++ b/src/stream/fmt/buf/stream.hxx @@ -0,0 +1,88 @@ +#pragma once + +#include "stream/fmt/detail/prelude.hxx" + +namespace stream::fmt::buf { + template + class Stream { + public: + using TChar = CharType; + + public: + TChar* buffer; + TChar* current_pos; + TChar* buffer_end; // Not included + + public: + Stream() noexcept : buffer(nullptr), current_pos(nullptr), buffer_end(nullptr) {} + Stream(TChar* const buffer_, const std::size_t size_) noexcept : buffer(buffer_), current_pos(buffer_), buffer_end(buffer_ + size_) {} + + public: + constexpr inline TChar get() const { + return *current_pos; + } + + public: + constexpr inline std::size_t get_buffer_total_size() const noexcept { + return static_cast(buffer_end - buffer); + } + constexpr inline std::size_t get_buffer_current_size() const noexcept { + return static_cast(current_pos - buffer); + } + constexpr inline std::size_t get_buffer_remaining_size() const noexcept { + return static_cast(buffer_end - current_pos); + } + + constexpr inline bool is_out_of_bound() const noexcept { + return current_pos < buffer || current_pos >= buffer_end; + } + constexpr inline bool is_empty() const noexcept { + return current_pos >= buffer_end; + } + constexpr inline bool is_end_of_string() const noexcept { + return is_empty() || get() == 0; + } + }; + + template + class StreamView : public Stream { + public: + using typename Stream::TChar; + + using Stream::buffer; + using Stream::current_pos; + using Stream::buffer_end; + + using Stream::get; + using Stream::get_buffer_total_size; + using Stream::get_buffer_current_size; + using Stream::get_buffer_remaining_size; + using Stream::is_out_of_bound; + using Stream::is_empty; + using Stream::is_end_of_string; + + public: + StreamView() noexcept : Stream() {} + + template + StreamView(const CharType (&data)[SIZE]) noexcept : Stream(data, SIZE) { + while (buffer_end - 1 > buffer && *(buffer_end - 1) == 0) + --buffer_end; + } + + StreamView(std::basic_string_view sv) noexcept : Stream(sv.data(), sv.size()) {} + + StreamView(const CharType* const buffer, const std::size_t size) noexcept : Stream(buffer, size) {} + + public: + operator Stream() const { + return Stream{.buffer = buffer, .current_pos = current_pos, .buffer_end = buffer_end}; + } + }; + + template + concept convertible_to_buffer_info = requires(T&& t) { Stream(std::forward(t)); }; + + template + concept convertible_to_buffer_info_view = requires(T&& t) { StreamView(std::forward(t)); }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/streamio.hxx b/src/stream/fmt/buf/streamio.hxx new file mode 100644 index 00000000..9c748dcf --- /dev/null +++ b/src/stream/fmt/buf/streamio.hxx @@ -0,0 +1,53 @@ +#pragma once + +#include "stream.hxx" +#include "manip.hxx" + +#include "streamio_manager/basic_streamio_manager.hxx" + +namespace stream::fmt::buf { + template + class StreamIO : public Stream { + public: + using typename Stream::TChar; + + using Stream::buffer; + using Stream::current_pos; + using Stream::buffer_end; + + using Stream::get; + using Stream::get_buffer_total_size; + using Stream::get_buffer_current_size; + using Stream::get_buffer_remaining_size; + using Stream::is_out_of_bound; + using Stream::is_empty; + using Stream::is_end_of_string; + + protected: + StreamIO(BasicStreamIOManager& ostream_manager) noexcept : Stream(), manager(ostream_manager) {} + + protected: + static void init(StreamIO& in) { + in.manager.begin_context(); + Manip(in).reload(in.manager.get_buffer(), in.manager.get_buffer_size()); + } + + public: + static StreamIO create(BasicStreamIOManager& ostream_manager) { + StreamIO res(ostream_manager); + init(res); + return res; + } + + public: + inline void set(const TChar c) noexcept { + *current_pos = c; + } + + public: + BasicStreamIOManager& manager; + }; + + template + concept convertible_to_streamio_info = requires(T&& t) { StreamIO(std::forward(t)); }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/streamio_manager/basic_streamio_manager.hxx b/src/stream/fmt/buf/streamio_manager/basic_streamio_manager.hxx new file mode 100644 index 00000000..489ca0de --- /dev/null +++ b/src/stream/fmt/buf/streamio_manager/basic_streamio_manager.hxx @@ -0,0 +1,63 @@ +#pragma once + +#include "stream/fmt/detail/prelude.hxx" +#include "stream/fmt/buf/stream.hxx" + +namespace stream::fmt::buf { + template + class BasicStreamIOManager { + public: + BasicStreamIOManager() = default; + virtual ~BasicStreamIOManager() = default; + BasicStreamIOManager(BasicStreamIOManager&) = delete; + BasicStreamIOManager& operator=(BasicStreamIOManager&) = delete; + + protected: + virtual void begin_context_impl() {} + virtual void compute_generated_size_impl(const std::size_t /* totalGeneratedLength */) {} + + public: + void begin_context() { + return begin_context_impl(); + } + void compute_generated_size(std::size_t totalGeneratedLength) { + compute_generated_size_impl(totalGeneratedLength); + set_last_generated_data_size(totalGeneratedLength); + } + + public: + virtual CharType* get_buffer() = 0; + virtual const CharType* get_buffer() const = 0; + virtual std::size_t get_buffer_size() const = 0; + + public: + virtual bool add_size(const std::size_t count) = 0; + + public: + StreamView get_last_generated_buffer_info_view() const { + return StreamView(get_buffer(), last_generated_data_size_); + } + operator StreamView() const { + return get_last_generated_buffer_info_view(); + } + std::basic_string_view get_last_generated_string_view() const { + return std::basic_string_view(get_buffer(), last_generated_data_size_); + } + operator std::basic_string_view() const { + return get_last_generated_string_view(); + } + + public: + std::size_t get_last_generated_data_size() const { + return last_generated_data_size_; + } + + private: + void set_last_generated_data_size(const std::size_t size) { + last_generated_data_size_ = size; + } + + protected: + std::size_t last_generated_data_size_{0}; + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/streamio_manager/dynamic_streamio_manager.hxx b/src/stream/fmt/buf/streamio_manager/dynamic_streamio_manager.hxx new file mode 100644 index 00000000..d978ab0b --- /dev/null +++ b/src/stream/fmt/buf/streamio_manager/dynamic_streamio_manager.hxx @@ -0,0 +1,118 @@ +#pragma once + +#include "basic_streamio_manager.hxx" + +#include +#include +#include + +namespace stream::fmt::buf { + template + class DynamicStreamIOManager : public BasicStreamIOManager { + public: + DynamicStreamIOManager(std::size_t begin_size = DEFAULT_BEGIN_SIZE) : buffer_size_(begin_size) {} + + ~DynamicStreamIOManager() override = default; + DynamicStreamIOManager(DynamicStreamIOManager&) = delete; + DynamicStreamIOManager& operator=(DynamicStreamIOManager&) = delete; + + public: + static constexpr std::size_t DEFAULT_BEGIN_SIZE = 128; + static constexpr std::size_t GROW_UP_BUFFER_SIZE = 2; + static constexpr bool DEBUG_RESIZE = false; + + public: + CharType* get_buffer() override { + return buffer_.get(); + } + const CharType* get_buffer() const override { + return buffer_.get(); + } + std::size_t get_buffer_size() const override { + if (buffer_ == nullptr) return 0; + return buffer_size_; + } + + public: + void begin_context_impl() final { + if (buffer_ != nullptr) return; + + CharType* alloc = new CharType[buffer_size_]; + if (alloc == nullptr) throw std::runtime_error("fmt error: Manager_AllocationFailed"); + buffer_.reset(alloc); + } + + bool add_size(const std::size_t count) override { + return resize(count + buffer_size_); + } + bool resize(const std::size_t target_buffer_size); + + protected: + std::unique_ptr buffer_ = nullptr; + std::size_t buffer_size_ = 0; + }; + + template + class ShrinkDynamicStreamIOManager : public DynamicStreamIOManager { + public: + using Base = DynamicStreamIOManager; + using Base::DEBUG_RESIZE; + using Base::DEFAULT_BEGIN_SIZE; + using Base::GROW_UP_BUFFER_SIZE; + + using Base::get_buffer; + using Base::get_buffer_size; + using Base::resize; + + using Base::buffer_; + using Base::buffer_size_; + + static constexpr float MEAN_SIZE_OVERFLOW = 4.2f; + static constexpr float MEAN_SIZE_RESIZE = 1.4f; + static constexpr float MEAN_CALCFACT_OLD = 5; + static constexpr float MEAN_CALCFACT_LAST = 1; + + public: + ShrinkDynamicStreamIOManager(std::size_t begin_size = DEFAULT_BEGIN_SIZE) : Base(begin_size), mean_generated_size_(begin_size) {} + ~ShrinkDynamicStreamIOManager() override = default; + ShrinkDynamicStreamIOManager(ShrinkDynamicStreamIOManager&) = delete; + ShrinkDynamicStreamIOManager& operator=(ShrinkDynamicStreamIOManager&) = delete; + + protected: + void compute_generated_size_impl(std::size_t totalGeneratedLength) override { + // WTF + mean_generated_size_ = (mean_generated_size_ * MEAN_CALCFACT_OLD + totalGeneratedLength * MEAN_CALCFACT_LAST) / (MEAN_CALCFACT_OLD + MEAN_CALCFACT_LAST); + } + + public: + void shrink_if_needed() { + if (buffer_size_ > static_cast(mean_generated_size_ * MEAN_SIZE_OVERFLOW)) + return resize(static_cast(mean_generated_size_ * MEAN_SIZE_RESIZE)); + } + + private: + std::size_t mean_generated_size_ = 0; + }; + + template + bool DynamicStreamIOManager::resize(const std::size_t target_buffer_size) { + std::size_t new_buffer_size = target_buffer_size; + + if (buffer_size_ < target_buffer_size) { + new_buffer_size = buffer_size_; + while (new_buffer_size < target_buffer_size) + new_buffer_size *= GROW_UP_BUFFER_SIZE; + } + + CharType* new_buffer = new CharType[new_buffer_size]; + if (new_buffer == nullptr) return false; + + std::memcpy(new_buffer, buffer_.get(), std::min(new_buffer_size, buffer_size_)); + + if constexpr (DEBUG_RESIZE) std::cout << "resize from " << buffer_size_ << " to " << new_buffer_size << std::endl; + + buffer_.reset(new_buffer); + buffer_size_ = new_buffer_size; + return true; + } +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/streamio_manager/given_streamio_manager.hxx b/src/stream/fmt/buf/streamio_manager/given_streamio_manager.hxx new file mode 100644 index 00000000..920bde10 --- /dev/null +++ b/src/stream/fmt/buf/streamio_manager/given_streamio_manager.hxx @@ -0,0 +1,39 @@ +#pragma once + +#include "basic_streamio_manager.hxx" + +namespace stream::fmt::buf { + template + class GivenStreamIOManager : public BasicStreamIOManager { + public: + template + GivenStreamIOManager(CharType (&buffer)[SIZE]) : buffer_(buffer), buffer_size_(SIZE) {} + + GivenStreamIOManager(CharType* buffer, std::size_t buffer_size) : buffer_(buffer), buffer_size_(buffer_size) {} + + ~GivenStreamIOManager() override = default; + + GivenStreamIOManager(GivenStreamIOManager&) = delete; + GivenStreamIOManager& operator=(GivenStreamIOManager&) = delete; + + public: + CharType* get_buffer() override { + return buffer_; + } + const CharType* get_buffer() const override { + return buffer_; + } + std::size_t get_buffer_size() const override { + return buffer_size_; + } + + public: + bool add_size(const std::size_t /* count */) override { + return false; + } + + private: + CharType* buffer_; + std::size_t buffer_size_; + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/streamio_manager/static_streamio_manager.hxx b/src/stream/fmt/buf/streamio_manager/static_streamio_manager.hxx new file mode 100644 index 00000000..83a73d3f --- /dev/null +++ b/src/stream/fmt/buf/streamio_manager/static_streamio_manager.hxx @@ -0,0 +1,32 @@ +#pragma once + +#include "basic_streamio_manager.hxx" + +namespace stream::fmt::buf { + template + class StaticStreamIOManager : public BasicStreamIOManager { + public: + ~StaticStreamIOManager() override = default; + StaticStreamIOManager(StaticStreamIOManager&) = delete; + StaticStreamIOManager& operator=(StaticStreamIOManager&) = delete; + + public: + CharType* get_buffer() override { + return buffer_; + } + const CharType* get_buffer() const override { + return buffer_; + } + std::size_t get_buffer_size() const override { + return Count; + } + + public: + bool add_size(const std::size_t) override { + return false; + } + + private: + CharType buffer_[Count]; + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/test_manip.hxx b/src/stream/fmt/buf/test_manip.hxx new file mode 100644 index 00000000..1f59ce67 --- /dev/null +++ b/src/stream/fmt/buf/test_manip.hxx @@ -0,0 +1,184 @@ +#pragma once + +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/manip.hxx" + +namespace stream::fmt::buf { + template + class TestAccess { + public: + constexpr inline TestAccess(const Stream& buffer) noexcept : buffer(buffer) {} + + public: + const Stream& buffer; + + public: + constexpr inline bool is_equal_to(const TChar c) const noexcept { + return buffer.get() == c; + } + constexpr inline bool is_not_equal_to(const TChar c) const noexcept { + return buffer.get() != c; + } + template + constexpr inline bool is_equal_to(const TChar c, const CharToTest... ele) const noexcept { + return is_equal_to(c) || is_equal_to(ele...); + } + template + constexpr inline bool is_not_equal_to(const TChar c, const CharToTest... ele) const noexcept { + return is_not_equal_to(c) && is_not_equal_to(ele...); + } + + public: + constexpr inline bool is_lower_case() const noexcept { + return buffer.get() >= 'a' && buffer.get() <= 'z'; + } + constexpr inline bool is_upper_case() const noexcept { + return buffer.get() >= 'A' && buffer.get() <= 'Z'; + } + constexpr inline bool is_a_digit() const noexcept { + return buffer.get() >= '0' && buffer.get() <= '9'; + } + + public: + template + constexpr bool is_same(const CharToTest* str, std::size_t size, bool exact = false) const noexcept { + if (exact == true && size != buffer.get_buffer_remaining_size()) { + return false; + } + if (size > buffer.get_buffer_remaining_size()) { + return false; + } + + const TChar* bufferStr = buffer.current_pos; + bool is_same = true; + while (is_same && size != 0 && *str != 0) { + is_same = *bufferStr++ == *str++; + --size; + } + if (size != 0) { + return false; + } + return is_same; + } + template + constexpr inline bool is_same(std::basic_string_view sv, bool exact = false) const noexcept { + return is_same(sv.data(), sv.size(), false); + } + }; + + template + class TestManip { + public: + constexpr inline TestManip(Stream& buffer) noexcept : buffer(buffer) {} + + public: + Stream& buffer; + + using TConstChar = std::remove_const_t; + + public: + TestAccess access() const noexcept { + return TestAccess(buffer); + } + + public: + template + constexpr inline bool is_equal_to_forward(const CharToTest... ele) { + if (access().is_equal_to(ele...)) { + Manip(buffer).forward(); + return true; + } + return false; + } + template + constexpr inline bool is_not_equal_forward(const CharToTest... ele) { + if (access().is_not_equal_to(ele...)) { + Manip(buffer).forward(); + return true; + } + return false; + } + + public: + template + constexpr bool is_same_forward(const CharToTest* str, std::size_t size) { + if (access().is_same(str, size)) { + Manip(buffer).forward(size); + return true; + } + return false; + } + template + constexpr inline bool is_same_forward(std::basic_string_view sv) { + if (access().is_same(sv)) { + Manip(buffer).forward(sv.size()); + return true; + } + return false; + } + + public: + template + void skip_one_of(const CharToTest... ele) { + if (access().is_equal_to(ele...)) { + Manip(buffer).forward(); + } + throw std::runtime_error("fmt error: Parse_TokenNotExpected"); + } + + template + inline void ignore_one_of(const CharToTest... ele) { + if (access().is_equal_to(ele...) && Access(buffer).can_move_forward()) { + Manip(buffer).forward_force(); + } + } + + template + inline void ignore_every(const CharToTest... ele) { + while (access().is_equal_to(ele...) && Access(buffer).can_move_forward()) { + Manip(buffer).forward_force(); + } + } + + public: + void IgnoreOneSpace() { + return ignore_one_of(' ', '\t'); + } + void IgnoreOneBlank() { + return ignore_one_of(' ', '\t', '\n', '\r', '\v'); + } + + inline void ignore_every_spaces() { + ignore_every(' ', '\t'); + } + inline void IgnoreEveryBlanks() { + ignore_every(' ', '\t', '\n', '\r', '\v'); + } + + public: + template + inline void GoTo(const CharToTest... ele) noexcept { + while (access().is_not_equal_to(ele...) && Access(buffer).can_move_forward()) + Manip(buffer).forward_force(); + } + template + void go_to_forward(const CharToTest... ele) { + GoTo(ele...); + return Manip(buffer).forward(); + } + + public: + template + std::basic_string_view view_exec(Func&& func) { + TChar* begin = buffer.current_pos; + func(); + TChar* end = buffer.current_pos; + return std::basic_string_view(begin, end - begin); + } + + template + inline std::basic_string_view view_until(CharToTest&&... c) { + return view_exec([&] { TestManip(buffer).GoTo(std::forward(c)...); }); + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/utils/buffer_globber_manip.hxx b/src/stream/fmt/buf/utils/buffer_globber_manip.hxx new file mode 100644 index 00000000..d8ffd346 --- /dev/null +++ b/src/stream/fmt/buf/utils/buffer_globber_manip.hxx @@ -0,0 +1,115 @@ +#pragma once + +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/manip.hxx" + +namespace stream::fmt::buf { + template + class Globber { + public: + enum class PatternMatchType { + MatchBiggest, + MatchSmallest + }; + + private: + static const TChar* buffer_exec_glob_(Stream& istream, Stream& glob) { + if (glob.is_end_of_string()) { + return istream.current_pos; + } + + if (istream.is_end_of_string()) { + return nullptr; + } + + if (TestAccess(glob).is_equal_to('?')) { + Manip(glob).forward(); + Manip(istream).forward(); + return buffer_exec_glob_(istream, glob); + } else if (TestAccess(glob).is_equal_to('*')) { + Manip(glob).forward(); + const TChar* further = buffer_exec_glob_(istream, glob); + while (Access(istream).can_move_forward()) { + Manip(istream).forward(); + const TChar* last = buffer_exec_glob_(istream, glob); + if (last > further || further == nullptr) further = last; + } + return further; + } else if (TestAccess(glob).is_equal_to('[')) { + Manip(istream).forward(); + const TChar* begin = glob.current_pos; + TestManip(glob).go_to_forward(']'); + const TChar* end = glob.current_pos; + + StreamView charSet(begin, end - begin); + + bool is_inverted = TestAccess(glob).is_equal_to('!'); + TChar toMatch = istream.get(); + Manip(glob).forward(); + Manip(istream).forward(); + bool found = false; + + while (found == false && Access(charSet).can_move_forward()) { + if (TestAccess(charSet).is_equal_to(toMatch)) { + found = true; + break; + } + + if (TestAccess(charSet).is_equal_to('-')) { + TChar beginSubSet = Access(charSet).get_prev_force(); + TChar endSubSet = Access(charSet).get_next_force(); + if (toMatch >= beginSubSet && toMatch <= endSubSet) { + found = true; + break; + } + } + + Manip(charSet).forward(); + } + + if (found && is_inverted == false) + return buffer_exec_glob_(istream, glob); + else if (found == false && is_inverted == true) + return buffer_exec_glob_(istream, glob); + return nullptr; + } + + if (istream.get() == glob.get()) { + Manip(glob).forward(); + Manip(istream).forward(); + return buffer_exec_glob_(istream, glob); + } + return nullptr; + } + + public: + static void buffer_exec_glob(Stream& istream, Stream& glob, [[maybe_unused]] PatternMatchType patternMatchtype = PatternMatchType::MatchBiggest) { + const TChar* furtherPointMatched = buffer_exec_glob_(istream, glob); + if (furtherPointMatched != nullptr) istream.current_pos = furtherPointMatched; + } + }; + + template + class BufferGlobberManip { + public: + constexpr inline BufferGlobberManip(Stream& buffer) noexcept : buffer(buffer) {} + + public: + Stream& buffer; + + public: + void fast_read_char_ptrGlobber(std::basic_string_view globPattern, TChar* str, std::size_t size_to_copy) { + Stream globber(globPattern); + const TChar* begin = buffer.current_pos; + Globber::buffer_exec_glob(*this, globber); + const TChar* end = buffer.current_pos; + + Stream subContext(begin, end); + return ReadManip(subContext).fast_read_char_ptr(str, size_to_copy); + } + + void fast_read_char_ptrRegex(std::basic_string_view regexPattern, TChar* str, std::size_t size_to_copy) { + throw std::runtime_error("fmt error: FunctionNotImpl"); + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/utils/buffer_shift_manip.hxx b/src/stream/fmt/buf/utils/buffer_shift_manip.hxx new file mode 100644 index 00000000..31ad6b34 --- /dev/null +++ b/src/stream/fmt/buf/utils/buffer_shift_manip.hxx @@ -0,0 +1,79 @@ +#pragma once + +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/manip_io.hxx" + +namespace stream::fmt::buf { + template + class ShiftWriteManip { + public: + ShiftWriteManip(StreamIO& buffer) : buffer(buffer) {} + + public: + StreamIO& buffer; + + public: + void WriteShiftCenterBegin(detail::ShiftInfo& shift) { + if (shift.type == detail::ShiftInfo::ShiftType::CenterRight || shift.type == detail::ShiftInfo::ShiftType::CenterLeft) { + std::int32_t shift_ = shift.size / 2; + if (shift.type == detail::ShiftInfo::ShiftType::CenterLeft) shift_ = (shift.size + 1) / 2; + ManipIO(buffer).pushback(shift.print.before, shift.size - shift_); + shift.size = shift_; + } + } + + void WriteShiftCenterEnd(detail::ShiftInfo& shift) { + if (shift.type == detail::ShiftInfo::ShiftType::CenterRight || shift.type == detail::ShiftInfo::ShiftType::CenterLeft) + return ManipIO(buffer).pushback(shift.print.after, shift.size); + } + + void write_shift_right_all(detail::ShiftInfo& shift) { + if (shift.type == detail::ShiftInfo::ShiftType::Right) return ManipIO(buffer).pushback(shift.print.before, shift.size); + } + + void WriteShiftLeftAll(detail::ShiftInfo& shift) { + if (shift.type == detail::ShiftInfo::ShiftType::Left) return ManipIO(buffer).pushback(shift.print.after, shift.size); + } + + void write_shift_begin(detail::ShiftInfo& shift) { + WriteShiftCenterBegin(shift); + return write_shift_right_all(shift); + } + + void write_shift_end(detail::ShiftInfo& shift) { + WriteShiftLeftAll(shift); + return WriteShiftCenterEnd(shift); + } + }; + + template + class ShiftReadManip { + public: + ShiftReadManip(Stream& buffer) : buffer(buffer) {} + + public: + Stream& buffer; + + public: + void ignore_shift_begin_space(detail::ShiftInfo& shift) { + if (shift.print.before_is_a_digit() == false) return; + if (shift.type == detail::ShiftInfo::ShiftType::Right || shift.type == detail::ShiftInfo::ShiftType::CenterLeft || + shift.type == detail::ShiftInfo::ShiftType::CenterRight) { + while (buffer.get() == ' ') { + Manip(buffer).forward(); + --shift.size; + } + } + } + + void ignore_shift_end(detail::ShiftInfo& shift) { + if (shift.type == detail::ShiftInfo::ShiftType::Left || shift.type == detail::ShiftInfo::ShiftType::CenterLeft || + shift.type == detail::ShiftInfo::ShiftType::CenterRight) { + while (buffer.get() == ' ' && shift.size > 0) { + Manip(buffer).forward(); + --shift.size; + } + } + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/utils/buffer_utils.hxx b/src/stream/fmt/buf/utils/buffer_utils.hxx new file mode 100644 index 00000000..48e67753 --- /dev/null +++ b/src/stream/fmt/buf/utils/buffer_utils.hxx @@ -0,0 +1,114 @@ +#pragma once + +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/manip_io.hxx" +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/write_manip.hxx" +#include "stream/fmt/buf/read_manip.hxx" + +#include "stream/fmt/buf/streamio_manager/dynamic_streamio_manager.hxx" +#include "stream/fmt/buf/streamio_manager/given_streamio_manager.hxx" +#include "stream/fmt/buf/streamio_manager/static_streamio_manager.hxx" + +namespace stream::fmt::buf { + template + class UtilsManip { + public: + constexpr inline UtilsManip(Stream& buffer_) noexcept : buffer(buffer_) {} + + public: + Stream& buffer; + + using TConstChar = std::remove_const_t; + + public: + template + std::optional get_word_from_list(const std::basic_string_view (&data)[SIZE]) { + for (std::size_t idx = 0; idx < SIZE; ++idx) { + bool found = TestManip(buffer).is_same_forward(data[idx]); + if (found) return idx; + } + return std::nullopt; + } + + // TODO: use static map ? + template + using DictPairs = std::pair, T>; + + template + T get_word_from_dict_pairs(const DictPairs (&data)[SIZE]) { + for (std::size_t idx = 0; idx < SIZE; ++idx) { + bool found = TestManip(buffer).is_same_forward(data[idx].first); + if (found) return data[idx].second; + } + throw std::runtime_error("fmt error: Specifiers_Invalid"); + } + }; + + namespace utils { + template + static void parse_escaped_quoted_string(buf::Stream& buffer, buf::StreamIO& stringOut) { + buf::TestManip(buffer).skip_one_of('"'); + while (buffer.is_end_of_string() == false) { + auto view = buf::TestManip(buffer).view_until('"', '\\'); + buf::WriteManip(stringOut).fast_write_sv(view); + + if (buf::TestAccess(buffer).is_equal_to('"')) { + break; + } + + buf::TestManip(buffer).skip_one_of('\\'); + switch (buffer.get()) { + // TODO : Do all others escape char + case '"': + buf::ManipIO(stringOut).pushback('"'); + break; + case 't': + buf::ManipIO(stringOut).pushback('\t'); + break; + case 'r': + buf::ManipIO(stringOut).pushback('\r'); + break; + case 'n': + buf::ManipIO(stringOut).pushback('\n'); + break; + default: + break; + } + } + buf::TestManip(buffer).skip_one_of('"'); + } + + template + static void format_escaped_quoted_string(buf::StreamIO& buffer, buf::Stream& string_in) { + buf::ManipIO(buffer).pushback('"'); + while (string_in.is_end_of_string() == false) { + auto view = buf::TestManip(string_in).view_until('\\'); + buf::WriteManip(buffer).fast_write_sv(view); + + if (string_in.is_end_of_string()) break; + + // TODO + buf::TestManip(string_in).skip_one_of('\\'); + switch (string_in.get()) { + // TODO : Do all others escape char + case '"': + buf::ManipIO(buffer).pushback('"'); + break; + case 't': + buf::ManipIO(buffer).pushback('\t'); + break; + case 'r': + buf::ManipIO(buffer).pushback('\r'); + break; + case 'n': + buf::ManipIO(buffer).pushback('\n'); + break; + default: + break; + } + } + buf::ManipIO(buffer).pushback('"'); + } + }; // namespace utils +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/buf/write_manip.hxx b/src/stream/fmt/buf/write_manip.hxx new file mode 100644 index 00000000..d2c591ec --- /dev/null +++ b/src/stream/fmt/buf/write_manip.hxx @@ -0,0 +1,165 @@ +#pragma once + +#include "stream.hxx" +#include "manip.hxx" +#include "test_manip.hxx" +#include "manip_io.hxx" + +#include +#include +#include +#include + +namespace stream::fmt::buf { + class WriteUtils { + public: + template + static std::int32_t get_number_of_digit_dec(T value) { + if constexpr (std::numeric_limits::is_signed) { + if (value < 0) value = -value; + } + std::int32_t nb = 0; + while (true) { + if (value < 10) + return nb + 1; + else if (value < 100) + return nb + 2; + else if (value < 1000) + return nb + 3; + else if (value < 10000) + return nb + 4; + else { + value /= static_cast(10000); + nb += 4; + } + } + } + }; + + template + class WriteManip { + public: + constexpr inline WriteManip(StreamIO& buffer) noexcept : buffer(buffer) {} + + public: + StreamIO& buffer; + + public: + static constexpr TChar BIN[2] = {'0', '1'}; + static constexpr TChar OCT[8] = {'0', '1', '2', '3', '4', '5', '6', '7'}; + static constexpr TChar UPPER_HEX[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'b', 'C', 'D', 'E', 'F'}; + static constexpr TChar LOWER_HEX[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + public: + template + requires std::is_integral_v + constexpr void fast_write_integer(T i) { + ManipIO manip(buffer); + + if (i == 0) { + manip.pushback('0'); + return; + } + + if constexpr (std::is_signed_v) { + if (i < 0) { + manip.pushback('-'); + i = -i; + } + } + + std::int32_t nb_digit = WriteUtils::get_number_of_digit_dec(i); + manip.forward(nb_digit); + while (i > 0) { + Manip(buffer).backward_force(); + ManipIO(buffer).set(i % 10 + '0'); + i /= 10; + } + manip.forward(nb_digit); + } + + public: + template + requires std::is_floating_point_v + constexpr void fast_write_float(T i, std::int32_t float_precision = 2) { + ManipIO manip(buffer); + + if (i == 0) { + manip.pushback('0'); + return; + } + if (i < 0) { + manip.pushback('-'); + i = -i; + } + + T k = std::trunc(i); + i = i - k; + std::int32_t nb_digit = WriteUtils::get_number_of_digit_dec(k); + manip.forward(nb_digit); + std::int32_t nb_digit_ = nb_digit; + while (nb_digit_ > 0) { + Manip(buffer).backward_force(); + buffer.set(char(std::fmod(k, 10)) + '0'); + k /= 10; + nb_digit_--; + } + manip.forward(nb_digit); + manip.pushback('.'); + + while (float_precision-- >= 0) { + TChar intPart = static_cast(std::trunc(i *= 10)); + manip.pushback(intPart + '0'); + i -= intPart; + } + } + + public: + constexpr void fast_write_sv(const std::basic_string_view sv) { + if (sv.size() == 0) { + return; + } + + if (ManipIO(buffer).reserve(sv.size()) == false) { + return fast_write_sv(sv.substr(0, buffer.get_buffer_remaining_size())); + } + + std::copy(sv.begin(), sv.end(), buffer.current_pos); + buffer.current_pos += sv.size(); + } + + template + void fast_write_literal(const TChar (&str)[SIZE]) { + std::size_t size = SIZE; + while (str[size - 1] == 0) { + --size; + } + return fast_write_sv(std::basic_string_view(str, size)); + } + + public: + void basic_write_type(const std::basic_string_view str) { + return fast_write_sv(str); + } + template + void basic_write_type(const TChar (&str)[SIZE]) { + return fast_write_literal(str); + } + template + requires std::is_integral_v + void basic_write_type(T t) { + return fast_write_integer(t); + } + template + requires std::is_floating_point_v + void basic_write_type(T t) { + return fast_write_float(t); + } + + template + void basic_write_type(Type&& type, Rest&&... rest) { + basic_write_type(type); + if constexpr (sizeof...(rest) > 0) basic_write_type(std::forward(rest)...); + } + }; +} // namespace stream::fmt::buf diff --git a/src/stream/fmt/context/basic_context/basic_args_interface.hxx b/src/stream/fmt/context/basic_context/basic_args_interface.hxx new file mode 100644 index 00000000..9b15f72e --- /dev/null +++ b/src/stream/fmt/context/basic_context/basic_args_interface.hxx @@ -0,0 +1,87 @@ +#pragma once + +#include "stream/fmt/detail/convert_traits.hxx" +#include "stream/fmt/detail/prelude.hxx" +#include "stream/fmt/buf/stream.hxx" + +#include +#include +#include + +namespace stream::fmt::context { + template + class BasicContext; + + template + class ContextExecutor; +} // namespace stream::fmt::context + +namespace stream::fmt::detail { + struct PointerID { + const std::type_info& type_info; + void* ptr = nullptr; + }; + + template + class BasicArgsInterface { + public: + BasicArgsInterface() {} + virtual ~BasicArgsInterface() = default; + + public: + virtual size_t size() = 0; + + public: + virtual PointerID get_pointerid_at(std::int32_t idx) = 0; + virtual void run_type_at(std::int32_t idx) = 0; + virtual std::optional get_index_of_current_named_arg(buf::StreamView& format) = 0; + virtual typename std::basic_string_view get_string_at(std::int32_t idx) = 0; + virtual std::int64_t get_int_at(std::int32_t idx) = 0; + + public: + template + const T* get_type_at(std::int32_t idx) { + PointerID ptr = get_pointerid_at(idx); + if (ptr.type_info != typeid(T)) { + throw std::runtime_error("fmt error: ArgsInterface_InvalidTypeID"); + } + return reinterpret_cast(ptr.ptr); + } + + template + void run_func_from_type_at(std::int32_t idx, std::function func) { + const T* value = get_type_at(idx); + func(*value); + } + }; + + template + class EmptyContextArgsTupleInterface : public BasicArgsInterface { + public: + EmptyContextArgsTupleInterface() {} + ~EmptyContextArgsTupleInterface() override = default; + + public: + size_t size() override { + return 0; + } + + public: + PointerID get_pointerid_at(std::int32_t) override { + throw std::runtime_error("fmt error: ArgsInterface_Unavailble"); + } + PointerID run_type_at(std::int32_t) override { + throw std::runtime_error("fmt error: ArgsInterface_Unavailble"); + } + std::optional get_index_of_current_named_arg(buf::StreamView&) override { + throw std::runtime_error("fmt error: ArgsInterface_Unavailble"); + return std::nullopt; + } + std::basic_string_view get_string_at(std::int32_t) override { + throw std::runtime_error("fmt error: ArgsInterface_Unavailble"); + } + std::int64_t get_int_at(std::int32_t) override { + throw std::runtime_error("fmt error: ArgsInterface_Unavailble"); + } + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/basic_context/basic_context.hxx b/src/stream/fmt/context/basic_context/basic_context.hxx new file mode 100644 index 00000000..65fc73b1 --- /dev/null +++ b/src/stream/fmt/context/basic_context/basic_context.hxx @@ -0,0 +1,104 @@ +#pragma once + +#include "stream/fmt/detail/convert_traits.hxx" +#include "stream/fmt/detail/prelude.hxx" +#include "stream/fmt/detail/specifiers.hxx" + +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/manip.hxx" +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/read_manip.hxx" + +#include "basic_args_interface.hxx" + +#include "text_properties_executor.hxx" +#include "text_properties_manager.hxx" + +namespace stream::fmt::context { + template + class BasicContext; + + template + class ContextExecutor { + public: + using TChar = CharType; + + public: + ContextExecutor(detail::ITextPropertiesExecutor& text_properties_executor) : data{}, text_manager{text_properties_executor} {} + virtual ~ContextExecutor() = default; + + public: + virtual void exec_settings() = 0; + virtual void exec_raw_string(std::basic_string_view) = 0; + + BasicContext& get_context() { + return *reinterpret_cast*>(context); + } + + public: + detail::FormatData data; + detail::TextPropertiesManager text_manager; + + void* context = nullptr; + }; + + template + class BasicContext { + public: + using TChar = CharType; + + public: + BasicContext(ContextExecutor& executor, buf::StreamView fmtstream, detail::BasicArgsInterface& args_interface); + virtual ~BasicContext(); + + public: + ContextExecutor& executor; + + buf::StreamView fmtstream; + detail::BasicArgsInterface& args_interface; + std::int32_t values_index; + + private: + void* old_context_attached = nullptr; + + public: + void run(); + + protected: + void parse_variable(std::int32_t format_idx); + void parse(); + }; +} // namespace stream::fmt::context + +namespace stream::fmt::context { + template + BasicContext::BasicContext(ContextExecutor& executor, buf::StreamView format, detail::BasicArgsInterface& args_interface) + : executor(executor), fmtstream{format}, args_interface{args_interface}, values_index{0} { + old_context_attached = executor.context; + executor.context = this; + } + + template + BasicContext::~BasicContext() { + executor.context = old_context_attached; + } + + template + void BasicContext::run() { + while (!fmtstream.is_end_of_string()) { + const TChar* begin_continuous_string = fmtstream.current_pos; + std::size_t size_continuous_string = 0; + while (fmtstream.is_end_of_string() == false && buf::TestAccess(fmtstream).is_equal_to('{') == false) { + ++size_continuous_string; + buf::Manip(fmtstream).forward(); + } + executor.exec_raw_string(std::basic_string_view(begin_continuous_string, size_continuous_string)); + + if (fmtstream.is_end_of_string() == false && buf::TestAccess(fmtstream).is_equal_to('{')) { + parse(); + } + } + } +} // namespace stream::fmt::context + +#include "basic_context_parse_impl.hxx" diff --git a/src/stream/fmt/context/basic_context/basic_context_parse_formatdata.hxx b/src/stream/fmt/context/basic_context/basic_context_parse_formatdata.hxx new file mode 100644 index 00000000..5f30329e --- /dev/null +++ b/src/stream/fmt/context/basic_context/basic_context_parse_formatdata.hxx @@ -0,0 +1,212 @@ +#pragma once + +#include "stream/fmt/buf/manip.hxx" +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/write_manip.hxx" +#include "stream/fmt/buf/read_manip.hxx" +#include "stream/fmt/buf/fmt_manip_io.hxx" +#include "stream/fmt/buf/fmt_read_manip.hxx" + +#include "basic_context_parse_getindex.hxx" + +namespace stream::fmt::detail { + namespace { + template + std::basic_string_view parse_next_override_format_data(Executor& executor, buf::StreamView& stream, + detail::FormatData& data) { + buf::TestAccess access(stream); + buf::TestManip manip(stream); + + manip.is_equal_to_forward(':'); + manip.ignore_every_spaces(); + + const typename Executor::TChar* begin = stream.current_pos; + int scopes = 0; + while (buf::FMTParamsManip(stream).is_end_of_parameter() == false || scopes > 0) { + manip.GoTo('\'', '}', '{'); + if (access.is_equal_to('\'')) { + buf::Manip(stream).forward(); + manip.go_to_forward('\''); + } else if (access.is_equal_to('{')) { + buf::Manip(stream).forward(); + scopes++; + } else if (scopes > 0 && access.is_equal_to('}')) { + buf::Manip(stream).forward(); + scopes--; + } + } + const typename Executor::TChar* end = stream.current_pos; + return std::basic_string_view(begin, end - begin); + } + + template + void parse_format_data_base(Executor& executor, buf::StreamView& stream, detail::FormatData& data) { + buf::TestAccess access(stream); + + if (access.is_equal_to('C')) { + buf::Manip(stream).forward(); + executor.text_manager.parse_color(executor.get_context(), stream); + } else if (access.is_equal_to('S')) { + buf::Manip(stream).forward(); + executor.text_manager.parse_style(executor.get_context(), stream); + buf::Manip(stream).forward(); + } else if (access.is_equal_to('F')) { + executor.text_manager.parse_front(executor.get_context(), stream); + } + + else if (access.is_equal_to('K')) { + buf::Manip(stream).forward(); + data.keep_new_style = true; + } + } + + template + void parse_format_data_special_shift_type(Executor& executor, buf::StreamView& stream, detail::FormatData& data, + const detail::ShiftInfo::ShiftType type) { + data.shift.type = type; + data.shift.size = format_read_parameter(executor, stream, -1); + if (buf::TestAccess(stream).is_equal_to(':')) { + buf::Manip(stream).forward(); + data.shift.print.before = stream.get(); + data.shift.print.after = data.shift.print.before; + buf::Manip(stream).forward(); + if (buf::TestAccess(stream).is_equal_to('|')) { + buf::Manip(stream).forward(); + data.shift.print.after = stream.get(); + buf::Manip(stream).forward(); + } + } + } + + template + bool parse_format_data_special(Executor& executor, buf::StreamView& stream, detail::FormatData& data) { + buf::TestAccess access(stream); + buf::TestManip manip(stream); + + bool local_spec = false; + + if (access.is_equal_to('{')) { + local_spec = true; + buf::Manip(stream).forward(); + std::optional format_index = get_format_index(executor, stream); + + bool ableToapply = false; + if (format_index.has_value()) { + auto applyFormatData = executor.get_context().args_interface.template get_type_at>(format_index.value()); + ableToapply |= data.testapply(applyFormatData); + auto applyFormatSpecifier = executor.get_context().args_interface.template get_type_at>(format_index.value()); + ableToapply |= data.testapply(applyFormatSpecifier); + auto applyIntegerPrintBase = executor.get_context().args_interface.template get_type_at(format_index.value()); + ableToapply |= data.testapply(applyIntegerPrintBase); + auto applyShiftInfo = executor.get_context().args_interface.template get_type_at(format_index.value()); + ableToapply |= data.testapply(applyShiftInfo); + } + + if (not ableToapply) { + throw std::runtime_error("fmt error: Context_CannotapplyType"); + } + manip.skip_one_of('}'); + } + + if (access.is_equal_to('#')) { + local_spec = true; + buf::Manip(stream).forward(); + data.prefix_suffix = true; + } + + bool is_integer_spec = access.is_equal_to('d', 'b', 'b', 'o', 'O', 'x', 'X'); + is_integer_spec = is_integer_spec && (stream.get_buffer_remaining_size() == 1 || (buf::Access(stream).get_next() > 'z' && buf::Access(stream).get_next() < 'a')); + if (is_integer_spec) { + local_spec = true; + data.integer_print = static_cast(stream.get()); + buf::Manip(stream).forward(); + } + + if (access.is_equal_to('.')) { + local_spec = true; + buf::Manip(stream).forward(); + data.float_precision = format_read_parameter(executor, stream, -1); + } + + if (access.is_equal_to('>')) { + local_spec = true; + buf::Manip(stream).forward(); + parse_format_data_special_shift_type(executor, stream, data, detail::ShiftInfo::ShiftType::Right); + } else if (access.is_equal_to('<')) { + buf::Manip(stream).forward(); + parse_format_data_special_shift_type(executor, stream, data, detail::ShiftInfo::ShiftType::Left); + } else if (access.is_equal_to('^')) { + buf::Manip(stream).forward(); + if (access.is_equal_to('<')) { + buf::Manip(stream).forward(); + parse_format_data_special_shift_type(executor, stream, data, detail::ShiftInfo::ShiftType::CenterLeft); + } else { + manip.ignore_one_of('>'); + parse_format_data_special_shift_type(executor, stream, data, detail::ShiftInfo::ShiftType::CenterRight); + } + } + + if (access.is_equal_to(':')) { + local_spec = true; + buf::Manip(stream).forward(); + data.next_override = parse_next_override_format_data(executor, stream, data); + } + + return local_spec; + } + + template + void parse_format_data_custom(Executor& executor, buf::StreamView& stream, detail::FormatData& data) { + buf::TestAccess access(stream); + buf::TestManip manip(stream); + + std::basic_string_view name = manip.view_exec([&] { buf::FMTParamsManip(stream).param_go_to(' ', '=', '\'', '{', ','); }); + buf::FMTParamsManip(stream).param_go_to('=', '\'', '{', ','); + manip.ignore_one_of('='); + manip.ignore_every_spaces(); + + if (access.is_equal_to('\'')) { + buf::Manip(stream).forward(); + std::basic_string_view value = buf::TestManip(stream).view_until('\''); + data.specifiers.concat(detail::FormatSpecifier{name, value}); + buf::Manip(stream).forward(); + } else if (access.is_a_digit()) { + std::int32_t value = 0; + buf::ReadManip(stream).fast_read_integer(value); + data.specifiers.concat(detail::FormatSpecifier{name, value}); + } else if (access.is_equal_to('{')) { + buf::Manip(stream).forward(); + std::optional idx = get_format_index(executor, stream); + // TODO / FIXME + // data.specifiers.concat(detail::FormatSpecifier{name, GetTypeAtIndexAuto(idx)}); + manip.skip_one_of('}'); + } else if (access.is_equal_to(',', '}')) { + data.specifiers.concat(detail::FormatSpecifier{name}); + } + } + } // namespace + + template + detail::FormatData parse_format_data(Executor& executor, buf::StreamView& stream) { + detail::FormatData data; + + buf::TestAccess access(stream); + + data.has_spec = true; + while (stream.is_end_of_string() == false && buf::FMTParamsManip(stream).is_end_of_parameter() == false) { + buf::TestManip(stream).ignore_every_spaces(); + + if (access.is_upper_case()) { + parse_format_data_base(executor, stream, data); + } else if (parse_format_data_special(executor, stream, data)) { + } else { + parse_format_data_custom(executor, stream, data); + } + + buf::FMTParamsManip(stream).param_go_to(','); + buf::TestManip(stream).ignore_one_of(','); + } + + return data; + } +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/basic_context/basic_context_parse_getindex.hxx b/src/stream/fmt/context/basic_context/basic_context_parse_getindex.hxx new file mode 100644 index 00000000..b43014e7 --- /dev/null +++ b/src/stream/fmt/context/basic_context/basic_context_parse_getindex.hxx @@ -0,0 +1,113 @@ +#pragma once + +#include "stream/fmt/buf/manip.hxx" +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/write_manip.hxx" +#include "stream/fmt/buf/read_manip.hxx" +#include "stream/fmt/buf/fmt_manip_io.hxx" +#include "stream/fmt/buf/fmt_read_manip.hxx" + +namespace stream::fmt::context { + namespace { + template + std::optional get_format_index_number(Executor& executor, buf::StreamView& stream) { + std::int32_t index = -1; + buf::ReadManip(stream).fast_read_integer(index); + if (buf::TestAccess(stream).is_equal_to(':') || buf::TestAccess(stream).is_equal_to('}')) { + if (index >= 0 && index < executor.get_context().args_interface.size()) { + return index; + } + } + return std::nullopt; + } + template + std::optional get_format_index_name(Executor& executor, buf::StreamView& stream) { + std::optional index = executor.get_context().args_interface.get_index_of_current_named_arg(stream); + if (index.has_value() == false) return std::nullopt; + if (buf::TestAccess(stream).is_equal_to(':') || buf::TestAccess(stream).is_equal_to('}')) { + if (index >= 0 && index < executor.get_context().args_interface.size()) { + return index; + } + } + return std::nullopt; + } + template + std::optional get_format_index_sub_index(Executor& executor, buf::StreamView& stream) { + buf::TestAccess access(stream); + buf::TestManip manip(stream); + + if (access.is_equal_to('{')) { + buf::Manip(stream).forward(); + std::optional rec_index = get_format_index(executor, stream); + if (rec_index.has_value() == false) { + return std::nullopt; + } + if (access.is_equal_to('}') && rec_index >= 0 && rec_index < executor.get_context().args_interface.size()) { + buf::Manip(stream).forward(); + manip.ignore_every_spaces(); + if (access.is_equal_to(':', '}')) { + std::int32_t final_rec_index = (std::int32_t)executor.get_context().args_interface.get_int_at(rec_index.value()); + if (final_rec_index >= 0 && final_rec_index < executor.get_context().args_interface.size()) { + return final_rec_index; + } + } + } + } + return std::nullopt; + } + } // namespace + + template + std::optional get_format_index(Executor& executor, buf::StreamView& stream) { + buf::TestAccess access(stream); + + // I : if there is no number specified : ':' or '}' + if (access.is_equal_to(':') || access.is_equal_to('}')) + if (executor.get_context().values_index < executor.get_context().args_interface.size()) { + return executor.get_context().values_index++; + } + + // II: A number(idx) + if (access.is_a_digit()) { + return get_format_index_number(executor, stream); + } + + // III : A name + if (access.is_lower_case() || access.is_upper_case()) { + return get_format_index_name(executor, stream); + } + + // VI : { which is a idx to an argument + if (access.is_equal_to('{')) { + const typename Executor::TChar* oldPos = stream.current_pos; + std::optional res = get_format_index_sub_index(executor, stream); + if (res.has_value() == false) { + stream.current_pos = oldPos; + return std::nullopt; + } + return res; + } + + return std::nullopt; + } + + template + T format_read_parameter(Executor& executor, buf::StreamView& stream, const T& default_value) { + if (!buf::TestAccess(stream).is_equal_to('{')) { + T t; + buf::ReadManip(stream).fast_read_integer(t); + return t; + } + + // SubIndex + buf::TestManip(stream).skip_one_of('{'); + std::optional format_idx = get_format_index(executor, stream); + if constexpr (std::is_convertible_v) { + return executor.get_context().args_interface.get_int_at(format_idx.value()); + } else if constexpr (std::is_convertible_v>) { + return executor.get_context().args_interface.get_string_at(format_idx.value()); + } + + throw std::runtime_error("fmt error: Context_ArgumentIndexExpected"); + } +} // namespace stream::fmt::context diff --git a/src/stream/fmt/context/basic_context/basic_context_parse_impl.hxx b/src/stream/fmt/context/basic_context/basic_context_parse_impl.hxx new file mode 100644 index 00000000..f7e8e896 --- /dev/null +++ b/src/stream/fmt/context/basic_context/basic_context_parse_impl.hxx @@ -0,0 +1,54 @@ +#pragma once + +#include "basic_context.hxx" + +#include "stream/fmt/buf/manip.hxx" +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/write_manip.hxx" +#include "stream/fmt/buf/read_manip.hxx" +#include "stream/fmt/buf/fmt_manip_io.hxx" +#include "stream/fmt/buf/fmt_read_manip.hxx" + +#include "basic_context_parse_formatdata.hxx" + +namespace stream::fmt::context { + template + void BasicContext::parse_variable(std::int32_t format_idx) { + detail::FormatData saveFormatData = executor.data; + executor.data = detail::FormatData{}; + detail::TextProperties::Properties saveTextProperties = executor.text_manager.save(); + + if (buf::TestAccess(fmtstream).is_equal_to(':', '{')) { + buf::Manip(fmtstream).forward(); + executor.data = detail::parse_format_data(executor, fmtstream); + } + + args_interface.run_type_at(format_idx); + + if (executor.data.keep_new_style == false) { + executor.text_manager.reload(saveTextProperties); + } + + executor.data = saveFormatData; + } + + template + void BasicContext::parse() { + buf::Manip(fmtstream).forward(); // Ignore { + + if (buf::TestAccess(fmtstream).is_upper_case()) { + executor.data = detail::parse_format_data(executor, fmtstream); + return buf::FMTParamsManip(fmtstream).param_go_to_forward(); // Ignore } + } + + std::optional format_idx = get_format_index(executor, fmtstream); + if (format_idx.has_value()) { + if (format_idx >= 0 && format_idx < args_interface.size()) { + parse_variable(format_idx.value()); + return buf::FMTParamsManip(fmtstream).param_go_to_forward(); // Ignore } + } + } + + executor.exec_raw_string("{"); + } +} // namespace stream::fmt::context diff --git a/src/stream/fmt/context/basic_context/text_properties_executor.hxx b/src/stream/fmt/context/basic_context/text_properties_executor.hxx new file mode 100644 index 00000000..19683342 --- /dev/null +++ b/src/stream/fmt/context/basic_context/text_properties_executor.hxx @@ -0,0 +1,46 @@ +#pragma once + +#include "stream/fmt/detail/prelude.hxx" +#include "stream/fmt/text_properties/text_properties.hxx" + +namespace stream::fmt::detail { + class ITextPropertiesExecutor { + public: + virtual ~ITextPropertiesExecutor() = default; + + public: + virtual void link_to_executor(void* executor) = 0; + + public: + virtual void all_properties_reset() = 0; + + public: + virtual void reset_color() = 0; + virtual void execute_color(const TextProperties::TextColor::BasicColorFG& t) = 0; + virtual void execute_color(const TextProperties::TextColor::BasicColorBG& t) = 0; + virtual void execute_color(const TextProperties::TextColor::BasicColor& t) = 0; + virtual void execute_color(const TextProperties::TextColor::Color24bFG& t) = 0; + virtual void execute_color(const TextProperties::TextColor::Color24bBG& t) = 0; + virtual void execute_color(const TextProperties::TextColor::Color24b& t) = 0; + virtual void execute_color(const TextProperties::TextColor::ColorCubeFG& t) = 0; + virtual void execute_color(const TextProperties::TextColor::ColorCubeBG& t) = 0; + virtual void execute_color(const TextProperties::TextColor::ColorCube& t) = 0; + + public: + virtual void reset_front() = 0; + virtual void execute_front(const TextProperties::TextFront::FrontID& t) = 0; + + public: + virtual void reset_style() = 0; + virtual void execute_style(const TextProperties::TextStyle::Intensity& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::Italic& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::Underline& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::UnderlineColor::Color& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::UnderlineColor::ColorCube& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::UnderlineColor::Color24b& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::Blink& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::Inverted& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::Ideogram& t) = 0; + virtual void execute_style(const TextProperties::TextStyle::Script& t) = 0; + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/basic_context/text_properties_manager.cxx b/src/stream/fmt/context/basic_context/text_properties_manager.cxx new file mode 100644 index 00000000..0c32d3e4 --- /dev/null +++ b/src/stream/fmt/context/basic_context/text_properties_manager.cxx @@ -0,0 +1,172 @@ +#include "text_properties_manager.hxx" + +namespace stream::fmt::detail { + void TextPropertiesapplyManager::reload_color_fg(const TextProperties::TextColor::ColorFG& target) { + if (target.type != current_context_properties_.color.fg.type) { + switch (target.type) { + case TextProperties::TextColor::ColorType::BasicColor: { + apply_color(target.data.basic_color); + return; + } + case TextProperties::TextColor::ColorType::ColorCube: { + apply_color(target.data.color_cube); + return; + } + case TextProperties::TextColor::ColorType::Color24b: { + apply_color(target.data.color24b); + return; + } + } + } else { + switch (target.type) { + case TextProperties::TextColor::ColorType::BasicColor: + if (current_context_properties_.color.fg.data.basic_color != target.data.basic_color) { + { + apply_color(target.data.basic_color); + } + return; + } + break; + case TextProperties::TextColor::ColorType::ColorCube: + if (current_context_properties_.color.fg.data.color_cube != target.data.color_cube) { + { + apply_color(target.data.color_cube); + } + return; + } + break; + case TextProperties::TextColor::ColorType::Color24b: + if (current_context_properties_.color.fg.data.color24b != target.data.color24b) { + { + apply_color(target.data.color24b); + } + return; + } + break; + } + } + } + + void TextPropertiesapplyManager::reload_color_bg(const TextProperties::TextColor::ColorBG& target) { + if (target.type != current_context_properties_.color.bg.type) { + switch (target.type) { + case TextProperties::TextColor::ColorType::BasicColor: { + apply_color(target.data.basic_color); + return; + } + case TextProperties::TextColor::ColorType::ColorCube: { + apply_color(target.data.color_cube); + return; + } + case TextProperties::TextColor::ColorType::Color24b: { + apply_color(target.data.color24b); + return; + } + } + } else { + switch (target.type) { + case TextProperties::TextColor::ColorType::BasicColor: + if (current_context_properties_.color.bg.data.basic_color != target.data.basic_color) { + { + apply_color(target.data.basic_color); + } + return; + } + break; + case TextProperties::TextColor::ColorType::ColorCube: + if (current_context_properties_.color.bg.data.color_cube != target.data.color_cube) { + { + apply_color(target.data.color_cube); + } + return; + } + break; + case TextProperties::TextColor::ColorType::Color24b: + if (current_context_properties_.color.bg.data.color24b != target.data.color24b) { + { + apply_color(target.data.color24b); + } + return; + } + break; + } + } + } + + // NOLINTBEGIN(readability-function-cognitive-complexity) + void TextPropertiesapplyManager::reload_style(const TextProperties::TextStyle::Style& target) { + if (target.intensity != current_context_properties_.style.intensity) { + apply_style(target.intensity); + current_context_properties_.style.intensity = target.intensity; + } + if (target.italic != current_context_properties_.style.italic) { + apply_style(target.italic); + current_context_properties_.style.italic = target.italic; + } + if (target.blink != current_context_properties_.style.blink) { + apply_style(target.blink); + current_context_properties_.style.blink = target.blink; + } + if (target.inverted != current_context_properties_.style.inverted) { + apply_style(target.inverted); + current_context_properties_.style.inverted = target.inverted; + } + if (target.ideogram != current_context_properties_.style.ideogram) { + apply_style(target.ideogram); + current_context_properties_.style.ideogram = target.ideogram; + } + if (target.script != current_context_properties_.style.script) { + apply_style(target.script); + current_context_properties_.style.script = target.script; + } + + if (target.underline != current_context_properties_.style.underline) { + apply_style(target.underline); + current_context_properties_.style.underline = target.underline; + } + + if (target.underline_color.type != current_context_properties_.style.underline_color.type) { + switch (target.underline_color.type) { + case TextProperties::TextStyle::UnderlineColor::ColorType::Default: + apply_style(TextProperties::TextStyle::UnderlineColor::ColorCube{TextProperties::TextStyle::UnderlineColor::ColorCube::Default}); + break; + case TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube: + apply_style(target.underline_color.data.color_cube); + current_context_properties_.style.underline_color.data.color_cube = target.underline_color.data.color_cube; + break; + case TextProperties::TextStyle::UnderlineColor::ColorType::Color24b: + apply_style(target.underline_color.data.color24b); + current_context_properties_.style.underline_color.data.color24b = target.underline_color.data.color24b; + break; + } + current_context_properties_.style.underline_color.type = target.underline_color.type; + } else { + switch (target.underline_color.type) { + case TextProperties::TextStyle::UnderlineColor::ColorType::Default: + break; + case TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube: + if (current_context_properties_.style.underline_color.data.color_cube != target.underline_color.data.color_cube) { + apply_style(target.underline_color.data.color_cube); + current_context_properties_.style.underline_color.data.color_cube = target.underline_color.data.color_cube; + } + break; + case TextProperties::TextStyle::UnderlineColor::ColorType::Color24b: + if (current_context_properties_.style.underline_color.data.color24b != target.underline_color.data.color24b) { + apply_style(target.underline_color.data.color24b); + current_context_properties_.style.underline_color.data.color24b = target.underline_color.data.color24b; + } + break; + } + } + } + // NOLINTEND(readability-function-cognitive-complexity) + + void TextPropertiesapplyManager::reload_front(const TextProperties::TextFront::Front& target) { + if (current_context_properties_.front == target) { + return; + } + + apply_front(target.current_id); + current_context_properties_.front = target; + } +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/basic_context/text_properties_manager.hxx b/src/stream/fmt/context/basic_context/text_properties_manager.hxx new file mode 100644 index 00000000..d2898c24 --- /dev/null +++ b/src/stream/fmt/context/basic_context/text_properties_manager.hxx @@ -0,0 +1,201 @@ +#pragma once + +#include "stream/fmt/detail/prelude.hxx" +#include "text_properties_executor.hxx" +#include "basic_args_interface.hxx" +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/utils/buffer_utils.hxx" + +namespace stream::fmt::detail { + class TextPropertiesapplyManager { + public: + TextPropertiesapplyManager(ITextPropertiesExecutor& text_properties_executor) : text_properties_executor_{text_properties_executor}, current_context_properties_{} {} + + void terminate() { + return reload_default(); + } + + public: + template + requires detail::text_properties_color_can_apply + void apply_color(const T& modif) { + current_context_properties_.color.apply(modif); + return text_properties_executor_.execute_color(modif); + } + template + requires detail::text_properties_style_can_apply + void apply_style(const T& modif) { + current_context_properties_.style.apply(modif); + return text_properties_executor_.execute_style(modif); + } + template + requires detail::text_properties_front_can_apply + void apply_front(const T& modif) { + current_context_properties_.front.apply(modif); + return text_properties_executor_.execute_front(modif); + } + + void all_properties_reset() { + apply_color_reset(); + apply_style_reset(); + return apply_front_reset(); + } + void apply_color_reset() { + current_context_properties_.color.modify_reset(); + return text_properties_executor_.reset_color(); + } + void apply_style_reset() { + current_context_properties_.style.modify_reset(); + return text_properties_executor_.reset_style(); + } + void apply_front_reset() { + current_context_properties_.front.modify_reset(); + return text_properties_executor_.reset_front(); + } + + public: + detail::TextProperties::Properties save() { + return current_context_properties_; + } + + public: + void reload_default() { + reload_default_color(); + reload_default_style(); + return reload_default_front(); + } + void reload_default_color() { + reload_default_color_fg(); + return reload_default_color_bg(); + } + void reload_default_color_fg() { + return reload_color_fg(detail::TextProperties::TextColor::ColorFG{}); + } + void reload_default_color_bg() { + return reload_color_bg(detail::TextProperties::TextColor::ColorBG{}); + } + void reload_default_style() { + return reload_style(detail::TextProperties::TextStyle::Style{}); + } + void reload_default_front() { + return reload_front(detail::TextProperties::TextFront::Front{}); + } + + void reload(const detail::TextProperties::Properties& target) { + reload_color(target.color); + reload_style(target.style); + return reload_front(target.front); + } + void reload_color(const detail::TextProperties::TextColor::Color& target) { + reload_color_fg(target.fg); + return reload_color_bg(target.bg); + } + + void reload_color_fg(const detail::TextProperties::TextColor::ColorFG& target); + void reload_color_bg(const detail::TextProperties::TextColor::ColorBG& target); + void reload_style(const detail::TextProperties::TextStyle::Style& target); + void reload_front(const detail::TextProperties::TextFront::Front& target); + + public: + ITextPropertiesExecutor& get_text_properties_executor() { + return text_properties_executor_; + } + detail::TextProperties::Properties& get_current_context_properties() { + return current_context_properties_; + } + + protected: + ITextPropertiesExecutor& text_properties_executor_; + detail::TextProperties::Properties current_context_properties_; + + public: + template + requires detail::text_properties_color_can_apply + void ask_apply_color(const T& modif) { + if (current_context_properties_.color.need_modif(modif)) return apply_color(modif); + } + template + requires detail::text_properties_style_can_apply + void ask_apply_style(const T& modif) { + if (current_context_properties_.style.need_modif(modif)) return apply_style(modif); + } + template + requires detail::text_properties_front_can_apply + void ask_apply_front(const T& modif) { + if (current_context_properties_.front.need_modif(modif)) return apply_front(modif); + } + + void ask_apply_color(const detail::TextProperties::TextColor::BasicColor& modif) { + if (current_context_properties_.color.need_modif(modif.fg)) { + if (current_context_properties_.color.need_modif(modif.bg)) return apply_color(modif); + return apply_color(modif.fg); + } + if (current_context_properties_.color.need_modif(modif.fg)) return apply_color(modif.bg); + } + + void ask_apply_color(const detail::TextProperties::TextColor::ColorCube& modif) { + if (current_context_properties_.color.need_modif(modif.fg)) { + if (current_context_properties_.color.need_modif(modif)) return apply_color(modif); + return apply_color(modif.fg); + } + if (current_context_properties_.color.need_modif(modif.fg)) return apply_color(modif.bg); + } + + void ask_apply_color(const detail::TextProperties::TextColor::Color24b& modif) { + if (current_context_properties_.color.need_modif(modif.fg)) { + if (current_context_properties_.color.need_modif(modif)) return apply_color(modif); + return apply_color(modif.fg); + } + if (current_context_properties_.color.need_modif(modif.fg)) return apply_color(modif.bg); + } + + void ask_apply_color(const detail::TextProperties::TextColor::ColorFG& modif) { + return reload_color_fg(modif); + } + void ask_apply_color(const detail::TextProperties::TextColor::ColorBG& modif) { + return reload_color_bg(modif); + } + void ask_apply_color(const detail::TextProperties::TextColor::Color& modif) { + return reload_color(modif); + } + }; + + template + class TextPropertiesManager : public TextPropertiesapplyManager { + public: + TextPropertiesManager(ITextPropertiesExecutor& text_properties_executor) : TextPropertiesapplyManager(text_properties_executor) {} + + public: + void apply_color_on_index(context::BasicContext& context, std::int32_t index); + void apply_style_on_index(context::BasicContext& context, std::int32_t index); + void apply_front_on_index(context::BasicContext& context, std::int32_t index); + + public: + void parse_color(context::BasicContext& context, buf::StreamView& stream); + void parse_style(context::BasicContext& context, buf::StreamView& stream); + void parse_front(context::BasicContext& context, buf::StreamView& stream); + + private: + std::optional get_color_code(buf::StreamView& format, std::size_t base, std::size_t brightbase); + void parse_style_named(buf::StreamView& format); + TextProperties::TextStyle::UnderlineColor::ColorCube select_underlined_color_style(buf::StreamView& format); + }; +} // namespace stream::fmt::detail + +namespace stream::fmt::detail { + template + std::optional detail::TextPropertiesManager::get_color_code(buf::StreamView& format, std::size_t base, std::size_t brightbase) { + static constexpr std::string_view colorCode[] = {"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", " ", "default"}; + + bool bright = buf::TestManip(format).is_equal_to_forward('+'); + std::size_t step = bright ? brightbase : base; + std::optional color_code = buf::UtilsManip(format).get_word_from_list(colorCode); + if (color_code.has_value() == false) { + return std::nullopt; + } + return color_code.value() + step; + } +} // namespace stream::fmt::detail + +#include "text_properties_manager_impl.hxx" diff --git a/src/stream/fmt/context/basic_context/text_properties_manager_impl.hxx b/src/stream/fmt/context/basic_context/text_properties_manager_impl.hxx new file mode 100644 index 00000000..dcefb92f --- /dev/null +++ b/src/stream/fmt/context/basic_context/text_properties_manager_impl.hxx @@ -0,0 +1,226 @@ +#pragma once + +#include "stream/fmt/buf/manip.hxx" +#include "stream/fmt/buf/manip_io.hxx" +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/fmt_manip_io.hxx" +#include "stream/fmt/buf/utils/buffer_utils.hxx" + +namespace stream::fmt::detail { + template + void detail::TextPropertiesManager::apply_color_on_index(context::BasicContext& context, std::int32_t index) { + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextColor::Color& data) { this->reload_color(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextColor::BasicColorFG& data) { this->ask_apply_color(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextColor::BasicColorBG& data) { this->ask_apply_color(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextColor::ColorCubeFG& data) { this->ask_apply_color(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextColor::ColorCubeBG& data) { this->ask_apply_color(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextColor::Color24bFG& data) { this->ask_apply_color(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextColor::Color24bBG& data) { this->ask_apply_color(data); }); + } + + template + void detail::TextPropertiesManager::apply_front_on_index(context::BasicContext& context, std::int32_t index) { + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextFront::Front& data) { this->reload_front(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextFront::FrontID& data) { this->ask_apply_front(data); }); + } + + template + void detail::TextPropertiesManager::apply_style_on_index(context::BasicContext& context, std::int32_t index) { + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::Style& data) { return this->reload_style(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::Intensity& data) { return this->ask_apply_style(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::Italic& data) { return this->ask_apply_style(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::Underline& data) { return this->ask_apply_style(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::Blink& data) { return this->ask_apply_style(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::Inverted& data) { return this->ask_apply_style(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::Ideogram& data) { return this->ask_apply_style(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::Script& data) { return this->ask_apply_style(data); }); + + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::UnderlineColor::ColorCube& data) { this->ask_apply_style(data); }); + context.args_interface.template run_func_from_type_at( + index, [this](const detail::TextProperties::TextStyle::UnderlineColor::Color24b& data) { this->ask_apply_style(data); }); + } + + template + void detail::TextPropertiesManager::parse_color(context::BasicContext& context, buf::StreamView& stream) { + if (buf::TestAccess(stream).is_equal_to(':')) { + buf::Manip(stream).forward(); + buf::TestManip(stream).ignore_every_spaces(); + if (buf::TestAccess(stream).is_equal_to('{')) { + buf::Manip(stream).forward(); + std::optional idx = get_format_index(context.executor, stream); + if (idx.has_value() == false) { + } + apply_color_on_index(context, idx.value()); + buf::TestManip(stream).skip_one_of('}'); + } else { + std::optional color_fg = get_color_code(stream, static_cast(TextProperties::TextColor::BasicColorFG::BaseStep), + static_cast(TextProperties::TextColor::BasicColorFG::BaseBrightStep)); + buf::FMTParamsManip(stream).param_go_to('-', ','); + if (buf::TestAccess(stream).is_equal_to('-')) { + buf::Manip(stream).forward(); + buf::TestManip(stream).ignore_every_spaces(); + std::optional color_bg = get_color_code(stream, static_cast(TextProperties::TextColor::BasicColorBG::BaseStep), + static_cast(TextProperties::TextColor::BasicColorBG::BaseBrightStep)); + if (color_bg.has_value() && color_fg.has_value()) { + return ask_apply_color(detail::TextProperties::TextColor::BasicColor{static_cast(color_fg.value()), + static_cast(color_bg.value())}); + } else { + return reload_default_color(); + } + } else { + if (color_fg.has_value()) { + return ask_apply_color(static_cast(color_fg.value())); + } else { + return reload_default_color(); + } + } + } + } else { + return reload_default_color(); + } + } + + template + void detail::TextPropertiesManager::parse_style(context::BasicContext& context, buf::StreamView& stream) { + if (buf::TestAccess(stream).is_equal_to(':')) { + buf::Manip(stream).forward(); + if (!buf::TestAccess(stream).is_equal_to('}', ',')) { + bool loop = true; + while (loop) { + buf::TestManip(stream).ignore_every_spaces(); + if (buf::TestAccess(stream).is_equal_to('{')) { + buf::Manip(stream).forward(); + std::optional idx = get_format_index(context.executor, stream); + apply_style_on_index(context, idx.value()); + buf::TestManip(stream).skip_one_of('}'); + } else { + parse_style_named(stream); + } + buf::FMTParamsManip(stream).param_go_to('|', ','); + loop = buf::TestAccess(stream).is_equal_to('|'); + buf::Manip(stream).forward(); + buf::TestManip(stream).ignore_every_spaces(); + } + } else { + return reload_default_style(); + } + } else { + return reload_default_style(); + } + } + + template + void detail::TextPropertiesManager::parse_style_named(buf::StreamView& format) { + buf::UtilsManip utils(format); + + static constexpr std::pair, detail::TextProperties::TextStyle::Intensity> styleIntensity[] = { + { "bold", detail::TextProperties::TextStyle::Intensity::Bold}, + { "dim", detail::TextProperties::TextStyle::Intensity::Dim}, + {"n-intensity", detail::TextProperties::TextStyle::Intensity::Normal} + }; + + static constexpr std::pair, detail::TextProperties::TextStyle::Italic> styleItalic[] = { + { "italic", detail::TextProperties::TextStyle::Italic::enable}, + {"n-italic", detail::TextProperties::TextStyle::Italic::Disable} + }; + + // TODO: magic values + static constexpr typename std::pair, detail::TextProperties::TextStyle::Underline> styleUnderline[] = { + { "underlined", detail::TextProperties::TextStyle::Underline::Underlined}, + {"d-underlined", detail::TextProperties::TextStyle::Underline::DoubleUnerlined}, + {"n-underlined", detail::TextProperties::TextStyle::Underline::Disable}, + {"c-underlined", detail::TextProperties::TextStyle::Underline::SelectUnderlinedColor} + }; + + static constexpr typename std::pair, detail::TextProperties::TextStyle::Blink> styleBlink[] = { + {"slowblink", detail::TextProperties::TextStyle::Blink::SlowBlink}, + {"fastblink", detail::TextProperties::TextStyle::Blink::FastBlink}, + { "n-blink", detail::TextProperties::TextStyle::Blink::Disable} + }; + + static constexpr typename std::pair, detail::TextProperties::TextStyle::Inverted> styleInverted[] = { + { "inverted", detail::TextProperties::TextStyle::Inverted::enable}, + {"n-inverted", detail::TextProperties::TextStyle::Inverted::Disable}, + }; + + static constexpr typename std::pair, detail::TextProperties::TextStyle::Ideogram> styleIdeogram[] = { + { "i-underlined", detail::TextProperties::TextStyle::Ideogram::Underlined}, + {"i-d-underlined", detail::TextProperties::TextStyle::Ideogram::DoubleUnderlined}, + { "i-overlined", detail::TextProperties::TextStyle::Ideogram::Overlined}, + { "i-d-overlined", detail::TextProperties::TextStyle::Ideogram::DoubleOverlined}, + { "i-stress", detail::TextProperties::TextStyle::Ideogram::StressMarking}, + { "n-i", detail::TextProperties::TextStyle::Ideogram::AllDisable}, + }; + + static constexpr typename std::pair, detail::TextProperties::TextStyle::Script> styleScript[] = { + {"superscript", detail::TextProperties::TextStyle::Script::Superscript}, + { "subscript", detail::TextProperties::TextStyle::Script::Subscript}, + { "n-script", detail::TextProperties::TextStyle::Script::AllDisable} + }; + + std::uint8_t code = (std::uint8_t)buf::UtilsManip(format).get_word_from_dict_pairs(styleIntensity); + if (code != 255) return apply_style(detail::TextProperties::TextStyle::Intensity{code}); + code = (std::uint8_t)buf::UtilsManip(format).get_word_from_dict_pairs(styleItalic); + if (code != 255) return apply_style(detail::TextProperties::TextStyle::Italic{code}); + code = (std::uint8_t)buf::UtilsManip(format).get_word_from_dict_pairs(styleBlink); + if (code != 255) return apply_style(detail::TextProperties::TextStyle::Blink{code}); + code = (std::uint8_t)buf::UtilsManip(format).get_word_from_dict_pairs(styleInverted); + if (code != 255) return apply_style(detail::TextProperties::TextStyle::Inverted{code}); + code = (std::uint8_t)buf::UtilsManip(format).get_word_from_dict_pairs(styleIdeogram); + if (code != 255) return apply_style(detail::TextProperties::TextStyle::Ideogram{code}); + code = (std::uint8_t)buf::UtilsManip(format).get_word_from_dict_pairs(styleScript); + if (code != 255) return apply_style(detail::TextProperties::TextStyle::Script{code}); + + code = (std::uint8_t)buf::UtilsManip(format).get_word_from_dict_pairs(styleUnderline); + if (code != 255) { + if (code == (std::uint8_t)detail::TextProperties::TextStyle::Underline::SelectUnderlinedColor) { + detail::TextProperties::TextStyle::UnderlineColor::ColorCube underlineColor = select_underlined_color_style(format); + return apply_style(underlineColor); + } + return apply_style(detail::TextProperties::TextStyle::Underline{code}); + } + } + + template + TextProperties::TextStyle::UnderlineColor::ColorCube TextPropertiesManager::select_underlined_color_style(buf::StreamView& format) { + // TODO + // FIXME + throw std::runtime_error("fmt error: FunctionNotImpl"); + } + + template + void detail::TextPropertiesManager::parse_front(context::BasicContext& context, buf::StreamView& stream) { + static constexpr std::string_view frontCode[] = {"default", "front0", "front1", "front2", "front3", "front4", "front5", "front6", "front7", "front8", "front9"}; + + if (buf::TestAccess(stream).is_equal_to(':')) { + buf::Manip(stream).forward(); + buf::TestManip(stream).ignore_every_spaces(); + + std::optional front_id = buf::UtilsManip(stream).get_word_from_list(frontCode); + + if (front_id.has_value()) { + apply_front(static_cast(front_id.value())); + return; + } + } + reload_default_front(); + } +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/formatter_executor/basic_formatter_executor.hxx b/src/stream/fmt/context/formatter_executor/basic_formatter_executor.hxx new file mode 100644 index 00000000..33918cf4 --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/basic_formatter_executor.hxx @@ -0,0 +1,116 @@ +#pragma once + +#include "stream/fmt/context/basic_context/basic_context.hxx" + +#include "stream/fmt/buf/fmt_manip_io.hxx" +#include "stream/fmt/buf/write_manip.hxx" + +#include "formatter_type.hxx" +#include "index_args.hxx" +#include "named_args.hxx" + +#include "formatter_args.hxx" +#include "forwarders.hxx" + +namespace stream::fmt::context { + enum class EndOfStringCharMode { + Forced, + Optional + }; + + template + class BasicFormatterExecutor : public ContextExecutor { + public: + using TChar = CharType; + + private: + using M_Type = BasicFormatterExecutor; + + public: + BasicFormatterExecutor(buf::FMTStreamIO& ostream, detail::ITextPropertiesExecutor& text_properties_executor); + ~BasicFormatterExecutor() override = default; + + void terminate(); + + public: + buf::FMTStreamIO& ostream; + EndOfStringCharMode end_of_string_char = EndOfStringCharMode::Optional; + + using ContextExecutor::data; + using ContextExecutor::text_manager; + + protected: + void exec_raw_string(std::basic_string_view sv) override { + return buf::WriteManip(ostream).fast_write_sv(sv); + } + void exec_settings() override; + + public: + template + void run_(buf::StreamView format, Args&&... args); + template + void run(Format&& format, Args&&... args); + + public: + template + void write_type(Type&& type) { + FormatterType>::type, M_Type>::format(std::forward(type), *this); + } + template + void write_type(Type&& type, Rest&&... rest) { + write_type(std::forward(type)); + if constexpr (sizeof...(rest) > 0) { + write_type(std::forward(rest)...); + } + } + }; +} // namespace stream::fmt::context + +namespace stream::fmt::context { + template + BasicFormatterExecutor::BasicFormatterExecutor(buf::FMTStreamIO& ostream_, detail::ITextPropertiesExecutor& text_properties_executor_) + : ContextExecutor(text_properties_executor_), ostream(ostream_) { + text_properties_executor_.link_to_executor(this); + } + + template + void BasicFormatterExecutor::terminate() { + buf::ManipIO(ostream).compute_generated_size(); + + // End char not included in buffer manager context to deduce size correctly + if (end_of_string_char == EndOfStringCharMode::Forced) { + buf::ManipIO(ostream).pushback('\0'); + } else { + if (ostream.get_buffer_remaining_size() > 1) { + buf::ManipIO(ostream).pushback('\0'); + } + } + } + + template + void BasicFormatterExecutor::exec_settings() { + // indent + auto indent = data.specifiers.get("indent"); + if (indent != nullptr) ostream.indent = indent->as_number; + } + + template + template + void BasicFormatterExecutor::run_(buf::StreamView format, Args&&... args) { + auto args_interface = detail::FormatterArgsInterface, Args...>(*this, std::forward(args)...); + + detail::TextProperties::Properties saveTextProperties = text_manager.save(); + context::BasicContext context(*this, format, args_interface); + context.run(); + return text_manager.reload(saveTextProperties); + } + + template + template + void BasicFormatterExecutor::run(Format&& format_input, Args&&... args) { + return run_(buf::StreamView{format_input}, std::forward(args)...); + } +} // namespace stream::fmt::context + +#include "format_basics.hxx" +#include "format_text_properties_impl.hxx" diff --git a/src/stream/fmt/context/formatter_executor/format_basics.hxx b/src/stream/fmt/context/formatter_executor/format_basics.hxx new file mode 100644 index 00000000..17cc06f0 --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/format_basics.hxx @@ -0,0 +1,113 @@ +#pragma once + +#include "basic_formatter_executor.hxx" + +#include "stream/fmt/buf/fmt_write_manip.hxx" + +#include "forwarders.hxx" + +namespace stream::fmt { + //---------------------------------------------// + //----------------- Internals -----------------// + //---------------------------------------------// + + template + struct FormatterType, FormatterExecutor> { + static void format(const typename FormatterExecutor::detail::template FormatSpecifier& specifier, FormatterExecutor& executor) { + if (specifier.ValueIsText) { + executor.run("{ '{}', '{}' }", specifier.name, specifier.as_text); + } else { + executor.run("{ '{}', '{}' }", specifier.name, specifier.as_number); + } + return; + } + }; + + //-----------------------------------------------// + //----------------- C/CXX Types -----------------// + //-----------------------------------------------// + + template + struct FormatterType { + static void format(const bool t, FormatterExecutor& executor) { + if (executor.data.prefix_suffix) { + if (t == true) + return buf::WriteManip(executor.ostream).fast_write_literal("True"); + else + return buf::WriteManip(executor.ostream).fast_write_literal("False"); + } else { + if (t == true) + return buf::ManipIO(executor.ostream).pushback('1'); + else + return buf::ManipIO(executor.ostream).pushback('0'); + } + + return; + } + }; + + template + requires(std::is_integral_v && !std::is_floating_point_v && !detail::IsCharType::value) + struct FormatterType { + static inline void format(const T t, FormatterExecutor& executor) { + return buf::FMTWriteManip(executor.ostream).write_integer_format_data(t, executor.data); + } + }; + + template + requires std::is_floating_point_v + struct FormatterType { + static inline void format(const T t, FormatterExecutor& executor) { + return buf::FMTWriteManip(executor.ostream).write_float_formatdata(t, executor.data); + } + }; + + template + requires detail::IsCharType::value + struct FormatterType { + static inline void format(const T t, FormatterExecutor& executor) { + return buf::ManipIO(executor.ostream).pushback(t); + } + }; + + //-------------------------------------------------------// + //----------------- Pointers and Arrays -----------------// + //-------------------------------------------------------// + + template + struct FormatterType { + static inline void format(const void* const t, FormatterExecutor& executor) { + if (t == nullptr) return buf::ManipIO(executor.ostream).fast_write_sv(executor.data.get_as_text("null", "nullptr")); + return buf::FMTWriteManip(executor.ostream).write_integer_format_data(std::size_t(t), executor.data); + } + }; + + template + struct FormatterType { + static inline void format(const T* const t, FormatterExecutor& executor) { + if (t == nullptr) { + return buf::WriteManip(executor.ostream).fast_write_sv(executor.data.specifiers.get_as_text("null", "nullptr")); + } + + if constexpr (detail::IsCharType::value) { + detail::forwarders::format_string_view(std::basic_string_view(t), executor); + } else { + detail::forwarders::format_span(std::span(t), executor); + } + } + }; + + template + struct FormatterType { + static inline void format(T const (&t)[SIZE], FormatterExecutor& executor) { + if constexpr (detail::IsCharType::value) { + std::size_t size = SIZE; + while (t[size - 1] == '\0') + --size; + return detail::forwarders::format_string_view(std::basic_string_view(t, size), executor); + } else { + return detail::forwarders::format_span(std::span(t, SIZE), executor); + } + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/context/formatter_executor/format_text_properties_impl.hxx b/src/stream/fmt/context/formatter_executor/format_text_properties_impl.hxx new file mode 100644 index 00000000..d1c7c664 --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/format_text_properties_impl.hxx @@ -0,0 +1,65 @@ +#pragma once + +#include "basic_formatter_executor.hxx" + +namespace stream::fmt { + //------------------------------------------// + //----------------- Resets -----------------// + //------------------------------------------// + + template + struct FormatterType { + static void format(const detail::TextProperties::ResetProperties, FormatterExecutor& executor) { + return executor.text_manager.all_properties_reset(); + } + }; + + template + struct FormatterType { + static void format(const detail::TextProperties::TextColor::reset_color, FormatterExecutor& executor) { + return executor.text_manager.apply_color_reset(); + } + }; + + template + struct FormatterType { + static void format(const detail::TextProperties::TextStyle::reset_style, FormatterExecutor& executor) { + return executor.text_manager.apply_style_reset(); + } + }; + + template + struct FormatterType { + static void format(const detail::TextProperties::TextFront::ResetFront, FormatterExecutor& executor) { + return executor.text_manager.apply_front_reset(); + } + }; + + //---------------------------------------// + //----------------- Ask -----------------// + //---------------------------------------// + + template + requires detail::text_properties_color_is_apply + struct FormatterType { + static void format(const T& t, FormatterExecutor& executor) { + return executor.text_manager.ask_apply_color(t); + } + }; + + template + requires detail::TextPropertiesStyleIsapply + struct FormatterType { + static void format(const T& t, FormatterExecutor& executor) { + return executor.text_manager.ask_apply_style(t); + } + }; + + template + requires detail::TextPropertiesFrontIsapply + struct FormatterType { + static void format(const T& t, FormatterExecutor& executor) { + return executor.text_manager.ask_apply_front(t); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/context/formatter_executor/formatter_args.hxx b/src/stream/fmt/context/formatter_executor/formatter_args.hxx new file mode 100644 index 00000000..1d4a531c --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/formatter_args.hxx @@ -0,0 +1,136 @@ + +#pragma once + +#include "stream/fmt/context/basic_context/basic_args_interface.hxx" +#include "stream/fmt/detail/prelude.hxx" + +#include "formatter_type.hxx" + +namespace stream::fmt::detail { + /****************************/ + /******** Args tuple ********/ + /****************************/ + template + struct FormatterArgs; + + template <> + struct FormatterArgs<> { + public: + static inline constexpr std::size_t size() { + return 0; + } + + public: + template + void run_type_at(FormatterExecutor&, std::int32_t) { + throw std::runtime_error("fmt error: ArgsInterface_IndexOutOfBounds"); + } + template + inline std::optional get_index_of_current_named_arg(buf::StreamView& stream, std::int32_t) { + return std::nullopt; + } + inline PointerID get_pointerid_at(std::int32_t) { + throw std::runtime_error("fmt error: ArgsInterface_IndexOutOfBounds"); + } + template + inline T get_converted_type_at(std::int32_t) { + throw std::runtime_error("fmt error: ArgsInterface_IndexOutOfBounds"); + } + }; + + template + struct FormatterArgs : public FormatterArgs { + private: + using TypeWithoutRef = std::remove_reference_t; + + public: + FormatterArgs(const TypeWithoutRef& t, Rest&&... rest) : FormatterArgs(std::forward(rest)...), value_(t) {} + + private: + const TypeWithoutRef& value_; + + public: + static inline constexpr std::size_t size() { + return sizeof...(Rest) + 1; + } + + public: + template + void run_type_at(Executor& executor, std::int32_t idx) { + if (idx == 0) { + return executor.write_type(value_); + } + return FormatterArgs::run_type_at(executor, idx - 1); + } + + public: + template + inline std::optional get_index_of_current_named_arg(buf::StreamView& format, std::int32_t begin_search_index) { + if constexpr (detail::IsANamedArgs>::value) { + bool current_is_a_named_arg = buf::FMTParamsManip(format).next_is_named_args(value_.get_name()); + if (current_is_a_named_arg) return begin_search_index; + } + return FormatterArgs::get_index_of_current_named_arg(format, begin_search_index + 1); + } + + public: + inline PointerID get_pointerid_at(std::int32_t idx) { + if (idx == 0) return PointerID{.type_info = typeid(const TypeWithoutRef), .ptr = const_cast(static_cast(&value_))}; + return FormatterArgs::get_pointerid_at(idx - 1); + } + + public: + template + inline T get_converted_type_at(std::int32_t idx) { + if (idx == 0) { + if constexpr (FMTCanContextConvert) { + return FMTContextConvert::convert(value_); + } else { + throw std::runtime_error("fmt error: ArgsInterface_InvalidConversion"); + } + } + return FormatterArgs::template get_converted_type_at(idx - 1); + } + }; + + + /********************************/ + /******** Args interface ********/ + /********************************/ + template + class FormatterArgsInterface : public BasicArgsInterface { + public: + using ContextArgsType = FormatterArgs; + + public: + FormatterArgsInterface(FormatterExecutor& executor, Args&&... args) : BasicArgsInterface(), executor(executor), args_interface(std::forward(args)...) {} + ~FormatterArgsInterface() override = default; + + public: + size_t size() override { + return args_interface.size(); + } + + void run_type_at(std::int32_t idx) override { + return args_interface.run_type_at(executor, idx); + } + std::optional get_index_of_current_named_arg(buf::StreamView& format) override { + return args_interface.get_index_of_current_named_arg(format, std::int32_t{0}); + } + PointerID get_pointerid_at(std::int32_t idx) override { + return args_interface.get_pointerid_at(idx); + } + + public: + std::basic_string_view get_string_at(std::int32_t idx) override { + return args_interface.template get_converted_type_at>(idx); + } + std::int64_t get_int_at(std::int32_t idx) override { + return args_interface.template get_converted_type_at(idx); + } + + protected: + FormatterExecutor& executor; + ContextArgsType args_interface; + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/formatter_executor/formatter_text_properties_executor/formatter_text_properties_executor.hxx b/src/stream/fmt/context/formatter_executor/formatter_text_properties_executor/formatter_text_properties_executor.hxx new file mode 100644 index 00000000..0393af62 --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/formatter_text_properties_executor/formatter_text_properties_executor.hxx @@ -0,0 +1,61 @@ +#pragma once + +#include "stream/fmt/context/basic_context/text_properties_executor.hxx" +#include "stream/fmt/buf/fmt_manip_io.hxx" +#include "stream/fmt/context/formatter_executor/basic_formatter_executor.hxx" + +namespace stream::fmt::detail { + template + class IFormatterTextPropertiesExecutor : public ITextPropertiesExecutor { + public: + ~IFormatterTextPropertiesExecutor() override = default; + + void link_to_executor(void* executor) override { + buffer = &reinterpret_cast*>(executor)->ostream; + } + + protected: + buf::FMTStreamIO* buffer{nullptr}; + }; +} // namespace stream::fmt::detail + +namespace stream::fmt::detail { + template + class FormatterNOTextPropertiesExecutor final : public IFormatterTextPropertiesExecutor { + public: + FormatterNOTextPropertiesExecutor() = default; + ~FormatterNOTextPropertiesExecutor() override = default; + + public: + void all_properties_reset() override {} + + public: + void reset_color() override {} + void execute_color(const detail::TextProperties::TextColor::BasicColorFG&) override {} + void execute_color(const detail::TextProperties::TextColor::BasicColorBG&) override {} + void execute_color(const detail::TextProperties::TextColor::BasicColor&) override {} + void execute_color(const detail::TextProperties::TextColor::Color24bFG&) override {} + void execute_color(const detail::TextProperties::TextColor::Color24bBG&) override {} + void execute_color(const detail::TextProperties::TextColor::Color24b&) override {} + void execute_color(const detail::TextProperties::TextColor::ColorCubeFG&) override {} + void execute_color(const detail::TextProperties::TextColor::ColorCubeBG&) override {} + void execute_color(const detail::TextProperties::TextColor::ColorCube&) override {} + + public: + void reset_front() override {} + void execute_front(const detail::TextProperties::TextFront::FrontID&) override {} + + public: + void reset_style() override {} + void execute_style(const detail::TextProperties::TextStyle::Intensity&) override {} + void execute_style(const detail::TextProperties::TextStyle::Italic&) override {} + void execute_style(const detail::TextProperties::TextStyle::Underline&) override {} + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::Color&) override {} + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::ColorCube&) override {} + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::Color24b&) override {} + void execute_style(const detail::TextProperties::TextStyle::Blink&) override {} + void execute_style(const detail::TextProperties::TextStyle::Inverted&) override {} + void execute_style(const detail::TextProperties::TextStyle::Ideogram&) override {} + void execute_style(const detail::TextProperties::TextStyle::Script&) override {} + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/formatter_executor/formatter_text_properties_executor/formatter_text_properties_executor_ansi.hxx b/src/stream/fmt/context/formatter_executor/formatter_text_properties_executor/formatter_text_properties_executor_ansi.hxx new file mode 100644 index 00000000..82478c8c --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/formatter_text_properties_executor/formatter_text_properties_executor_ansi.hxx @@ -0,0 +1,121 @@ +#pragma once + +#include "formatter_text_properties_executor.hxx" +#include "stream/fmt/detail/indent_handlers.hxx" + +namespace stream::fmt::detail { + template + class FormatterTextPropertiesExecutorANSI final : public IFormatterTextPropertiesExecutor { + public: + FormatterTextPropertiesExecutorANSI() = default; + ~FormatterTextPropertiesExecutorANSI() override = default; + + using IFormatterTextPropertiesExecutor::buffer; + + public: + void all_properties_reset() override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).fast_write_literal("\033[0m"); + } + + public: + void reset_color() override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).fast_write_literal("\033[39;49m"); + } + + void execute_color(const TextProperties::TextColor::BasicColorFG& t) { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + void execute_color(const TextProperties::TextColor::BasicColorBG& t) { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + void execute_color(const detail::TextProperties::TextColor::BasicColor& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t.fg), ";", static_cast(t.bg), "m"); + } + void execute_color(const detail::TextProperties::TextColor::Color24bFG& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[38;2;", t.r, ";", t.g, ";", t.b, "m"); + } + void execute_color(const detail::TextProperties::TextColor::Color24bBG& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[48;2;", t.r, ";", t.g, ";", t.b, "m"); + } + void execute_color(const detail::TextProperties::TextColor::Color24b& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[38;2;", t.fg.r, ";", t.fg.g, ";", t.fg.b, "; 48; 2;", t.bg.r, ";", t.bg.g, ";", t.bg.b, "m"); + } + void execute_color(const detail::TextProperties::TextColor::ColorCubeFG& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[38;5;", t.get_color_ref(), "m"); + } + void execute_color(const detail::TextProperties::TextColor::ColorCubeBG& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[48;5;", t.get_color_ref(), "m"); + } + void execute_color(const detail::TextProperties::TextColor::ColorCube& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[48;5;", t.fg.get_color_ref(), ";48;5;", t.bg.get_color_ref(), "m"); + } + + public: + void reset_front() override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", detail::TextProperties::TextFront::FrontID::DefaultFrontID, "m"); + } + void execute_front(const detail::TextProperties::TextFront::FrontID& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", t.id, "m"); + } + + public: + void reset_style() override { + // TODO + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).fast_write_literal("\033[0m"); + } + void execute_style(const detail::TextProperties::TextStyle::Intensity& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + void execute_style(const detail::TextProperties::TextStyle::Italic& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + void execute_style(const detail::TextProperties::TextStyle::Underline& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::Color&) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[59m"); + } + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::ColorCube& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[58;5;", t.get_color_ref(), "m"); + } + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::Color24b& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[58;2;", t.r, ";", t.g, ";", t.b, "m"); + } + void execute_style(const detail::TextProperties::TextStyle::Blink& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + void execute_style(const detail::TextProperties::TextStyle::Inverted& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + void execute_style(const detail::TextProperties::TextStyle::Ideogram& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + void execute_style(const detail::TextProperties::TextStyle::Script& t) override { + NoStrideFunction no_stride(*buffer); + return buf::WriteManip(*buffer).basic_write_type("\033[", static_cast(t), "m"); + } + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/formatter_executor/formatter_type.hxx b/src/stream/fmt/context/formatter_executor/formatter_type.hxx new file mode 100644 index 00000000..d803875a --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/formatter_type.hxx @@ -0,0 +1,37 @@ +#pragma once + +#include "stream/fmt/detail/prelude.hxx" + +#define STREAMFORMAT_FORMATTER_DECLARED +namespace stream::fmt { + template + struct FormatterType { + static void format(const T&, FormatterExecutor& executor) { +#ifdef UNKOWN_TYPE_MESSAGE + executor.run("({C:red}FMT unknow type: {})", typeid(T).name()); +#endif +#ifdef UNKOWN_TYPE_FAIL + static_assert(false); +#endif +#ifdef UNKOWN_TYPE_DEBUG + STREAMFORMAT_DEBUGBREAK(); +#endif + } + }; +} // namespace stream::fmt + +#define STREAMFORMAT_AUTO_FORMATTER(Type, formatstr, ...) \ + template \ + struct stream::fmt::FormatterType { \ + static void format(const Type&, FormatterExecutor& executor) { \ + return executor.run(formatstr, __VA_ARGS__); \ + } \ + }; + +#define STREAMFORMAT_AUTO_FORMATTER_T(Type, formatstr, ...) \ + template \ + struct stream::fmt::FormatterType { \ + static void format(const Type&, FormatterExecutor& executor) { \ + return executor.run(formatstr, __VA_ARGS__); \ + } \ + }; diff --git a/src/stream/fmt/context/formatter_executor/forwarders.hxx b/src/stream/fmt/context/formatter_executor/forwarders.hxx new file mode 100644 index 00000000..8cc0eb78 --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/forwarders.hxx @@ -0,0 +1,91 @@ +#pragma once + +#include "stream/fmt/detail/specifiers.hxx" +#include "stream/fmt/buf/fmt_write_manip.hxx" +#include "stream/fmt/context/basic_context/basic_context_parse_formatdata.hxx" + +#include + +namespace stream::fmt::detail { + template + class ContainersUtility { + public: + static constexpr std::basic_string_view default_join = ", "; + static constexpr std::basic_string_view default_begin = "{ "; + static constexpr std::basic_string_view default_end = " }"; + }; + + template + struct FunctionapplyNextOverride { + inline explicit FunctionapplyNextOverride(FormatterExecutor& executor) : executor(executor), formatdata(executor.data) { + buf::StreamView stream{executor.data.next_override}; + executor.data = parse_format_data(executor, stream); + } + + inline ~FunctionapplyNextOverride() { + executor.data = formatdata; + } + + FormatterExecutor& executor; + FormatData formatdata; + }; + + namespace forwarders { + template + void format_span(const std::span container, FormatterExecutor& executor) { + std::size_t begin_idx = (std::size_t)executor.data.specifiers.get_as_number("begin", 0); + std::size_t end = executor.data.specifiers.get_as_number("end", container.size()); + std::int32_t size_to_print = executor.data.specifiers.get_as_number("size", static_cast(end) - static_cast(begin_idx)); + + buf::FMTWriteManip(executor.ostream).write_indent_sv(executor.data.specifiers.get_as_text("begin", ContainersUtility::default_begin)); + std::basic_string_view join = executor.data.specifiers.get_as_text("join", ContainersUtility::default_join); + + if (size_to_print > 0) { + detail::FunctionapplyNextOverride apply_next_override(executor); + + bool first = true; + std::for_each_n(container.begin() + begin_idx, static_cast(size_to_print), [&](const auto& element) { + if (first) { + first = false; + } else { + buf::FMTWriteManip(executor.ostream).write_indent_sv(join); + } + + executor.write_type(element); + }); + } + + buf::FMTWriteManip(executor.ostream).write_indent_sv(executor.data.specifiers.get_as_text("end", ContainersUtility::default_end)); + } + + template + void format_string_view(const std::basic_string_view container, FormatterExecutor& executor) { + std::size_t begin_idx = (std::size_t)executor.data.specifiers.get_as_number("begin", 0); + std::size_t end = executor.data.specifiers.get_as_number("end", container.size()); + std::int32_t size_to_print = executor.data.specifiers.get_as_number("size", static_cast(end) - static_cast(begin_idx)); + + if (executor.data.specifiers.has("span")) { + return format_span(std::span(container), executor); + } + + if (executor.data.prefix_suffix) { + buf::ManipIO(executor.ostream).pushback('\"'); + } + + if (size_to_print > 0) { + // TODO: current indent ignore shift + if (executor.data.specifiers.has("indent")) { + return buf::FMTWriteManip(executor.ostream).write_indent_sv(container.substr(begin_idx, static_cast(size_to_print))); + } else if (executor.data.has_spec == false) { + buf::WriteManip(executor.ostream).fast_write_sv(container.substr(begin_idx, static_cast(size_to_print))); + } else { + buf::FMTWriteManip(executor.ostream).write_sv(container.substr(begin_idx, static_cast(size_to_print)), executor.data.shift); + } + } + + if (executor.data.prefix_suffix) { + buf::ManipIO(executor.ostream).pushback('\"'); + } + } + } // namespace forwarders +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/formatter_executor/index_args.hxx b/src/stream/fmt/context/formatter_executor/index_args.hxx new file mode 100644 index 00000000..95062044 --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/index_args.hxx @@ -0,0 +1,33 @@ +#pragma once + +#include "formatter_type.hxx" + +namespace stream::fmt { + template + struct FCIndexArgs { + public: + FCIndexArgs(const std::uint8_t idx, const T& t) : value_(t), idx_(idx) {} + + public: + inline bool IsRightIdx(std::uint8_t idx) const { + return idx == idx_; + } + + public: + inline const T& get_value() const { + return value_; + } + + protected: + const T& value_; + const std::uint8_t idx_; + }; + + template + struct FormatterType, FormatterExecutor> { + template + static inline void format(const FCIndexArgs& t, FormatterExecutor& executor) { + return executor.write_type(t.get_value()); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/context/formatter_executor/named_args.hxx b/src/stream/fmt/context/formatter_executor/named_args.hxx new file mode 100644 index 00000000..cf9dd476 --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/named_args.hxx @@ -0,0 +1,97 @@ +#pragma once + +#include "formatter_type.hxx" + +namespace stream::fmt { + /////---------- string_view NamedArgs Do not allocate memory (Best) ----------///// + template + struct StringViewNamedArgs { + public: + template + StringViewNamedArgs(const CharName (&name)[SIZE], const T& t) : name_(name), value(t) {} + + StringViewNamedArgs(std::basic_string_view name, const T& t) : name_(name), value(t) {} + + public: + T& get_value() { + return value; + } + const T& get_value() const { + return value; + } + std::basic_string_view get_name() const { + return name_; + } + + protected: + std::basic_string_view name_; + const T& value; + }; + + template + struct FormatterType, FormatterExecutor> { + static inline void format(const StringViewNamedArgs& t, FormatterExecutor& executor) { + return executor.write_type(t.get_value()); + } + }; + + /////---------- stringNamedArgs Allocate memory (Only if necessary) ----------///// + template + struct StringNamedArgs { + public: + StringNamedArgs(std::string str, const T& t) : name_(std::move(str)), value(t) {} + + public: + T& get_value() { + return value; + } + const T& get_value() const { + return value; + } + std::basic_string_view get_name() const { + return name_; + } + + protected: + std::basic_string name_; + const T& value; + }; + + template + struct FormatterType, FormatterExecutor> { + static inline void format(const StringNamedArgs& t, FormatterExecutor& executor) { + return executor.write_type(t.get_value()); + } + }; + + namespace detail { + template + struct IsANamedArgs { + public: + [[maybe_unused]] inline constexpr static bool value = false; + }; + + template + struct IsANamedArgs> { + [[maybe_unused]] inline constexpr static bool value = true; + }; + + template + struct IsANamedArgs> { + [[maybe_unused]] inline constexpr static bool value = true; + }; + + template + inline constexpr bool IsANamedArgsValue = false; + + template + inline constexpr bool IsANamedArgsValue> = true; + + template + inline constexpr bool IsANamedArgsValue> = true; + } // namespace detail +} // namespace stream::fmt + +#define FORMAT(value) stream::fmt::StringViewNamedArgs(#value, value) +#define FORMAT_SV(name, value) stream::fmt::StringViewNamedArgs(name, value) +#define FORMAT_STR(name, value) stream::fmt::StringNamedArgs(name, value) diff --git a/src/stream/fmt/context/formatter_executor/utility_functions.hxx b/src/stream/fmt/context/formatter_executor/utility_functions.hxx new file mode 100644 index 00000000..28852b90 --- /dev/null +++ b/src/stream/fmt/context/formatter_executor/utility_functions.hxx @@ -0,0 +1,184 @@ +#pragma once + +#include "basic_formatter_executor.hxx" + +#include "stream/fmt/buf/streamio_manager/dynamic_streamio_manager.hxx" +#include "stream/fmt/buf/streamio_manager/given_streamio_manager.hxx" +#include "stream/fmt/buf/streamio_manager/static_streamio_manager.hxx" + +#include "formatter_text_properties_executor/formatter_text_properties_executor_ansi.hxx" + +#include + +namespace stream::fmt { + /////---------- Impl with as Format ----------////// + namespace detail { + template + requires(IsCharType::value) + void format_in_manager(buf::BasicStreamIOManager& ostream_manager, bool newline, buf::StreamView format, Args&&... args) { + using TCharResolved = std::remove_const_t; + + detail::FormatterTextPropertiesExecutorANSI text_properties_executor; + buf::FMTStreamIO ostream = buf::FMTStreamIO::create(ostream_manager); + context::BasicFormatterExecutor executor(ostream, text_properties_executor); + executor.run(format, std::forward(args)...); + if (newline) buf::ManipIO(ostream).pushback('\n'); + return executor.terminate(); + } + + template + requires(IsCharType::value) + void format_in_manager(buf::BasicStreamIOManager& ostream_manager, bool newline, T&& t) { + using TCharResolved = std::remove_const_t; + + detail::FormatterTextPropertiesExecutorANSI text_properties_executor; + buf::FMTStreamIO ostream = buf::FMTStreamIO::create(ostream_manager); + context::BasicFormatterExecutor executor(ostream, text_properties_executor); + executor.write_type(std::forward(t)); + if (newline) buf::ManipIO(ostream).pushback('\n'); + return executor.terminate(); + } + } // namespace detail + + template + requires(detail::IsCharType::value && buf::convertible_to_buffer_info_view) + void format_in_char(TChar (&buffer)[BUFFER_SIZE], Format&& format_input, Args&&... args) { + buf::GivenStreamIOManager ostream_manager(buffer); + return detail::format_in_manager(ostream_manager, false, buf::StreamView{format_input}, std::forward(args)...); + } + + template + requires(detail::IsCharType::value && buf::convertible_to_buffer_info_view) + void format_in_char(TChar* const buffer, const std::size_t buffer_size, Format&& format_input, Args&&... args) { + buf::GivenStreamIOManager ostream_manager(buffer, buffer_size); + return detail::format_in_manager(ostream_manager, false, buf::StreamView{format_input}, std::forward(args)...); + } + + template + requires(detail::IsCharType::value && buf::convertible_to_buffer_info_view) + void cfile_print(FILE* stream, Format&& format_input, Args&&... args) { + buf::DynamicStreamIOManager ostream_manager(256); + detail::format_in_manager(ostream_manager, false, buf::StreamView{format_input}, std::forward(args)...); + + std::fwrite(ostream_manager.get_buffer(), ostream_manager.get_last_generated_data_size(), 1, stream); + std::fflush(stream); + } + + template + requires(detail::IsCharType::value && buf::convertible_to_buffer_info_view) + void cfile_println(FILE* stream, Format&& format_input, Args&&... args) { + buf::DynamicStreamIOManager ostream_manager(256); + detail::format_in_manager(ostream_manager, true, buf::StreamView{format_input}, std::forward(args)...); + + std::fwrite(ostream_manager.get_buffer(), ostream_manager.get_last_generated_data_size(), 1, stream); + std::fflush(stream); + } + + template + requires(detail::IsCharType::value && buf::convertible_to_buffer_info_view) + void file_print(std::basic_ostream& stream, Format&& format_input, Args&&... args) { + buf::DynamicStreamIOManager ostream_manager(256); + detail::format_in_manager(ostream_manager, false, buf::StreamView{format_input}, std::forward(args)...); + + stream.write(ostream_manager.get_buffer(), ostream_manager.get_last_generated_data_size()); + stream.flush(); + } + + template + requires(detail::IsCharType::value && buf::convertible_to_buffer_info_view) + void file_println(std::basic_ostream& stream, Format&& format_input, Args&&... args) { + buf::DynamicStreamIOManager ostream_manager(256); + detail::format_in_manager(ostream_manager, true, buf::StreamView{format_input}, std::forward(args)...); + + stream.write(ostream_manager.get_buffer(), ostream_manager.get_last_generated_data_size()); + stream.flush(); + } + + template + requires(detail::IsCharType::value && buf::convertible_to_buffer_info_view) + void format_in_string(std::basic_string& str, Format&& format_input, Args&&... args) { + buf::DynamicStreamIOManager ostream_manager(256); + detail::format_in_manager(ostream_manager, false, buf::StreamView{format_input}, std::forward(args)...); + str = ostream_manager.get_last_generated_string_view(); + } + + template + requires(detail::IsCharType::value && buf::convertible_to_buffer_info_view) + inline std::basic_string format_string(Format&& format_input, Args&&... args) { + buf::DynamicStreamIOManager ostream_manager(256); + detail::format_in_manager(ostream_manager, false, buf::StreamView{format_input}, std::forward(args)...); + return std::basic_string{ostream_manager.get_last_generated_string_view()}; + } + + /////---------- NO-FORMAT Impl except for string which are formatted to avoid {} ----------////// + + template + requires(detail::IsCharType::value) + void format_in_char(TChar (&buffer)[BUFFER_SIZE], T&& t) { + buf::GivenStreamIOManager ostream_manager(buffer, BUFFER_SIZE); + return detail::format_in_manager(ostream_manager, false, std::forward(t)); + } + + template + requires(detail::IsCharType::value) + void format_in_char(TChar* const buffer, const std::size_t buffer_size, T&& t) { + buf::GivenStreamIOManager ostream_manager(buffer, buffer_size); + return detail::format_in_manager(ostream_manager, false, std::forward(t)); + } + + template + requires(detail::IsCharType::value) + void cfile_print(FILE* stream, T&& t) { + buf::DynamicStreamIOManager ostream_manager(32); + detail::format_in_manager(ostream_manager, false, std::forward(t)); + + std::fwrite(ostream_manager.get_buffer(), static_cast(ostream_manager.get_last_generated_data_size()), 1, stream); + std::fflush(stream); + } + + template + requires(detail::IsCharType::value) + void cfile_println(FILE* stream, T&& t) { + buf::DynamicStreamIOManager ostream_manager(32); + detail::format_in_manager(ostream_manager, true, std::forward(t)); + + std::fwrite(ostream_manager.get_buffer(), static_cast(ostream_manager.get_last_generated_data_size()), 1, stream); + std::fflush(stream); + } + + template + requires(detail::IsCharType::value) + void file_print(std::basic_ostream& stream, T&& t) { + buf::DynamicStreamIOManager ostream_manager(32); + detail::format_in_manager(ostream_manager, false, std::forward(t)); + + stream.write(ostream_manager.get_buffer(), static_cast(ostream_manager.get_last_generated_data_size())); + stream.flush(); + } + + template + requires(detail::IsCharType::value) + void file_println(std::basic_ostream& stream, T&& t) { + buf::DynamicStreamIOManager ostream_manager(32); + detail::format_in_manager(ostream_manager, true, std::forward(t)); + + stream.write(ostream_manager.get_buffer(), static_cast(ostream_manager.get_last_generated_data_size())); + stream.flush(); + } + + template + requires(detail::IsCharType::value) + void format_in_string(std::basic_string& str, T&& t) { + buf::DynamicStreamIOManager ostream_manager(32); + detail::format_in_manager(ostream_manager, false, std::forward(t)); + str = ostream_manager.get_last_generated_string_view(); + } + + template + requires(detail::IsCharType::value) + inline std::basic_string format_string(T&& t) { + buf::DynamicStreamIOManager ostream_manager(32); + detail::format_in_manager(ostream_manager, false, std::forward(t)); + return std::string{ostream_manager.get_last_generated_string_view()}; + } +} // namespace stream::fmt diff --git a/src/stream/fmt/context/parser_executor/basic_parser_executor.hxx b/src/stream/fmt/context/parser_executor/basic_parser_executor.hxx new file mode 100644 index 00000000..507ff67e --- /dev/null +++ b/src/stream/fmt/context/parser_executor/basic_parser_executor.hxx @@ -0,0 +1,86 @@ +#pragma once + +#include "stream/fmt/buf/stream.hxx" +#include "stream/fmt/buf/manip.hxx" +#include "stream/fmt/buf/test_manip.hxx" + +#include "stream/fmt/context/basic_context/basic_context.hxx" + +#include "parser_type.hxx" + +#include "parser_args.hxx" + +#include "parser_text_properties_executor/parser_text_properties_executor.hxx" + +namespace stream::fmt::context { + template + class BasicParserExecutor : public ContextExecutor { + public: + using TChar = CharType; + + private: + using M_Type = BasicParserExecutor; + + public: + BasicParserExecutor(buf::StreamView& istream, detail::ITextPropertiesExecutor& text_properties_executor); + ~BasicParserExecutor() override = default; + + void terminate(); + + public: + buf::StreamView& istream; + + using ContextExecutor::data; + using ContextExecutor::text_manager; + + protected: + void exec_raw_string(std::basic_string_view sv) override { + buf::TestManip(istream).is_same_forward(sv.data(), sv.size()); + } + void exec_settings() override {}; + + public: + template + void run_(buf::StreamView format, Args&&... args); + template + void run(Format&& format, Args&&... args); + + public: + template + void read_type(Type& type, Rest&... rest) { + ParserType>::type, M_Type>::parse(type, *this); + if constexpr (sizeof...(rest) > 0) read_type(std::forward(rest)...); + } + }; +} // namespace stream::fmt::context + +namespace stream::fmt::context { + template + BasicParserExecutor::BasicParserExecutor(buf::StreamView& istream_, detail::ITextPropertiesExecutor& text_properties_executor_) + : ContextExecutor(text_properties_executor_), istream{istream_} { + text_properties_executor_.link_to_executor(this); + } + + template + void BasicParserExecutor::terminate() {} + + template + template + void BasicParserExecutor::run_(buf::StreamView format, Args&&... args) { + auto args_interface = detail::ParserArgsInterface, Args...>(*this, std::forward(args)...); + + detail::TextProperties::Properties saveTextProperties = text_manager.save(); + context::BasicContext context(*this, format, args_interface); + context.run(); + return text_manager.reload(saveTextProperties); + } + + template + template + void BasicParserExecutor::run(Format&& format_input, Args&&... args) { + return run_(buf::StreamView{format_input}, std::forward(args)...); + } +} // namespace stream::fmt::context + +#include "parse_basics_impl.hxx" +#include "parse_text_properties_impl.hxx" diff --git a/src/stream/fmt/context/parser_executor/parse_basics_impl.hxx b/src/stream/fmt/context/parser_executor/parse_basics_impl.hxx new file mode 100644 index 00000000..f966dc22 --- /dev/null +++ b/src/stream/fmt/context/parser_executor/parse_basics_impl.hxx @@ -0,0 +1,90 @@ +#pragma once + +#include "basic_parser_executor.hxx" +#include "stream/fmt/buf/fmt_read_manip.hxx" + +namespace stream::fmt { + //----------------------------------------------// + //----------------- forwarders -----------------// + //----------------------------------------------// + + //-----------------------------------------------// + //----------------- C/CXX Types -----------------// + //-----------------------------------------------// + + template + struct ParserType { + static void parse(bool& t, ParserExecutor& executor) { + if (!executor.data.prefix_suffix) { + if (buf::TestAccess(executor.istream).is_equal_to('t', 'T')) { + buf::Manip(executor.istream).forward(); + if (buf::TestAccess(executor.istream).is_same("rue")) { + buf::Manip(executor.istream).forward(3); + t = true; + } + } else if (buf::TestAccess(executor.istream).is_equal_to('f', 'F')) { + buf::Manip(executor.istream).forward(); + if (buf::TestAccess(executor.istream).is_same("alse")) { + buf::Manip(executor.istream).forward(4); + t = false; + } + } + } else { + if (buf::TestAccess(executor.istream).is_equal_to('1')) { + buf::Manip(executor.istream).forward(); + t = true; + } else if (buf::TestAccess(executor.istream).is_equal_to('0')) { + buf::Manip(executor.istream).forward(); + t = false; + } + } + } + }; + + template + requires(std::is_integral_v && !std::is_floating_point_v && !detail::IsCharType::value) + struct ParserType { + static inline void parse(T& t, ParserExecutor& executor) { + return buf::FMTReadManip(executor.istream).read_integer_format_data(t, executor.data); + } + }; + + template + requires std::is_floating_point_v + struct ParserType { + static inline void parse(T& t, ParserExecutor& executor) { + return buf::FMTReadManip(executor.istream).read_float_format_data(t, executor.data); + } + }; + + //-------------------------------------------------------// + //----------------- Pointers and Arrays -----------------// + //-------------------------------------------------------// + + template + struct ParserType { + static inline void parse(void*&, ParserExecutor&) { + // FIXME + // TODO + throw std::runtime_error("fmt error: FunctionNotImpl"); + } + }; + + template + struct ParserType { + static inline void parse(T*&, ParserExecutor&) { + // FIXME + // TODO + throw std::runtime_error("fmt error: FunctionNotImpl"); + } + }; + + template + struct ParserType { + static inline void parse(T (&)[SIZE], ParserExecutor&) { + // FIXME + // TODO + throw std::runtime_error("fmt error: FunctionNotImpl"); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/context/parser_executor/parse_text_properties_impl.hxx b/src/stream/fmt/context/parser_executor/parse_text_properties_impl.hxx new file mode 100644 index 00000000..f35a49f6 --- /dev/null +++ b/src/stream/fmt/context/parser_executor/parse_text_properties_impl.hxx @@ -0,0 +1,65 @@ +#pragma once + +#include "basic_parser_executor.hxx" + +namespace stream::fmt { + //------------------------------------------// + //----------------- Resets -----------------// + //------------------------------------------// + + template + struct ParserType { + static inline void parse(detail::TextProperties::ResetProperties, ParserExecutor& executor) { + return executor.text_manager.all_properties_reset(); + } + }; + + template + struct ParserType { + static inline void parse(detail::TextProperties::TextColor::reset_color, ParserExecutor& executor) { + return executor.text_manager.apply_color_reset(); + } + }; + + template + struct ParserType { + static inline void parse(detail::TextProperties::TextStyle::reset_style, ParserExecutor& executor) { + return executor.text_manager.apply_style_reset(); + } + }; + + template + struct ParserType { + static inline void parse(detail::TextProperties::TextFront::ResetFront, ParserExecutor& executor) { + return executor.text_manager.apply_front_reset(); + } + }; + + //---------------------------------------// + //----------------- Ask -----------------// + //---------------------------------------// + + template + requires detail::text_properties_color_is_apply + struct ParserType { + static inline void parse(T& t, ParserExecutor& executor) { + return executor.text_manager.ask_apply_color(t); + } + }; + + template + requires detail::TextPropertiesStyleIsapply + struct ParserType { + static inline void parse(T& t, ParserExecutor& executor) { + return executor.text_manager.ask_apply_style(t); + } + }; + + template + requires detail::TextPropertiesFrontIsapply + struct ParserType { + static inline void parse(T& t, ParserExecutor& executor) { + return executor.text_manager.ask_apply_front(t); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/context/parser_executor/parser_args.hxx b/src/stream/fmt/context/parser_executor/parser_args.hxx new file mode 100644 index 00000000..816c6815 --- /dev/null +++ b/src/stream/fmt/context/parser_executor/parser_args.hxx @@ -0,0 +1,138 @@ +#pragma once + +#include "stream/fmt/context/basic_context/basic_args_interface.hxx" +#include "stream/fmt/detail/prelude.hxx" +#include "stream/fmt/context/formatter_executor/named_args.hxx" + +namespace stream::fmt::detail { + /****************************/ + /******** Args tuple ********/ + /****************************/ + template + struct ParserArgs; + + template <> + struct ParserArgs<> { + public: + ParserArgs() = default; + + public: + static inline constexpr std::size_t size() { + return 0; + } + + public: + template + void run_type_at(FormatterExecutor&, std::int32_t) { + throw std::runtime_error("fmt error: ArgsInterface_IndexOutOfBounds"); + } + template + inline std::optional get_index_of_current_named_arg(buf::StreamView& format, std::int32_t) { + return std::nullopt; + } + inline PointerID get_pointerid_at(std::int32_t) { + throw std::runtime_error("fmt error: ArgsInterface_IndexOutOfBounds"); + } + template + inline T get_converted_type_at(std::int32_t) { + throw std::runtime_error("fmt error: ArgsInterface_IndexOutOfBounds"); + } + }; + + template + struct ParserArgs : ParserArgs { + private: + using TypeWithoutRef = std::remove_reference_t; + + public: + ParserArgs(TypeWithoutRef& t, Rest&... rest) : ParserArgs(std::forward(rest)...), value_(t) {} + + private: + TypeWithoutRef& value_; + + public: + static inline constexpr std::size_t size() { + return sizeof...(Rest) + 1; + } + + public: + template + void run_type_at(Executor& executor, std::int32_t idx) { + if (idx == 0) { + return executor.read_type(value_); + } + return ParserArgs::run_type_at(executor, idx - 1); + } + + public: + template + inline std::optional get_index_of_current_named_arg(buf::StreamView& format, std::int32_t begin_search_index) { + if constexpr (detail::IsANamedArgs>::value) { + bool current_is_a_named_arg = buf::FMTParamsManip(format).next_is_named_args(value_.get_name()); + if (current_is_a_named_arg) return begin_search_index; + } + return ParserArgs::get_index_of_current_named_arg(format, begin_search_index + 1); + } + + public: + inline PointerID get_pointerid_at(std::int32_t idx) { + if (idx == 0) return PointerID{.type_info = typeid(TypeWithoutRef), .ptr = static_cast(&value_)}; + return ParserArgs::get_pointerid_at(idx - 1); + } + + public: + template + inline T get_converted_type_at(std::int32_t idx) { + if (idx == 0) { + if constexpr (FMTCanContextConvert) { + return FMTContextConvert::convert(value_); + } else { + throw std::runtime_error("fmt error: ArgsInterface_InvalidConversion"); + } + } + return ParserArgs::template get_converted_type_at(idx - 1); + } + }; + + + /********************************/ + /******** Args interface ********/ + /********************************/ + template + class ParserArgsInterface : public BasicArgsInterface { + public: + using ContextArgsType = ParserArgs; + + public: + ParserArgsInterface(ParserExecutor& executor, Args&&... args) : BasicArgsInterface(), executor(executor), args_interface(std::forward(args)...) {} + ~ParserArgsInterface() override = default; + + public: + std::size_t size() override { + return args_interface.size(); + } + + public: + void run_type_at(std::int32_t idx) override { + return args_interface.run_type_at(executor, idx); + } + std::optional get_index_of_current_named_arg(buf::StreamView& format) override { + return args_interface.get_index_of_current_named_arg(format, std::int32_t{0}); + } + inline PointerID get_pointerid_at(std::int32_t idx) override { + return args_interface.get_pointerid_at(idx); + } + + public: + typename std::basic_string_view get_string_at(std::int32_t idx) override { + return args_interface.template get_converted_type_at>(idx); + } + std::int64_t get_int_at(std::int32_t idx) override { + return args_interface.template get_converted_type_at(idx); + } + + protected: + ParserExecutor& executor; + ContextArgsType args_interface; + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/parser_executor/parser_text_properties_executor/parser_text_properties_executor.hxx b/src/stream/fmt/context/parser_executor/parser_text_properties_executor/parser_text_properties_executor.hxx new file mode 100644 index 00000000..66067e1b --- /dev/null +++ b/src/stream/fmt/context/parser_executor/parser_text_properties_executor/parser_text_properties_executor.hxx @@ -0,0 +1,64 @@ +#pragma once + +#include "stream/fmt/context/basic_context/text_properties_executor.hxx" +#include "stream/fmt/detail/prelude.hxx" +#include "stream/fmt/context/parser_executor/basic_parser_executor.hxx" + +namespace stream::fmt::detail { + template + class IParserTextPropertiesExecutor : public ITextPropertiesExecutor { + public: + IParserTextPropertiesExecutor() = default; + ~IParserTextPropertiesExecutor() override = default; + + void link_to_executor(void* executor) override { + buffer = &reinterpret_cast*>(executor)->istream; + } + + protected: + buf::StreamView* buffer{nullptr}; + }; +} // namespace stream::fmt::detail + +namespace stream::fmt::detail { + template + class ParserNOTextPropertiesExecutor : public IParserTextPropertiesExecutor { + public: + ParserNOTextPropertiesExecutor() = default; + ~ParserNOTextPropertiesExecutor() override = default; + + using IParserTextPropertiesExecutor::buffer; + + public: + void all_properties_reset() override {} + + public: + void reset_color() override {} + void execute_color(const detail::TextProperties::TextColor::BasicColorFG&) override {} + void execute_color(const detail::TextProperties::TextColor::BasicColorBG&) override {} + void execute_color(const detail::TextProperties::TextColor::BasicColor&) override {} + void execute_color(const detail::TextProperties::TextColor::Color24bFG&) override {} + void execute_color(const detail::TextProperties::TextColor::Color24bBG&) override {} + void execute_color(const detail::TextProperties::TextColor::Color24b&) override {} + void execute_color(const detail::TextProperties::TextColor::ColorCubeFG&) override {} + void execute_color(const detail::TextProperties::TextColor::ColorCubeBG&) override {} + void execute_color(const detail::TextProperties::TextColor::ColorCube&) override {} + + public: + void reset_front() override {} + void execute_front(const detail::TextProperties::TextFront::FrontID&) override {} + + public: + void reset_style() override {} + void execute_style(const detail::TextProperties::TextStyle::Intensity&) override {} + void execute_style(const detail::TextProperties::TextStyle::Italic&) override {} + void execute_style(const detail::TextProperties::TextStyle::Underline&) override {} + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::Color&) override {} + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::ColorCube&) override {} + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::Color24b&) override {} + void execute_style(const detail::TextProperties::TextStyle::Blink&) override {} + void execute_style(const detail::TextProperties::TextStyle::Inverted&) override {} + void execute_style(const detail::TextProperties::TextStyle::Ideogram&) override {} + void execute_style(const detail::TextProperties::TextStyle::Script&) override {} + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/parser_executor/parser_text_properties_executor/parser_text_properties_executor_ansi.hxx b/src/stream/fmt/context/parser_executor/parser_text_properties_executor/parser_text_properties_executor_ansi.hxx new file mode 100644 index 00000000..788058d0 --- /dev/null +++ b/src/stream/fmt/context/parser_executor/parser_text_properties_executor/parser_text_properties_executor_ansi.hxx @@ -0,0 +1,118 @@ +#pragma once + +#include "parser_text_properties_executor.hxx" + +namespace stream::fmt::detail { + template + class ParserANSITextPropertiesExecutor : public IParserTextPropertiesExecutor { + public: + ParserANSITextPropertiesExecutor() = default; + ~ParserANSITextPropertiesExecutor() override = default; + + using IParserTextPropertiesExecutor::buffer; + + public: + void all_properties_reset() override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', 0, 'm');*/ + } + + public: + void reset_color() override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', 39, ';', 49, 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::BasicColorFG&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::BasicColorBG&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::BasicColor&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t.fg) , ';', static_cast(t.bg), 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::Color24bFG&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[38;2;", t.r, ';', t.g, ';', t.b, 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::Color24bBG&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[48;2;", t.r, ';', t.g, ';', t.b, 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::Color24b&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[38;2;", t.fg.r, ';', t.fg.g, ';', t.fg.b, "; 48; 2;", t.bg.r, ';', t.bg.g, ';', t.bg.b, 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::ColorCubeFG&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[38;5;", t.get_color_ref(), 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::ColorCubeBG&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[48;5;", t.get_color_ref(), 'm');*/ + } + void execute_color(const detail::TextProperties::TextColor::ColorCube&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[48;5;", t.fg.get_color_ref(), ";48;5;", t.bg.get_color_ref(), 'm');*/ + } + + public: + void reset_front() override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', detail::TextProperties::TextFront::FrontID::DefaultFrontID, 'm');*/ + } + void execute_front(const detail::TextProperties::TextFront::FrontID&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', t.id, 'm');*/ + } + + public: + void reset_style() override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', 0, 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::Intensity&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::Italic&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::Underline&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::Color&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[59m");*/ + } + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::ColorCube&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[58;5;", t.get_color_ref(), 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::UnderlineColor::Color24b&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType("\033[58;2;", t.r, ';', t.g, ';', t.b, 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::Blink&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::Inverted&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::Ideogram&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + void execute_style(const detail::TextProperties::TextStyle::Script&) override { + throw std::runtime_error("fmt error: FunctionNotImpl"); + /*ReadManip(buffer).BasicReadType('\033', '[', static_cast(t), 'm');*/ + } + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/context/parser_executor/parser_type.hxx b/src/stream/fmt/context/parser_executor/parser_type.hxx new file mode 100644 index 00000000..70ea460a --- /dev/null +++ b/src/stream/fmt/context/parser_executor/parser_type.hxx @@ -0,0 +1,33 @@ +#pragma once + +#include "stream/fmt/detail/prelude.hxx" + +#define STREAMFORMAT_PARSER_DECLARED +namespace stream::fmt { + template > + struct ParserType { + static inline bool parse(T&, ParserExecutor&) { +#ifdef UNKOWN_TYPE_MESSAGE + // FIXME + STREAMFORMAT_DEBUGBREAK(); + // static_cast(false); +#endif +#ifdef UNKOWN_TYPE_FAIL + static_cast(false); +#endif +#ifdef UNKOWN_TYPE_DEBUG + STREAMFORMAT_DEBUGBREAK(); +#endif + return false; + } + }; + +} // namespace stream::fmt + +#define STREAMFORMAT_AUTO_PARSER(type, fmt, ...) \ + template \ + struct stream::fmt::ParserType { \ + static bool parse(Type& value, ParserExecutor& executor) { \ + return executor.run(fmt, __VA_ARGS__); \ + } \ + }; diff --git a/src/stream/fmt/context/parser_executor/utility_functions.hxx b/src/stream/fmt/context/parser_executor/utility_functions.hxx new file mode 100644 index 00000000..87e468cf --- /dev/null +++ b/src/stream/fmt/context/parser_executor/utility_functions.hxx @@ -0,0 +1,22 @@ +#pragma once + +#include "basic_parser_executor.hxx" + +#include "stream/fmt/buf/streamio_manager/given_streamio_manager.hxx" +#include "stream/fmt/buf/streamio_manager/static_streamio_manager.hxx" + +#include "parser_text_properties_executor/parser_text_properties_executor_ansi.hxx" + +namespace stream::fmt { + template + void parse(Buffer&& buffer_input, Format&& format_input, Args&&... args) { + buf::StreamView buffer{buffer_input}; + buf::StreamView format{format_input}; + using TChar = typename decltype(format)::TChar; + + detail::ParserNOTextPropertiesExecutor> text_properties_executor; + context::BasicParserExecutor> executor(buffer, text_properties_executor); + executor.run(format, std::forward(args)...); + return executor.terminate(); + } +} // namespace stream::fmt diff --git a/src/stream/fmt/detail/convert_traits.hxx b/src/stream/fmt/detail/convert_traits.hxx new file mode 100644 index 00000000..f560549a --- /dev/null +++ b/src/stream/fmt/detail/convert_traits.hxx @@ -0,0 +1,56 @@ +#pragma once + +#include "prelude.hxx" + +namespace stream::fmt::detail { + template + struct FormatTypeForwardAs { + using type = T; + }; + + template + struct FMTContextConvert { + static constexpr bool is_convertible = false; + }; + + template + requires(std::is_convertible_v && std::is_convertible_v) + struct FMTContextConvert { + static constexpr bool is_convertible = true; + static constexpr To convert(const From& from) { + return static_cast(from); + } + }; + + template + requires(std::is_convertible_v && std::is_convertible_v) + struct FMTContextConvert { + static constexpr bool is_convertible = true; + static constexpr std::int32_t convert(const From& from) { + return std::int32_t(static_cast(from)); + } + }; + + template + concept FMTCanContextConvert = requires(const From& from) { + requires FMTContextConvert::is_convertible; + { FMTContextConvert::convert(from) } -> std::same_as; + }; + + template + struct FMTContextSame { + static constexpr bool same_as = false; + }; + + template + requires(std::is_same_v, detail::get_base_type>) + struct FMTContextSame { + static constexpr bool same_as = true; + }; + + template + concept fmt_is_context_same = requires(To* to, const From& from) { + requires FMTContextSame::same_as; + *to = from; + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/detail/indent_handlers.hxx b/src/stream/fmt/detail/indent_handlers.hxx new file mode 100644 index 00000000..930d6247 --- /dev/null +++ b/src/stream/fmt/detail/indent_handlers.hxx @@ -0,0 +1,18 @@ +#pragma once + +#include "stream/fmt/detail/prelude.hxx" +#include "stream/fmt/buf/fmt_manip_io.hxx" + +namespace stream::fmt::detail { + template + struct NoStrideFunction { + inline explicit NoStrideFunction(buf::FMTStreamIO& buffer_) : buffer(buffer_), size_buffer(buffer_.get_buffer_current_size()) {} + + ~NoStrideFunction() { + buf::FMTManipIO(buffer).add_no_stride(buffer.get_buffer_current_size() - size_buffer); + } + + buf::FMTStreamIO& buffer; + std::size_t size_buffer; + }; +} // namespace stream::fmt::detail diff --git a/src/StreamFormat/FMT/Detail/Detail.h b/src/stream/fmt/detail/prelude.hxx similarity index 69% rename from src/StreamFormat/FMT/Detail/Detail.h rename to src/stream/fmt/detail/prelude.hxx index 7efa6c34..217ac2d9 100644 --- a/src/StreamFormat/FMT/Detail/Detail.h +++ b/src/stream/fmt/detail/prelude.hxx @@ -1,12 +1,7 @@ #pragma once -#include "StreamFormat/Core/Core.h" - -#include "TypesTraits.h" - -#include "Exception.h" -#include "IndentHandlers.h" -#include "Specifiers.h" +#include "stream/core/prelude.hxx" +#include "types_traits.hxx" #define UNKOWN_TYPE_MESSAGE @@ -16,7 +11,7 @@ // // Macro PackSave ; PackSave (foreshadowing for constexpr) // -// TOKENIZER bufferIn +// TOKENIZER istream // // GLOBBER // @@ -28,16 +23,15 @@ // End writing all writer and reader (string / char pt) // -namespace StreamFormat::FMT::Context -{ +namespace stream::fmt::context { template class BasicContext; template class BasicFormatterExecutor; - struct ParserContextError; + struct ParserFMTError; template class BasicParserExecutor; -} +} // namespace stream::fmt::context diff --git a/src/stream/fmt/detail/specifiers.hxx b/src/stream/fmt/detail/specifiers.hxx new file mode 100644 index 00000000..5f1a46d6 --- /dev/null +++ b/src/stream/fmt/detail/specifiers.hxx @@ -0,0 +1,191 @@ +#pragma once + +#include "stream/core/prelude.hxx" +#include "stream/core/prelude.hxx" + +#include +#include +#include + +namespace stream::fmt::detail { + enum class IntegerPrintBase : char { + Dec = 'd', + Bin = 'b', + BinUpper = 'B', + Hex = 'x', + HexUpper = 'X', + Oct = 'o', + OctUpper = 'O', + }; + + struct ShiftInfo { + public: + enum class ShiftType : std::int8_t { + Nothing, + Right, + Left, + CenterRight, + CenterLeft, + Default = Nothing + }; + + struct ShiftPrint { + public: + constexpr ShiftPrint() : before(' '), after(' ') {} + + constexpr ShiftPrint(char c) : before(c), after(c) {} + + constexpr ShiftPrint(char before, char after) : before(before), after(after) {} + + public: + char before = ' '; + char after = ' '; + + public: + constexpr bool before_is_a_digit() const { + return before >= '0' && before <= '9'; + } + }; + + public: + ShiftType type = ShiftType::Default; // < - > - ^ + ShiftPrint print = ShiftPrint{}; // 0 - ' ' - * ..... + std::int32_t size = -1; // ? - ^? + }; +} // namespace stream::fmt::detail + +namespace stream::fmt::detail { + template + struct FormatSpecifier { + FormatSpecifier() : name(nullptr, 0), as_text(nullptr, 0), as_number(0), has_text(false), has_number(false) {} + + FormatSpecifier(std::basic_string_view name) : name(name), as_text(nullptr, 0), as_number(0), has_text(false), has_number(false) {} + + FormatSpecifier(std::basic_string_view name, std::basic_string_view value) : name(name), as_text(value), as_number(0), has_text(true), has_number(false) {} + + FormatSpecifier(std::basic_string_view name, const std::int32_t value) : name(name), as_text(nullptr, 0), as_number(value), has_text(false), has_number(true) {} + + FormatSpecifier(std::basic_string_view name, const std::int32_t value_as_number, std::basic_string_view value_as_text) + : name(name), as_text(value_as_text), as_number(value_as_number), has_text(true), has_number(true) {} + + std::basic_string_view name = ""; + std::basic_string_view as_text = ""; + std::int32_t as_number = 0; + bool has_text = false; + bool has_number = false; + }; + + template + struct FormatSpecifierList { + public: + std::uint8_t specifier_count = 0; + std::array, SIZE> specifiers{}; + + struct Constraint { + bool has_text = false; + bool has_number = false; + }; + + public: + FormatSpecifier* get(std::basic_string_view name, const Constraint& constraint = Constraint{}) { + STREAMFORMAT_ASSERT(specifier_count <= SIZE); + for (std::uint8_t i = 0; i < specifier_count; ++i) + if (specifiers[i].name == name) { + bool text_contraint_satisfied = !constraint.has_text || specifiers[i].has_text; + bool number_contraint_satisfied = !constraint.has_number || specifiers[i].has_number; + if (text_contraint_satisfied && number_contraint_satisfied) return &specifiers[i]; + } + return nullptr; + } + + const FormatSpecifier* get(std::basic_string_view name, const Constraint& constraint = Constraint{}) const { + STREAMFORMAT_ASSERT(specifier_count <= SIZE); + for (std::uint8_t i = 0; i < specifier_count; ++i) + if (specifiers[i].name == name) { + bool text_contraint_satisfied = !constraint.has_text || specifiers[i].has_text; + bool number_contraint_satisfied = !constraint.has_number || specifiers[i].has_number; + if (text_contraint_satisfied && number_contraint_satisfied) return &specifiers[i]; + } + return nullptr; + } + + bool has(std::basic_string_view name) const { + return get(name) != nullptr; + } + + std::int32_t get_as_number(std::basic_string_view name, std::int32_t default_value) const { + const FormatSpecifier* getptr = get(name, Constraint{.has_number = true}); + if (getptr == nullptr || !getptr->has_number) return default_value; + return getptr->as_number; + } + + std::basic_string_view get_as_text(std::basic_string_view name, std::basic_string_view default_value) const { + const FormatSpecifier* getptr = get(name, Constraint{.has_text = true}); + if (getptr == nullptr || !getptr->has_text) return default_value; + return getptr->as_text; + } + + public: + void pushback(const FormatSpecifier& specifier) { + if (specifier_count >= SIZE) throw std::runtime_error("fmt error: Specifiers_Full"); + specifiers[specifier_count++] = specifier; + } + + void concat(const FormatSpecifier& specifier) { + FormatSpecifier* local = get(specifier.name); + if (local == nullptr) return pushback(specifier); + + if (specifier.has_text) { + local->has_text = true; + local->as_text = specifier.as_text; + } + if (specifier.has_number) { + local->has_number = true; + local->as_number = specifier.as_number; + } + } + }; + + template + struct FormatData { + public: + bool has_spec = false; + bool keep_new_style = false; // W + + bool prefix_suffix = false; // # + IntegerPrintBase integer_print = IntegerPrintBase::Dec; // b - X - O - D + std::int32_t float_precision = -1; // . + ShiftInfo shift; + + FormatSpecifierList specifiers; + + std::basic_string_view next_override = std::basic_string_view(nullptr, 0); + + public: + void apply(const FormatData& given) { + *this = given; + } + + void apply(const IntegerPrintBase& given) { + integer_print = given; + } + void apply(const ShiftInfo& given) { + shift = given; + } + void apply(const FormatSpecifier& given) { + specifiers.concat(given); + } + + template + bool testapply(const T* given) + requires requires(const T& value, FormatData& data) { data.apply(value); } + { + if (given == nullptr) return false; + apply(*given); + return true; + } + }; + + template + concept format_data_can_apply = requires(const T& value, FormatData& data) { data.apply(value); }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/detail/types_traits.hxx b/src/stream/fmt/detail/types_traits.hxx new file mode 100644 index 00000000..5bab1ed3 --- /dev/null +++ b/src/stream/fmt/detail/types_traits.hxx @@ -0,0 +1,17 @@ +#pragma once + +#include "stream/core/prelude.hxx" + +#include + +namespace stream::fmt::detail { + template + using get_base_type = std::remove_cv_t>; + + template + struct IsCharType { + using BaseType = get_base_type; + static constexpr bool value = std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; + }; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/serializers/compilation_data.hxx b/src/stream/fmt/serializers/compilation_data.hxx new file mode 100644 index 00000000..4821a283 --- /dev/null +++ b/src/stream/fmt/serializers/compilation_data.hxx @@ -0,0 +1,50 @@ +#pragma once + +#include "stream/core/prelude.hxx" +#include "stream/flog.hxx" + +namespace stream::fmt::detail { + struct FileLocation { + FileLocation(std::string_view file_name_, int file_line_ = 0) : file_name(file_name_), file_line(file_line_) {} + + std::string_view file_name; // __FILE__ + int file_line; // __LINE__ + }; + + struct FunctionProperties { + FunctionProperties(std::string_view file_name_, int file_line_ = 0, std::string_view functionName = "", std::string_view function_signature_ = "", + std::string_view function_assembly_name_ = "") + : location(file_name_, file_line_), function_name(functionName), function_signature(function_signature_), function_assembly_name(function_assembly_name_) {} + + FunctionProperties(FileLocation location, std::string_view functionName = "", std::string_view function_signature_ = "", std::string_view function_assembly_name_ = "") + : location(location), function_name(functionName), function_signature(function_signature_), function_assembly_name(function_assembly_name_) {} + + FileLocation location; + std::string_view function_name; // __FUNCTION__ + std::string_view function_signature; // __FUNCSIG__ -- __PRETTY_FUNCTION__ + std::string_view function_assembly_name; // __FUNCDNAME__ + }; +} // namespace stream::fmt::detail + +#define STREAMFORMAT_FMT_FILE_LOCATION() stream::fmt::detail::FileLocation(__FILE__, __LINE__) +#define STREAMFORMAT_FMT_FUNCTION_PROPERTIES() stream::fmt::detail::FunctionProperties(STREAMFORMAT_FMT_FILE_LOCATION(), __FUNCTION__, __FUNCSIG__, __FUNCDNAME__) + +namespace stream::fmt { + template + struct FormatterType { + static inline void format(const detail::FileLocation& t, FormatterExecutor& executor) { + executor.write_type(t.file_name); + executor.ostream.pushback(':'); + return executor.write_type(t.file_line); + } + }; + + template + struct FormatterType { + static inline void format(const detail::FunctionProperties& t, FormatterExecutor& executor) { + executor.write_type(t.location); + executor.ostream.write_char_array(" @ "); + return executor.write_type(t.function_name); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/format_chrono.hxx b/src/stream/fmt/serializers/format_chrono.hxx new file mode 100644 index 00000000..0496b025 --- /dev/null +++ b/src/stream/fmt/serializers/format_chrono.hxx @@ -0,0 +1,132 @@ +#pragma once + +#include "stream/fmt/buf/test_manip.hxx" +#include "stream/fmt/buf/write_manip.hxx" +#include "stream/fmt/buf/read_manip.hxx" +#include "stream/fmt/buf/fmt_write_manip.hxx" + +#include "stream/fmt/context/formatter_executor/basic_formatter_executor.hxx" + +#include + +namespace stream::fmt::detail { + enum class TimePrintMode : std::uint8_t { + FullTime, + Mod, + Sub, + }; + + template + void write_sub_time_(const std::chrono::time_point& value, buf::StreamView& pattern, buf::FMTStreamIO& buffer, TimePrintMode mode) { + ShiftInfo shift; + shift.type = detail::ShiftInfo::ShiftType::Right; + shift.print = detail::ShiftInfo::ShiftPrint('0', ' '); + shift.size = 0; + if (buf::TestAccess(pattern).is_a_digit()) { + buf::ReadManip(pattern).fast_read_integer(shift.size); + } + + if (mode == TimePrintMode::Mod && shift.size < 0) shift.size = 3; + + if (buf::TestAccess(pattern).is_same("ns", 2)) { + buf::Manip(pattern).forward(2); + std::uint32_t ns = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); + if (mode == TimePrintMode::Mod) ns = ns % 1000; + buf::FMTWriteManip(buffer).write_integer(static_cast(ns) % 1000, shift); + } else if (buf::TestAccess(pattern).is_same("us", 2)) { + buf::Manip(pattern).forward(2); + std::uint32_t us = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); + if (mode == TimePrintMode::Mod) + us = us % 1000; + else if (mode == TimePrintMode::Sub) + us = us / 1000; + buf::FMTWriteManip(buffer).write_integer(static_cast(us) % 1000, shift); + } else if (buf::TestAccess(pattern).is_same("ms", 2)) { + buf::Manip(pattern).forward(2); + std::uint32_t ms = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); + if (mode == TimePrintMode::Mod) + ms = ms % 1000; + else if (mode == TimePrintMode::Sub) + ms = ms / 1000000; + buf::FMTWriteManip(buffer).write_integer(static_cast(ms) % 1000, shift); + } else if (buf::TestAccess(pattern).is_equal_to('s')) { + buf::Manip(pattern).forward(); + std::uint32_t sec = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); + if (mode == TimePrintMode::Mod) + sec = sec % 60; + else if (mode == TimePrintMode::Sub) + sec = sec / 1000000000; + buf::FMTWriteManip(buffer).write_integer(static_cast(sec) % 1000, shift); + } else if (buf::TestAccess(pattern).is_equal_to('m')) { + buf::Manip(pattern).forward(); + std::uint32_t min = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); + if (mode == TimePrintMode::Mod) min = min % 60; + buf::FMTWriteManip(buffer).write_integer(static_cast(min) % 1000, shift); + } else if (buf::TestAccess(pattern).is_equal_to('h')) { + buf::Manip(pattern).forward(); + std::uint32_t hours = static_cast(std::chrono::time_point_cast(value).time_since_epoch().count()); + if (mode == TimePrintMode::Mod) hours = hours % 24; + buf::FMTWriteManip(buffer).write_integer(static_cast(hours) % 1000, shift); + } + } + + template + void write_time(const std::chrono::time_point& value, buf::StreamView pattern, buf::FMTStreamIO& buffer) { + if (buf::TestAccess(pattern).is_same("default", true) == true) { + buf::Manip(pattern).reload("%2h:%2m:%2s:%3ms"); + } + + auto view = buf::TestManip(pattern).view_exec([&] { buf::FMTParamsManip(pattern).param_go_to('%', '#', '/'); }); + buf::WriteManip(buffer).fast_write_sv(view); + + while (!pattern.is_end_of_string()) { + TimePrintMode mode; + if (buf::TestAccess(pattern).is_equal_to('%')) + mode = TimePrintMode::Mod; + else if (buf::TestAccess(pattern).is_equal_to('#')) + mode = TimePrintMode::FullTime; + else if (buf::TestAccess(pattern).is_equal_to('/')) + mode = TimePrintMode::Sub; + + buf::Manip(pattern).forward(); + write_sub_time_(value, pattern, buffer, mode); + + auto view = buf::TestManip(pattern).view_exec([&] { buf::FMTParamsManip(pattern).param_go_to('%', '#', '/'); }); + buf::WriteManip(buffer).fast_write_sv(view); + } + } +} // namespace stream::fmt::detail + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static inline void format(const std::chrono::time_point& t, FormatterExecutor& executor) { + return detail::write_time(t, buf::StreamView(executor.data.specifiers.get_as_text("pattern", "default")), executor.ostream); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static inline void format(const std::chrono::duration& t, FormatterExecutor& executor) { + if (executor.data.specifiers.has("pattern")) { + return detail::write_time(std::chrono::time_point>(t), + buf::StreamView(executor.data.specifiers.get_as_text("pattern", "default")), executor.ostream); + } + buf::WriteManip(executor.ostream).fast_write_integer(t.count()); + + if constexpr (std::is_same_v, std::chrono::seconds>) { + buf::ManipIO(executor.ostream).pushback('s'); + } else if constexpr (std::is_same_v, std::chrono::minutes>) { + buf::ManipIO(executor.ostream).pushback('m'); + } else if constexpr (std::is_same_v, std::chrono::hours>) { + buf::ManipIO(executor.ostream).pushback('h'); + } else if constexpr (std::is_same_v, std::chrono::milliseconds>) { + buf::ManipIO(executor.ostream).pushback('m', 's'); + } else if constexpr (std::is_same_v, std::chrono::microseconds>) { + buf::ManipIO(executor.ostream).pushback('u', 's'); + } else if constexpr (std::is_same_v, std::chrono::nanoseconds>) { + buf::ManipIO(executor.ostream).pushback('n', 's'); + } + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/format_stdlib.hxx b/src/stream/fmt/serializers/format_stdlib.hxx new file mode 100644 index 00000000..92f19b71 --- /dev/null +++ b/src/stream/fmt/serializers/format_stdlib.hxx @@ -0,0 +1,69 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/basic_formatter_executor.hxx" + +#include +#include +#include +#include + +namespace stream::fmt { + //------------------------------------------// + //----------------- String -----------------// + //------------------------------------------// + + template + struct FormatterType, FormatterExecutor> { + static inline void format(const std::basic_string& t, FormatterExecutor& executor) { + return buf::WriteManip(executor.ostream).fast_write_sv(t); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static inline void format(std::basic_string_view t, FormatterExecutor& executor) { + return buf::WriteManip(executor.ostream).fast_write_sv(t); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static inline void format(const std::basic_stringstream& t, FormatterExecutor& executor) { + return buf::WriteManip(executor.ostream).fast_write_sv(std::basic_string_view(t.str(), t.size())); + } + }; + + //------------------------------------------// + //----------------- Memory -----------------// + //------------------------------------------// + + // UniquePtr + template + struct FormatterType, FormatterExecutor> { + static inline void format(const std::unique_ptr& t, FormatterExecutor& executor) { + if (executor.data.TrueValue) + return FormatterType::format(t.get(), executor); + else + return FormatterType::format(*t, executor); + } + }; + + // SharedPtr + template + struct FormatterType, FormatterExecutor> { + static inline void format(const std::shared_ptr& t, FormatterExecutor& executor) { + if (executor.data.TrueValue) + return FormatterType::format(t.get(), executor); + else + return FormatterType::format(*t, executor); + } + }; + + // WeakPtr + template + struct FormatterType, FormatterExecutor> { + static inline void format(const std::weak_ptr& t, FormatterExecutor& executor) { + return FormatterType, FormatterExecutor>::format(t.lock(), executor); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/parse_chrono.hxx b/src/stream/fmt/serializers/parse_chrono.hxx new file mode 100644 index 00000000..d88280e3 --- /dev/null +++ b/src/stream/fmt/serializers/parse_chrono.hxx @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "stream/fmt/context/parser_executor/basic_parser_executor.hxx" + +namespace stream::fmt::detail {} + +namespace stream::fmt {} diff --git a/src/stream/fmt/serializers/parse_stdlib.hxx b/src/stream/fmt/serializers/parse_stdlib.hxx new file mode 100644 index 00000000..ed988593 --- /dev/null +++ b/src/stream/fmt/serializers/parse_stdlib.hxx @@ -0,0 +1,7 @@ +#pragma once + +#include "stream/fmt/context/parser_executor/basic_parser_executor.hxx" + +#include +#include +#include diff --git a/src/stream/fmt/serializers/std_container/array.hxx b/src/stream/fmt/serializers/std_container/array.hxx new file mode 100644 index 00000000..863a8c3e --- /dev/null +++ b/src/stream/fmt/serializers/std_container/array.hxx @@ -0,0 +1,15 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::array& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/deque.hxx b/src/stream/fmt/serializers/std_container/deque.hxx new file mode 100644 index 00000000..b23111e5 --- /dev/null +++ b/src/stream/fmt/serializers/std_container/deque.hxx @@ -0,0 +1,15 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::deque& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/forward_list.hxx b/src/stream/fmt/serializers/std_container/forward_list.hxx new file mode 100644 index 00000000..bbf6b5ba --- /dev/null +++ b/src/stream/fmt/serializers/std_container/forward_list.hxx @@ -0,0 +1,15 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::forward_list& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/list.hxx b/src/stream/fmt/serializers/std_container/list.hxx new file mode 100644 index 00000000..74462f46 --- /dev/null +++ b/src/stream/fmt/serializers/std_container/list.hxx @@ -0,0 +1,15 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::list& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/map.hxx b/src/stream/fmt/serializers/std_container/map.hxx new file mode 100644 index 00000000..780477a6 --- /dev/null +++ b/src/stream/fmt/serializers/std_container/map.hxx @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include "tuple.hxx" + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::map& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static void format(const std::multimap& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/queue.hxx b/src/stream/fmt/serializers/std_container/queue.hxx new file mode 100644 index 00000000..8d4220d1 --- /dev/null +++ b/src/stream/fmt/serializers/std_container/queue.hxx @@ -0,0 +1,13 @@ +#pragma once + +#include +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::queue& /*t*/, FormatterExecutor& /*executor*/) { + throw std::runtime_error("fmt error: FunctionNotImpl"); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/set.hxx b/src/stream/fmt/serializers/std_container/set.hxx new file mode 100644 index 00000000..d3b6bf91 --- /dev/null +++ b/src/stream/fmt/serializers/std_container/set.hxx @@ -0,0 +1,22 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::set& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static void format(const std::multiset& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_stack.h b/src/stream/fmt/serializers/std_container/stack.hxx similarity index 52% rename from src/StreamFormat/FMT/Serializers/STDContainer/FMT_stack.h rename to src/stream/fmt/serializers/std_container/stack.hxx index d46dc35a..920ce5c3 100644 --- a/src/StreamFormat/FMT/Serializers/STDContainer/FMT_stack.h +++ b/src/stream/fmt/serializers/std_container/stack.hxx @@ -1,15 +1,14 @@ #pragma once #include -#include "StreamFormat/FMT/Context/FormatterExecutor/FormatterType.h" +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" -namespace StreamFormat::FMT -{ +namespace stream::fmt { /* template struct FormatterType, FormatterExecutor> { - static void Format(const std::stack& t, FormatterExecutor& executor) { + static inline void format(const std::stack& t, FormatterExecutor& executor) { } }; */ diff --git a/src/stream/fmt/serializers/std_container/tuple.hxx b/src/stream/fmt/serializers/std_container/tuple.hxx new file mode 100644 index 00000000..bc2aceb5 --- /dev/null +++ b/src/stream/fmt/serializers/std_container/tuple.hxx @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" + +namespace stream::fmt::tuple_detail { + template + using NthTypeOf = typename std::tuple_element>::Type; + + template + constexpr NthTypeOf& get(Args&&... args) { + std::tuple tuple(std::forward(args)...); + return std::get(tuple); + } + + template + static inline void tuple_format_rec(FormatterExecutor& executor) {} + + template + static inline void tuple_format_rec(FormatterExecutor& executor, const T& t) { + return executor.write_type(t); + } + + template + static inline void tuple_format_rec(FormatterExecutor& executor, const T& t, Args&&... args) { + executor.write_type(t); + executor.ostream.pushback(','); + executor.ostream.pushback(' '); + return tuple_format_rec(executor, std::forward(args)...); + } +} // namespace stream::fmt::tuple_detail + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::tuple& t, FormatterExecutor& executor) { + executor.ostream.pushback('<'); + std::apply([&executor](auto&&... args) { auto&& res = tuple_detail::tuple_format_rec(executor, args...); }, t); + executor.ostream.pushback('>'); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static void format(const std::pair& t, FormatterExecutor& executor) { + executor.ostream.pushback('<'); + executor.write_type(t.first); + executor.ostream.pushback(':'); + executor.write_type(t.second); + executor.ostream.pushback('>'); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/unordered_map.hxx b/src/stream/fmt/serializers/std_container/unordered_map.hxx new file mode 100644 index 00000000..4434f1d2 --- /dev/null +++ b/src/stream/fmt/serializers/std_container/unordered_map.hxx @@ -0,0 +1,23 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include +#include "tuple.hxx" + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::unordered_map& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static void format(const std::unordered_multimap& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/unordered_set.hxx b/src/stream/fmt/serializers/std_container/unordered_set.hxx new file mode 100644 index 00000000..2e92383b --- /dev/null +++ b/src/stream/fmt/serializers/std_container/unordered_set.hxx @@ -0,0 +1,22 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::unordered_set& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; + + template + struct FormatterType, FormatterExecutor> { + static void format(const std::unordered_multiset& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/stream/fmt/serializers/std_container/vector.hxx b/src/stream/fmt/serializers/std_container/vector.hxx new file mode 100644 index 00000000..11387dff --- /dev/null +++ b/src/stream/fmt/serializers/std_container/vector.hxx @@ -0,0 +1,15 @@ +#pragma once + +#include "stream/fmt/context/formatter_executor/formatter_type.hxx" +#include "stream/fmt/context/formatter_executor/forwarders.hxx" + +#include + +namespace stream::fmt { + template + struct FormatterType, FormatterExecutor> { + static void format(const std::vector& t, FormatterExecutor& executor) { + detail::forwarders::format_span(std::span(t), executor); + } + }; +} // namespace stream::fmt diff --git a/src/StreamFormat/FMT/TextProperties/BaseTextProperties.h b/src/stream/fmt/text_properties/base_text_properties.hxx similarity index 54% rename from src/StreamFormat/FMT/TextProperties/BaseTextProperties.h rename to src/stream/fmt/text_properties/base_text_properties.hxx index de5eecad..fe97a3cf 100644 --- a/src/StreamFormat/FMT/TextProperties/BaseTextProperties.h +++ b/src/stream/fmt/text_properties/base_text_properties.hxx @@ -1,16 +1,12 @@ #pragma once -#include "StreamFormat/Core/Core.h" +#include "stream/core/prelude.hxx" // According to : https://en.wikipedia.org/wiki/ANSI_escape_code -namespace StreamFormat::FMT::Detail -{ - struct TextProperties - { - struct ResetProperties - { - }; +namespace stream::fmt::detail { + struct TextProperties { + struct ResetProperties {}; struct TextColor; struct TextStyle; @@ -18,4 +14,4 @@ namespace StreamFormat::FMT::Detail struct Properties; }; -} +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/text_properties/text_properties.hxx b/src/stream/fmt/text_properties/text_properties.hxx new file mode 100644 index 00000000..7401317e --- /dev/null +++ b/src/stream/fmt/text_properties/text_properties.hxx @@ -0,0 +1,17 @@ +#pragma once + +#include "text_properties_color.hxx" +#include "text_properties_front.hxx" +#include "text_properties_style.hxx" + +namespace stream::fmt::detail { + struct TextProperties::Properties { + TextProperties::TextColor::Color color; + TextProperties::TextStyle::Style style; + TextProperties::TextFront::Front front; + }; + + inline bool operator==(const TextProperties::Properties& lhs, const TextProperties::Properties& rhs) { + return lhs.color == rhs.color && lhs.style == rhs.style && lhs.front == rhs.front; + } +} // namespace stream::fmt::detail diff --git a/src/StreamFormat/FMT/TextProperties/TextPropertiesColor.h b/src/stream/fmt/text_properties/text_properties_color.hxx similarity index 51% rename from src/StreamFormat/FMT/TextProperties/TextPropertiesColor.h rename to src/stream/fmt/text_properties/text_properties_color.hxx index bb8cdf5c..c5867c43 100644 --- a/src/StreamFormat/FMT/TextProperties/TextPropertiesColor.h +++ b/src/stream/fmt/text_properties/text_properties_color.hxx @@ -1,14 +1,10 @@ #pragma once -#include "BaseTextProperties.h" - -namespace StreamFormat::FMT::Detail -{ - struct TextProperties::TextColor - { - struct ResetColor - { - }; +#include "base_text_properties.hxx" + +namespace stream::fmt::detail { + struct TextProperties::TextColor { + struct reset_color {}; enum class BasicColorFG : std::uint8_t; enum class BasicColorBG : std::uint8_t; @@ -34,8 +30,7 @@ namespace StreamFormat::FMT::Detail struct Color; }; - enum class TextProperties::TextColor::BasicColorFG : std::uint8_t - { + enum class TextProperties::TextColor::BasicColorFG : std::uint8_t { Black = 30, Red, Green, @@ -56,12 +51,11 @@ namespace StreamFormat::FMT::Detail Default = 39, - BaseStep = Black, - BaseBStep = BrightBlack + BaseStep = Black, + BaseBrightStep = BrightBlack }; - enum class TextProperties::TextColor::BasicColorBG : std::uint8_t - { + enum class TextProperties::TextColor::BasicColorBG : std::uint8_t { Black = 40, Red, Green, @@ -82,23 +76,19 @@ namespace StreamFormat::FMT::Detail Default = 49, - BaseStep = Black, - BaseBStep = BrightBlack, + BaseStep = Black, + BaseBrightStep = BrightBlack, }; - struct TextProperties::TextColor::BasicColor - { + struct TextProperties::TextColor::BasicColor { constexpr BasicColor(TextProperties::TextColor::BasicColorFG fg = TextProperties::TextColor::BasicColorFG::Default, TextProperties::TextColor::BasicColorBG bg = TextProperties::TextColor::BasicColorBG::Default) - : Fg(fg) - , Bg(bg) - {} - TextProperties::TextColor::BasicColorFG Fg; - TextProperties::TextColor::BasicColorBG Bg; + : fg(fg), bg(bg) {} + TextProperties::TextColor::BasicColorFG fg; + TextProperties::TextColor::BasicColorBG bg; }; - struct TextProperties::TextColor::BaseColorCube - { + struct TextProperties::TextColor::BaseColorCube { public: static inline constexpr std::uint8_t Black = 0; static inline constexpr std::uint8_t Red = 1; @@ -127,13 +117,12 @@ namespace StreamFormat::FMT::Detail static inline constexpr std::uint8_t MinGrayscale = 232; // grayscale from black to white in 24 step static inline constexpr std::uint8_t MaxGrayscale = 255; - static inline constexpr std::uint8_t BaseStep = MinNormalColor; - static inline constexpr std::uint8_t BaseBStep = MinBrightColor; - static inline constexpr std::uint8_t Default = 0; + static inline constexpr std::uint8_t BaseStep = MinNormalColor; + static inline constexpr std::uint8_t BaseBrightStep = MinBrightColor; + static inline constexpr std::uint8_t Default = 0; public: - enum class Type : std::uint8_t - { + enum class type : std::uint8_t { Normal, Bright, Cube666, @@ -141,298 +130,236 @@ namespace StreamFormat::FMT::Detail }; public: - std::uint8_t Color; + std::uint8_t color; public: - std::uint8_t GetColor() const { return Color; } - std::uint8_t GetColorRef() { return Color; } - std::uint8_t GetColorRef() const { return Color; } + std::uint8_t get_color() const { + return color; + } + std::uint8_t get_color_ref() { + return color; + } + std::uint8_t get_color_ref() const { + return color; + } public: - constexpr BaseColorCube(const std::uint8_t color) - : Color(color) - {} - - constexpr BaseColorCube() - : Color(0) - {} - - Type GetType() - { - if (Color >= MinNormalColor && Color <= MaxNormalColor) - return Type::Normal; - else if (Color >= MinBrightColor && Color <= MaxBrightColor) - return Type::Bright; - else if (Color >= Min666CubeColor && Color <= Max666CubeColor) - return Type::Cube666; - else if (Color >= MinGrayscale && Color <= MaxGrayscale) - return Type::Grayscale; - return Type::Normal; - } - - static BaseColorCube MakeNormalColor(std::uint8_t value) - { + constexpr BaseColorCube(const std::uint8_t color) : color(color) {} + + constexpr BaseColorCube() : color(0) {} + + type get_type() { + if (color >= MinNormalColor && color <= MaxNormalColor) + return type::Normal; + else if (color >= MinBrightColor && color <= MaxBrightColor) + return type::Bright; + else if (color >= Min666CubeColor && color <= Max666CubeColor) + return type::Cube666; + else if (color >= MinGrayscale && color <= MaxGrayscale) + return type::Grayscale; + return type::Normal; + } + + static BaseColorCube MakeNormalColor(std::uint8_t value) { if (value > MaxNormalColor) value -= MinBrightColor; if (value > MaxNormalColor) value = MaxNormalColor; return BaseColorCube(value); } - static BaseColorCube MakeBrightColor(std::uint8_t value) - { + static BaseColorCube MakeBrightColor(std::uint8_t value) { if (value < MinBrightColor) value += MinBrightColor; if (value > MaxBrightColor) value = MaxBrightColor; return BaseColorCube(value); } - static BaseColorCube Make666CubeColor255(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) - { + static BaseColorCube Make666CubeColor255(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) { return Make666CubeColor5(static_cast((static_cast(r) / 255) * 5), static_cast((static_cast(g) / 255) * 5), static_cast((static_cast(b) / 255) * 5)); } - static BaseColorCube Make666CubeColor5(std::uint8_t r, std::uint8_t g, std::uint8_t b) - { + static BaseColorCube Make666CubeColor5(std::uint8_t r, std::uint8_t g, std::uint8_t b) { if (r > 5) r = 5; if (g > 5) g = 5; if (b > 5) b = 5; return BaseColorCube(Min666CubeColor + 36 * r + 6 * g + b); } - static BaseColorCube MakeGrayscaleColor255(const std::uint8_t value) { return MakeGrayscaleColor24(static_cast(static_cast(value) / 255) * 24); } + static BaseColorCube MakeGrayscaleColor255(const std::uint8_t value) { + return MakeGrayscaleColor24(static_cast(static_cast(value) / 255) * 24); + } - static BaseColorCube MakeGrayscaleColor24(std::uint8_t value) - { + static BaseColorCube MakeGrayscaleColor24(std::uint8_t value) { if (value > 24) value = 24; return BaseColorCube(MinGrayscale + value); } }; // No need of virtual destructor since ColorCubeFG is purely a renaming of BaseColorCube - struct TextProperties::TextColor::ColorCubeFG : public TextProperties::TextColor::BaseColorCube - { + struct TextProperties::TextColor::ColorCubeFG : public TextProperties::TextColor::BaseColorCube { public: - constexpr explicit ColorCubeFG() - : TextProperties::TextColor::BaseColorCube() - {} - constexpr explicit ColorCubeFG(const std::uint8_t color) - : TextProperties::TextColor::BaseColorCube(color) - {} - constexpr ColorCubeFG(const TextProperties::TextColor::BaseColorCube& color) - : TextProperties::TextColor::BaseColorCube(color) - {} + constexpr explicit ColorCubeFG() : TextProperties::TextColor::BaseColorCube() {} + constexpr explicit ColorCubeFG(const std::uint8_t color) : TextProperties::TextColor::BaseColorCube(color) {} + constexpr ColorCubeFG(const TextProperties::TextColor::BaseColorCube& color) : TextProperties::TextColor::BaseColorCube(color) {} public: - static ColorCubeFG MakeNormalColor(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeNormalColor(value)); } + static ColorCubeFG MakeNormalColor(const std::uint8_t value) { + return static_cast(TextProperties::TextColor::BaseColorCube::MakeNormalColor(value)); + } - static ColorCubeFG MakeBrightColor(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeBrightColor(value)); } + static ColorCubeFG MakeBrightColor(const std::uint8_t value) { + return static_cast(TextProperties::TextColor::BaseColorCube::MakeBrightColor(value)); + } - static ColorCubeFG Make666CubeColor255(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) - { + static ColorCubeFG Make666CubeColor255(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) { return static_cast(TextProperties::TextColor::BaseColorCube::Make666CubeColor255(r, g, b)); } - static ColorCubeFG Make666CubeColor5(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) - { + static ColorCubeFG Make666CubeColor5(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) { return static_cast(TextProperties::TextColor::BaseColorCube::Make666CubeColor5(r, g, b)); } - static ColorCubeFG MakeGrayscaleColor255(const std::uint8_t value) - { + static ColorCubeFG MakeGrayscaleColor255(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeGrayscaleColor255(value)); } - static ColorCubeFG MakeGrayscaleColor24(const std::uint8_t value) - { + static ColorCubeFG MakeGrayscaleColor24(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeGrayscaleColor24(value)); } }; // No need of virtual destructor since ColorCubeBG is purely a renaming of BaseColorCube - struct TextProperties::TextColor::ColorCubeBG : public TextProperties::TextColor::BaseColorCube - { - constexpr explicit ColorCubeBG() - : TextProperties::TextColor::BaseColorCube() - {} - constexpr explicit ColorCubeBG(const std::uint8_t color) - : TextProperties::TextColor::BaseColorCube(color) - {} - constexpr ColorCubeBG(const TextProperties::TextColor::BaseColorCube& color) - : TextProperties::TextColor::BaseColorCube(color) - {} + struct TextProperties::TextColor::ColorCubeBG : public TextProperties::TextColor::BaseColorCube { + constexpr explicit ColorCubeBG() : TextProperties::TextColor::BaseColorCube() {} + constexpr explicit ColorCubeBG(const std::uint8_t color) : TextProperties::TextColor::BaseColorCube(color) {} + constexpr ColorCubeBG(const TextProperties::TextColor::BaseColorCube& color) : TextProperties::TextColor::BaseColorCube(color) {} public: - static TextProperties::TextColor::ColorCubeBG MakeNormalColor(const std::uint8_t value) - { + static TextProperties::TextColor::ColorCubeBG MakeNormalColor(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeNormalColor(value)); } - static TextProperties::TextColor::ColorCubeBG MakeBrightColor(const std::uint8_t value) - { + static TextProperties::TextColor::ColorCubeBG MakeBrightColor(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeBrightColor(value)); } - static TextProperties::TextColor::ColorCubeBG Make666CubeColor255(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) - { + static TextProperties::TextColor::ColorCubeBG Make666CubeColor255(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) { return static_cast(TextProperties::TextColor::BaseColorCube::Make666CubeColor255(r, g, b)); } - static TextProperties::TextColor::ColorCubeBG Make666CubeColor5(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) - { + static TextProperties::TextColor::ColorCubeBG Make666CubeColor5(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) { return static_cast(TextProperties::TextColor::BaseColorCube::Make666CubeColor5(r, g, b)); } - static TextProperties::TextColor::ColorCubeBG MakeGrayscaleColor255(const std::uint8_t value) - { + static TextProperties::TextColor::ColorCubeBG MakeGrayscaleColor255(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeGrayscaleColor255(value)); } - static TextProperties::TextColor::ColorCubeBG MakeGrayscaleColor24(const std::uint8_t value) - { + static TextProperties::TextColor::ColorCubeBG MakeGrayscaleColor24(const std::uint8_t value) { return static_cast(TextProperties::TextColor::BaseColorCube::MakeGrayscaleColor24(value)); } }; - inline bool operator==(const TextProperties::TextColor::BaseColorCube& lhs, const TextProperties::TextColor::BaseColorCube& rhs) - { - return lhs.Color == rhs.Color; + inline bool operator==(const TextProperties::TextColor::BaseColorCube& lhs, const TextProperties::TextColor::BaseColorCube& rhs) { + return lhs.color == rhs.color; } - struct TextProperties::TextColor::ColorCube - { - constexpr ColorCube() - : Fg() - , Bg() - {} - - constexpr ColorCube(const TextProperties::TextColor::ColorCubeFG& fg) - : Fg(fg) - , Bg() - {} - - constexpr ColorCube(const TextProperties::TextColor::ColorCubeFG& fg, const TextProperties::TextColor::ColorCubeBG& bg) - : Fg(fg) - , Bg(bg) - {} - - TextProperties::TextColor::ColorCubeFG Fg; - TextProperties::TextColor::ColorCubeBG Bg; + struct TextProperties::TextColor::ColorCube { + constexpr ColorCube() : fg(), bg() {} + + constexpr ColorCube(const TextProperties::TextColor::ColorCubeFG& fg) : fg(fg), bg() {} + + constexpr ColorCube(const TextProperties::TextColor::ColorCubeFG& fg, const TextProperties::TextColor::ColorCubeBG& bg) : fg(fg), bg(bg) {} + + TextProperties::TextColor::ColorCubeFG fg; + TextProperties::TextColor::ColorCubeBG bg; }; - struct TextProperties::TextColor::BaseColor24b - { - constexpr BaseColor24b(std::uint8_t r, std::uint8_t g, std::uint8_t b) - : R(r) - , G(g) - , B(b) - {} - std::uint8_t R, G, B; + struct TextProperties::TextColor::BaseColor24b { + constexpr BaseColor24b(std::uint8_t r, std::uint8_t g, std::uint8_t b) : r(r), g(g), b(b) {} + std::uint8_t r, g, b; }; - inline bool operator==(const TextProperties::TextColor::BaseColor24b& lhs, const TextProperties::TextColor::BaseColor24b& rhs) - { - return lhs.R == rhs.R && lhs.G == rhs.G && lhs.B == rhs.B; + inline bool operator==(const TextProperties::TextColor::BaseColor24b& lhs, const TextProperties::TextColor::BaseColor24b& rhs) { + return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b; } // No need of virtual destructor since Color24bFG is purely a renaming of BaseColor24b - struct TextProperties::TextColor::Color24bFG : public TextProperties::TextColor::BaseColor24b - { - constexpr Color24bFG(std::uint8_t r = 255, std::uint8_t g = 255, std::uint8_t b = 255) - : TextProperties::TextColor::BaseColor24b(r, g, b) - {} + struct TextProperties::TextColor::Color24bFG : public TextProperties::TextColor::BaseColor24b { + constexpr Color24bFG(std::uint8_t r = 255, std::uint8_t g = 255, std::uint8_t b = 255) : TextProperties::TextColor::BaseColor24b(r, g, b) {} }; // No need of virtual destructor since Color24bBG is purely a renaming of BaseColor24b - struct TextProperties::TextColor::Color24bBG : public TextProperties::TextColor::BaseColor24b - { - constexpr Color24bBG(std::uint8_t r = 0, std::uint8_t g = 0, std::uint8_t b = 0) - : TextProperties::TextColor::BaseColor24b(r, g, b) - {} + struct TextProperties::TextColor::Color24bBG : public TextProperties::TextColor::BaseColor24b { + constexpr Color24bBG(std::uint8_t r = 0, std::uint8_t g = 0, std::uint8_t b = 0) : TextProperties::TextColor::BaseColor24b(r, g, b) {} }; - struct TextProperties::TextColor::Color24b - { - constexpr Color24b(const TextProperties::TextColor::Color24bFG&& fg = TextProperties::TextColor::Color24bFG(), - const TextProperties::TextColor::Color24bBG&& bg = TextProperties::TextColor::Color24bBG()) - : Fg(fg) - , Bg(bg) - {} + struct TextProperties::TextColor::Color24b { + constexpr Color24b(const TextProperties::TextColor::Color24bFG&& fg_ = TextProperties::TextColor::Color24bFG(), + const TextProperties::TextColor::Color24bBG&& bg_ = TextProperties::TextColor::Color24bBG()) + : fg(fg_), bg(bg_) {} - TextProperties::TextColor::Color24bFG Fg; - TextProperties::TextColor::Color24bBG Bg; + TextProperties::TextColor::Color24bFG fg; + TextProperties::TextColor::Color24bBG bg; }; - inline bool operator==(const TextProperties::TextColor::Color24b& lhs, const TextProperties::TextColor::Color24b& rhs) - { - return lhs.Fg == rhs.Fg && lhs.Bg == rhs.Bg; + inline bool operator==(const TextProperties::TextColor::Color24b& lhs, const TextProperties::TextColor::Color24b& rhs) { + return lhs.fg == rhs.fg && lhs.bg == rhs.bg; } - enum class TextProperties::TextColor::ColorType : std::uint8_t - { + enum class TextProperties::TextColor::ColorType : std::uint8_t { BasicColor, ColorCube, Color24b }; - union TextProperties::TextColor::ColorFGData - { - constexpr ColorFGData() - : BasicColor{TextProperties::TextColor::BasicColorFG::Default} - {} + union TextProperties::TextColor::ColorFGData { + constexpr ColorFGData() : basic_color{TextProperties::TextColor::BasicColorFG::Default} {} - TextProperties::TextColor::BasicColorFG BasicColor; - TextProperties::TextColor::ColorCubeFG ColorCube; - TextProperties::TextColor::Color24bFG Color24b; + TextProperties::TextColor::BasicColorFG basic_color; + TextProperties::TextColor::ColorCubeFG color_cube; + TextProperties::TextColor::Color24bFG color24b; }; - union TextProperties::TextColor::ColorBGData - { - constexpr ColorBGData() - : BasicColor{TextProperties::TextColor::BasicColorBG::Default} - {} + union TextProperties::TextColor::ColorBGData { + constexpr ColorBGData() : basic_color{TextProperties::TextColor::BasicColorBG::Default} {} - TextProperties::TextColor::BasicColorBG BasicColor; - TextProperties::TextColor::ColorCubeBG ColorCube; - TextProperties::TextColor::Color24bBG Color24b; + TextProperties::TextColor::BasicColorBG basic_color; + TextProperties::TextColor::ColorCubeBG color_cube; + TextProperties::TextColor::Color24bBG color24b; }; - struct TextProperties::TextColor::ColorFG - { - TextProperties::TextColor::ColorFGData Data; - TextProperties::TextColor::ColorType Type{TextProperties::TextColor::ColorType::BasicColor}; + struct TextProperties::TextColor::ColorFG { + TextProperties::TextColor::ColorFGData data; + TextProperties::TextColor::ColorType type{TextProperties::TextColor::ColorType::BasicColor}; }; - struct TextProperties::TextColor::ColorBG - { - TextProperties::TextColor::ColorBGData Data; - TextProperties::TextColor::ColorType Type{TextProperties::TextColor::ColorType::BasicColor}; + struct TextProperties::TextColor::ColorBG { + TextProperties::TextColor::ColorBGData data; + TextProperties::TextColor::ColorType type{TextProperties::TextColor::ColorType::BasicColor}; }; - inline bool operator==(const TextProperties::TextColor::ColorFG& lhs, const TextProperties::TextColor::ColorFG& rhs) - { - if (lhs.Type != rhs.Type) return false; - switch (lhs.Type) - { + inline bool operator==(const TextProperties::TextColor::ColorFG& lhs, const TextProperties::TextColor::ColorFG& rhs) { + if (lhs.type != rhs.type) return false; + switch (lhs.type) { case TextProperties::TextColor::ColorType::BasicColor: - return lhs.Data.BasicColor == rhs.Data.BasicColor; + return lhs.data.basic_color == rhs.data.basic_color; case TextProperties::TextColor::ColorType::ColorCube: - return lhs.Data.ColorCube == rhs.Data.ColorCube; + return lhs.data.color_cube == rhs.data.color_cube; case TextProperties::TextColor::ColorType::Color24b: - return lhs.Data.Color24b == rhs.Data.Color24b; + return lhs.data.color24b == rhs.data.color24b; } return false; } - inline bool operator==(const TextProperties::TextColor::ColorBG& lhs, const TextProperties::TextColor::ColorBG& rhs) - { - if (lhs.Type != rhs.Type) return false; - switch (lhs.Type) - { + inline bool operator==(const TextProperties::TextColor::ColorBG& lhs, const TextProperties::TextColor::ColorBG& rhs) { + if (lhs.type != rhs.type) return false; + switch (lhs.type) { case TextProperties::TextColor::ColorType::BasicColor: - return lhs.Data.BasicColor == rhs.Data.BasicColor; + return lhs.data.basic_color == rhs.data.basic_color; case TextProperties::TextColor::ColorType::ColorCube: - return lhs.Data.ColorCube == rhs.Data.ColorCube; + return lhs.data.color_cube == rhs.data.color_cube; case TextProperties::TextColor::ColorType::Color24b: - return lhs.Data.Color24b == rhs.Data.Color24b; + return lhs.data.color24b == rhs.data.color24b; } return false; } @@ -440,106 +367,113 @@ namespace StreamFormat::FMT::Detail bool operator==(const TextProperties::TextColor::Color& lhs, const TextProperties::TextColor::Color& rhs); // Manage only the text color / the underline color will be manage by the TextProperties::TextStyle::UnderlineColor - struct TextProperties::TextColor::Color - { + struct TextProperties::TextColor::Color { public: - constexpr Color() - : Fg() - , Bg() - {} + constexpr Color() : fg(), bg() {} public: - TextProperties::TextColor::ColorFG Fg; - TextProperties::TextColor::ColorBG Bg; + TextProperties::TextColor::ColorFG fg; + TextProperties::TextColor::ColorBG bg; public: - void ModifyReset() - { - Fg = TextProperties::TextColor::ColorFG{}; - Bg = TextProperties::TextColor::ColorBG{}; + void modify_reset() { + fg = TextProperties::TextColor::ColorFG{}; + bg = TextProperties::TextColor::ColorBG{}; } - void Apply(const TextProperties::TextColor::Color& given) { *this = given; } + void apply(const TextProperties::TextColor::Color& given) { + *this = given; + } - void Apply(const TextProperties::TextColor::ResetColor&) { ModifyReset(); } - void Apply(const TextProperties::TextColor::BasicColorFG& given) - { - Fg.Type = TextProperties::TextColor::ColorType::BasicColor; - Fg.Data.BasicColor = given; + void apply(const TextProperties::TextColor::reset_color&) { + modify_reset(); + } + void apply(const TextProperties::TextColor::BasicColorFG& given) { + fg.type = TextProperties::TextColor::ColorType::BasicColor; + fg.data.basic_color = given; } - void Apply(const TextProperties::TextColor::BasicColorBG& given) - { - Bg.Type = TextProperties::TextColor::ColorType::BasicColor; - Bg.Data.BasicColor = given; + void apply(const TextProperties::TextColor::BasicColorBG& given) { + bg.type = TextProperties::TextColor::ColorType::BasicColor; + bg.data.basic_color = given; } - void Apply(const TextProperties::TextColor::BasicColor& given) - { - Apply(given.Fg); - Apply(given.Bg); + void apply(const TextProperties::TextColor::BasicColor& given) { + apply(given.fg); + apply(given.bg); } - void Apply(const TextProperties::TextColor::ColorCubeFG& given) - { - Fg.Type = TextProperties::TextColor::ColorType::ColorCube; - Fg.Data.ColorCube = given; + void apply(const TextProperties::TextColor::ColorCubeFG& given) { + fg.type = TextProperties::TextColor::ColorType::ColorCube; + fg.data.color_cube = given; } - void Apply(const TextProperties::TextColor::ColorCubeBG& given) - { - Bg.Type = TextProperties::TextColor::ColorType::ColorCube; - Bg.Data.ColorCube = given; + void apply(const TextProperties::TextColor::ColorCubeBG& given) { + bg.type = TextProperties::TextColor::ColorType::ColorCube; + bg.data.color_cube = given; } - void Apply(const TextProperties::TextColor::ColorCube& given) - { - Apply(given.Fg); - Apply(given.Bg); + void apply(const TextProperties::TextColor::ColorCube& given) { + apply(given.fg); + apply(given.bg); } - void Apply(const TextProperties::TextColor::Color24bFG& given) - { - Fg.Type = TextProperties::TextColor::ColorType::Color24b; - Fg.Data.Color24b = given; + void apply(const TextProperties::TextColor::Color24bFG& given) { + fg.type = TextProperties::TextColor::ColorType::Color24b; + fg.data.color24b = given; } - void Apply(const TextProperties::TextColor::Color24bBG& given) - { - Bg.Type = TextProperties::TextColor::ColorType::Color24b; - Bg.Data.Color24b = given; + void apply(const TextProperties::TextColor::Color24bBG& given) { + bg.type = TextProperties::TextColor::ColorType::Color24b; + bg.data.color24b = given; } - void Apply(const TextProperties::TextColor::Color24b& given) - { - Apply(given.Fg); - Apply(given.Bg); + void apply(const TextProperties::TextColor::Color24b& given) { + apply(given.fg); + apply(given.bg); } public: - bool NeedModif(const TextProperties::TextColor::ResetColor&) { return true; } - - bool NeedModif(const TextProperties::TextColor::Color& given) { return *this != given; } - - bool NeedModif(const TextProperties::TextColor::BasicColorFG& given) { return Fg.Type != TextProperties::TextColor::ColorType::BasicColor || Fg.Data.BasicColor != given; } - bool NeedModif(const TextProperties::TextColor::BasicColorBG& given) { return Bg.Type != TextProperties::TextColor::ColorType::BasicColor || Bg.Data.BasicColor != given; } - bool NeedModif(const TextProperties::TextColor::BasicColor& given) { return NeedModif(given.Fg) || NeedModif(given.Bg); } - bool NeedModif(const TextProperties::TextColor::ColorCubeFG& given) { return Fg.Type != TextProperties::TextColor::ColorType::ColorCube || Fg.Data.ColorCube != given; } - bool NeedModif(const TextProperties::TextColor::ColorCubeBG& given) { return Bg.Type != TextProperties::TextColor::ColorType::ColorCube || Bg.Data.ColorCube != given; } - bool NeedModif(const TextProperties::TextColor::ColorCube& given) { return NeedModif(given.Fg) || NeedModif(given.Bg); } - bool NeedModif(const TextProperties::TextColor::Color24bFG& given) { return Fg.Type != TextProperties::TextColor::ColorType::Color24b || Fg.Data.Color24b != given; } - bool NeedModif(const TextProperties::TextColor::Color24bBG& given) { return Bg.Type != TextProperties::TextColor::ColorType::Color24b || Bg.Data.Color24b != given; } - bool NeedModif(const TextProperties::TextColor::Color24b& given) { return NeedModif(given.Fg) || NeedModif(given.Bg); } + bool need_modif(const TextProperties::TextColor::reset_color&) { + return true; + } + + bool need_modif(const TextProperties::TextColor::Color& given) { + return *this != given; + } + + bool need_modif(const TextProperties::TextColor::BasicColorFG& given) { + return fg.type != TextProperties::TextColor::ColorType::BasicColor || fg.data.basic_color != given; + } + bool need_modif(const TextProperties::TextColor::BasicColorBG& given) { + return bg.type != TextProperties::TextColor::ColorType::BasicColor || bg.data.basic_color != given; + } + bool need_modif(const TextProperties::TextColor::BasicColor& given) { + return need_modif(given.fg) || need_modif(given.bg); + } + bool need_modif(const TextProperties::TextColor::ColorCubeFG& given) { + return fg.type != TextProperties::TextColor::ColorType::ColorCube || fg.data.color_cube != given; + } + bool need_modif(const TextProperties::TextColor::ColorCubeBG& given) { + return bg.type != TextProperties::TextColor::ColorType::ColorCube || bg.data.color_cube != given; + } + bool need_modif(const TextProperties::TextColor::ColorCube& given) { + return need_modif(given.fg) || need_modif(given.bg); + } + bool need_modif(const TextProperties::TextColor::Color24bFG& given) { + return fg.type != TextProperties::TextColor::ColorType::Color24b || fg.data.color24b != given; + } + bool need_modif(const TextProperties::TextColor::Color24bBG& given) { + return bg.type != TextProperties::TextColor::ColorType::Color24b || bg.data.color24b != given; + } + bool need_modif(const TextProperties::TextColor::Color24b& given) { + return need_modif(given.fg) || need_modif(given.bg); + } }; - inline bool operator==(const TextProperties::TextColor::Color& lhs, const TextProperties::TextColor::Color& rhs) - { - return lhs.Fg == rhs.Fg && lhs.Bg == rhs.Bg; + inline bool operator==(const TextProperties::TextColor::Color& lhs, const TextProperties::TextColor::Color& rhs) { + return lhs.fg == rhs.fg && lhs.bg == rhs.bg; } template - concept TextPropertiesColorCanApply = requires(const T& value, TextProperties::TextColor::Color& data) - { - data.Apply(value); - }; + concept text_properties_color_can_apply = requires(const T& value, TextProperties::TextColor::Color& data) { data.apply(value); }; template - struct TextPropertiesColorIsApplyType - { - using BaseType = GetBaseType; - static constexpr bool Value = std::is_same_v || std::is_same_v || + struct TextPropertiesColorIsApplyType { + using BaseType = get_base_type; + static constexpr bool value = std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || @@ -548,5 +482,5 @@ namespace StreamFormat::FMT::Detail }; template - concept TextPropertiesColorIsApply = TextPropertiesColorIsApplyType::Value; -} + concept text_properties_color_is_apply = TextPropertiesColorIsApplyType::value; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/text_properties/text_properties_front.hxx b/src/stream/fmt/text_properties/text_properties_front.hxx new file mode 100644 index 00000000..2157ed45 --- /dev/null +++ b/src/stream/fmt/text_properties/text_properties_front.hxx @@ -0,0 +1,87 @@ +#pragma once + +#include "base_text_properties.hxx" + +namespace stream::fmt::detail { + struct TextProperties::TextFront { + struct ResetFront {}; + + struct FrontID; + struct Front; + }; + + struct TextProperties::TextFront::FrontID { + public: + static inline constexpr std::uint8_t DefaultFrontID = 10; + static inline constexpr std::uint8_t MinFrontID = 10; + static inline constexpr std::uint8_t MaxFrontID = 19; + + public: + std::uint8_t id; + + constexpr FrontID() : id(DefaultFrontID) {} + constexpr FrontID(std::uint8_t id_) : id(id_) {} + + public: + constexpr bool operator==(const TextProperties::TextFront::FrontID& other) const { + return id == other.id; + } + constexpr bool is_valid() const { + return id > MinFrontID && id < MaxFrontID; + } + }; + + bool operator==(const TextProperties::TextFront::Front& lhs, const TextProperties::TextFront::Front& rhs); + + struct TextProperties::TextFront::Front { + public: + constexpr Front(const TextProperties::TextFront::FrontID front_id = TextProperties::TextFront::FrontID::DefaultFrontID) + : current_id(front_id.is_valid() ? front_id : TextProperties::TextFront::FrontID::DefaultFrontID) {} + + public: + FrontID current_id; + + public: + void modify_reset() { + *this = Front{}; + } + + void apply(const TextProperties::TextFront::ResetFront&) { + modify_reset(); + } + void apply(const TextProperties::TextFront::Front& given) { + *this = given; + } + void apply(const TextProperties::TextFront::FrontID& given) { + current_id = given; + } + + public: + bool need_modif(const TextProperties::TextFront::ResetFront&) { + return true; + } + bool need_modif(const TextProperties::TextFront::Front& given) { + return *this != given; + } + bool need_modif(const TextProperties::TextFront::FrontID& given) { + return current_id != given; + } + }; + + inline bool operator==(const TextProperties::TextFront::Front& lhs, const TextProperties::TextFront::Front& rhs) { + return lhs.current_id == rhs.current_id; + } + + template + concept text_properties_front_can_apply = requires(const T& value, TextProperties::TextFront::Front& data) { data.apply(value); }; + + template + struct TextPropertiesFrontIsapplyType { + using BaseType = get_base_type; + static constexpr bool value = std::is_same_v || std::is_same_v || + std::is_same_v; + }; + + template + concept TextPropertiesFrontIsapply = TextPropertiesFrontIsapplyType::value; +} // namespace stream::fmt::detail diff --git a/src/stream/fmt/text_properties/text_properties_style.hxx b/src/stream/fmt/text_properties/text_properties_style.hxx new file mode 100644 index 00000000..a37636f3 --- /dev/null +++ b/src/stream/fmt/text_properties/text_properties_style.hxx @@ -0,0 +1,300 @@ +#pragma once + +#include "base_text_properties.hxx" +#include "text_properties_color.hxx" + +namespace stream::fmt::detail { + struct TextProperties::TextStyle { + struct reset_style {}; + + enum class Intensity : std::uint8_t; + enum class Italic : std::uint8_t; + enum class Blink : std::uint8_t; + enum class Inverted : std::uint8_t; + enum class Ideogram : std::uint8_t; + enum class Script : std::uint8_t; + enum class Underline : std::uint8_t; + struct UnderlineColor; + + struct Style; + }; + + enum class TextProperties::TextStyle::Intensity : std::uint8_t { + Bold = 1, + Dim = 2, + Normal = 22 + }; + + enum class TextProperties::TextStyle::Italic : std::uint8_t { + enable = 3, + Disable = 23 + }; + + enum class TextProperties::TextStyle::Underline : std::uint8_t { + Underlined = 4, + DoubleUnerlined = 21, // may only disable bold + Disable = 24, + + SelectUnderlinedColor = 254 + }; + + enum class TextProperties::TextStyle::Blink : std::uint8_t { + SlowBlink = 5, + FastBlink = 6, + Disable = 25 + }; + + enum class TextProperties::TextStyle::Inverted : std::uint8_t { + enable = 7, + Disable = 27 + }; + + enum class TextProperties::TextStyle::Ideogram : std::uint8_t { + Underlined = 60, + DoubleUnderlined = 61, + Overlined = 62, + DoubleOverlined = 63, + StressMarking = 64, + AllDisable = 65 + }; + + enum class TextProperties::TextStyle::Script : std::uint8_t { + Superscript = 74, + Subscript = 75, + AllDisable = 76 + }; + + struct TextProperties::TextStyle::UnderlineColor { + struct ColorCube; + struct Color24b; + enum class ColorType : std::uint8_t; + union ColorData; + struct Color; + }; + + // No need of virtual destructor since color24b is purely a renaming of BaseColor24b + struct TextProperties::TextStyle::UnderlineColor::Color24b : public TextProperties::TextColor::BaseColor24b { + constexpr Color24b(std::uint8_t r = 0, std::uint8_t g = 0, std::uint8_t b = 0) : TextProperties::TextColor::BaseColor24b(r, g, b) {} + }; + + // No need of virtual destructor since color_cube is purely a renaming of BaseColorCube + struct TextProperties::TextStyle::UnderlineColor::ColorCube : public TextProperties::TextColor::BaseColorCube { + constexpr ColorCube() : TextProperties::TextColor::BaseColorCube() {} + constexpr ColorCube(const std::uint8_t color) : TextProperties::TextColor::BaseColorCube(color) {} + constexpr ColorCube(const TextProperties::TextColor::BaseColorCube& color) : TextProperties::TextColor::BaseColorCube(color) {} + + public: + static ColorCube MakeNormalColor(const std::uint8_t value) { + return static_cast(TextProperties::TextColor::BaseColorCube::MakeNormalColor(value)); + } + + static ColorCube MakeBrightColor(const std::uint8_t value) { + return static_cast(TextProperties::TextColor::BaseColorCube::MakeBrightColor(value)); + } + + static ColorCube Make666CubeColor255(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) { + return static_cast(TextProperties::TextColor::BaseColorCube::Make666CubeColor255(r, g, b)); + } + + static ColorCube Make666CubeColor5(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b) { + return static_cast(TextProperties::TextColor::BaseColorCube::Make666CubeColor5(r, g, b)); + } + + static ColorCube MakeGrayscaleColor255(const std::uint8_t value) { + return static_cast(TextProperties::TextColor::BaseColorCube::MakeGrayscaleColor255(value)); + } + + static ColorCube MakeGrayscaleColor24(const std::uint8_t value) { + return static_cast(TextProperties::TextColor::BaseColorCube::MakeGrayscaleColor24(value)); + } + }; + + enum class TextProperties::TextStyle::UnderlineColor::ColorType : std::uint8_t { + Default, + ColorCube, + Color24b + }; + + union TextProperties::TextStyle::UnderlineColor::ColorData { + constexpr ColorData() : color_cube() {} + + TextProperties::TextStyle::UnderlineColor::ColorCube color_cube; + TextProperties::TextStyle::UnderlineColor::Color24b color24b; + }; + + struct TextProperties::TextStyle::UnderlineColor::Color { + TextProperties::TextStyle::UnderlineColor::ColorData data; + TextProperties::TextStyle::UnderlineColor::ColorType type = TextProperties::TextStyle::UnderlineColor::ColorType::Default; + }; + + inline bool operator==(const TextProperties::TextStyle::UnderlineColor::Color& lhs, const TextProperties::TextStyle::UnderlineColor::Color& rhs) { + if (lhs.type != rhs.type) return false; + switch (lhs.type) { + case TextProperties::TextStyle::UnderlineColor::ColorType::Default: + return true; + case TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube: + return lhs.data.color_cube == rhs.data.color_cube; + case TextProperties::TextStyle::UnderlineColor::ColorType::Color24b: + return lhs.data.color24b == rhs.data.color24b; + } + return false; + } + + bool operator==(const TextProperties::TextStyle::Style& lhs, const TextProperties::TextStyle::Style& rhs); + + struct TextProperties::TextStyle::Style { + public: + constexpr Style() {} + + TextProperties::TextStyle::Intensity intensity = TextProperties::TextStyle::Intensity::Normal; + TextProperties::TextStyle::Italic italic = TextProperties::TextStyle::Italic::Disable; + TextProperties::TextStyle::Blink blink = TextProperties::TextStyle::Blink::Disable; + TextProperties::TextStyle::Inverted inverted = TextProperties::TextStyle::Inverted::Disable; + TextProperties::TextStyle::Ideogram ideogram = TextProperties::TextStyle::Ideogram::AllDisable; + TextProperties::TextStyle::Script script = TextProperties::TextStyle::Script::AllDisable; + + TextProperties::TextStyle::Underline underline = TextProperties::TextStyle::Underline::Disable; + TextProperties::TextStyle::UnderlineColor::Color underline_color; + + public: + void modify_reset() { + *this = Style{}; + } + + void apply(const TextProperties::TextStyle::reset_style&) { + modify_reset(); + } + void apply(const TextProperties::TextStyle::Style& given) { + *this = given; + } + void apply(const TextProperties::TextStyle::Intensity& given) { + intensity = given; + } + void apply(const TextProperties::TextStyle::Italic& given) { + italic = given; + } + void apply(const TextProperties::TextStyle::Underline& given) { + underline = given; + } + void apply(const TextProperties::TextStyle::Blink& given) { + blink = given; + } + void apply(const TextProperties::TextStyle::Inverted& given) { + inverted = given; + } + void apply(const TextProperties::TextStyle::Ideogram& given) { + ideogram = given; + } + void apply(const TextProperties::TextStyle::Script& given) { + script = given; + } + + void apply(const TextProperties::TextStyle::UnderlineColor::Color& given) { + underline_color = given; + } + void apply(const TextProperties::TextStyle::UnderlineColor::ColorCube& given) { + underline_color.type = TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube; + underline_color.data.color_cube = given; + } + void apply(const TextProperties::TextStyle::UnderlineColor::Color24b& given) { + underline_color.type = TextProperties::TextStyle::UnderlineColor::ColorType::Color24b; + underline_color.data.color24b = given; + } + + public: + bool need_modif(const TextProperties::TextStyle::reset_style&) { + return true; + } + bool need_modif(const TextProperties::TextStyle::Style& given) { + return *this != given; + } + bool need_modif(const TextProperties::TextStyle::Intensity& given) { + return intensity != given; + } + bool need_modif(const TextProperties::TextStyle::Italic& given) { + return italic != given; + } + bool need_modif(const TextProperties::TextStyle::Underline& given) { + return underline != given; + } + bool need_modif(const TextProperties::TextStyle::Blink& given) { + return blink != given; + } + bool need_modif(const TextProperties::TextStyle::Inverted& given) { + return inverted != given; + } + bool need_modif(const TextProperties::TextStyle::Ideogram& given) { + return ideogram != given; + } + bool need_modif(const TextProperties::TextStyle::Script& given) { + return script != given; + } + + bool need_modif(const TextProperties::TextStyle::UnderlineColor::Color& given) { + return underline_color != given; + } + bool need_modif(const TextProperties::TextStyle::UnderlineColor::ColorCube& given) { + return underline_color.type != TextProperties::TextStyle::UnderlineColor::ColorType::ColorCube || underline_color.data.color_cube != given; + } + bool need_modif(const TextProperties::TextStyle::UnderlineColor::Color24b& given) { + return underline_color.type != TextProperties::TextStyle::UnderlineColor::ColorType::Color24b || underline_color.data.color24b != given; + } + }; + + inline bool operator==(const TextProperties::TextStyle::Style& lhs, const TextProperties::TextStyle::Style& rhs) { + return lhs.intensity == rhs.intensity && lhs.italic == rhs.italic && lhs.blink == rhs.blink && lhs.inverted == rhs.inverted && lhs.ideogram == rhs.ideogram && + lhs.script == rhs.script && lhs.underline == rhs.underline && lhs.underline_color == rhs.underline_color; + } + + template + concept text_properties_style_can_apply = requires(const T& value, TextProperties::TextStyle::Style& data) { data.apply(value); }; + + template + struct TextPropertiesStyleIsapplyType { + using BaseType = get_base_type; + static constexpr bool value = std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || + std::is_same_v; + }; + + template + concept TextPropertiesStyleIsapply = TextPropertiesStyleIsapplyType::value; +} // namespace stream::fmt::detail + +namespace stream::fmt::detail::OLD { + enum class BasicStyle : std::uint8_t { + Intensity_Bold = static_cast(TextProperties::TextStyle::Intensity::Bold), + Intensity_Dim = static_cast(TextProperties::TextStyle::Intensity::Dim), + Intensity_Normal = static_cast(TextProperties::TextStyle::Intensity::Normal), + + Italic_Enable = static_cast(TextProperties::TextStyle::Italic::enable), + Italic_Disable = static_cast(TextProperties::TextStyle::Italic::Disable), + + Underline_Underlined = static_cast(TextProperties::TextStyle::Underline::Underlined), + Underline_DoubleUnerlined = static_cast(TextProperties::TextStyle::Underline::DoubleUnerlined), // may only disable bold + Underline_Disable = static_cast(TextProperties::TextStyle::Underline::Disable), + Underline_SelectColor = 255, + + Blink_SlowBlink = static_cast(TextProperties::TextStyle::Blink::SlowBlink), + Blink_FastBlink = static_cast(TextProperties::TextStyle::Blink::FastBlink), + Blink_Disable = static_cast(TextProperties::TextStyle::Blink::Disable), + + Inverted_Enable = static_cast(TextProperties::TextStyle::Inverted::enable), + Inverted_Disable = static_cast(TextProperties::TextStyle::Inverted::Disable), + + Ideogram_Underlined = static_cast(TextProperties::TextStyle::Ideogram::Underlined), + Ideogram_DoubleUnderlined = static_cast(TextProperties::TextStyle::Ideogram::DoubleUnderlined), + Ideogram_Overlined = static_cast(TextProperties::TextStyle::Ideogram::Overlined), + Ideogram_DoubleOverlined = static_cast(TextProperties::TextStyle::Ideogram::DoubleOverlined), + Ideogram_StressMarking = static_cast(TextProperties::TextStyle::Ideogram::StressMarking), + Ideogram_AllDisable = static_cast(TextProperties::TextStyle::Ideogram::AllDisable), + + Script_Superscript = static_cast(TextProperties::TextStyle::Script::Superscript), + Script_Subscript = static_cast(TextProperties::TextStyle::Script::Subscript), + Script_AllDisable = static_cast(TextProperties::TextStyle::Script::AllDisable) + }; +} // namespace stream::fmt::detail::OLD diff --git a/src/stream/json.hxx b/src/stream/json.hxx new file mode 100644 index 00000000..7e09551f --- /dev/null +++ b/src/stream/json.hxx @@ -0,0 +1,7 @@ +#pragma once + +#include "json/json_factory.hxx" +#include "json/json_objects.hxx" + +#include "json/json_serializer.hxx" +#include "json/serializers/serializers.hxx" diff --git a/src/stream/json/detail.hxx b/src/stream/json/detail.hxx new file mode 100644 index 00000000..832d3652 --- /dev/null +++ b/src/stream/json/detail.hxx @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include + +namespace stream::json::detail { + class JsonError : public std::exception { + public: + JsonError(std::string&& msg) : what_(std::move(msg)) {} + JsonError(const std::string_view msg) : what_(msg) {} + const char* what() const noexcept override { + return what_.c_str(); + } + + protected: + std::string what_; + }; + + class JsonIndexingError : public JsonError { + public: + JsonIndexingError(std::string msg = "") : JsonError(std::string("JsonIndexingError") + std::move(msg)) {} + }; + class JsonTypeSerializerNotImpl : public JsonError { + public: + JsonTypeSerializerNotImpl(std::string msg = "") : JsonError(std::string("JsonTypeSerializerNotImpl") + std::move(msg)) {} + }; + class JsonGivenTypeError : public JsonError { + public: + JsonGivenTypeError(std::string msg = "") : JsonError(std::string("JsonGivenTypeError") + std::move(msg)) {} + }; + class JsonCastError : public JsonError { + public: + JsonCastError(std::string msg = "") : JsonError(std::string("JsonCastError") + std::move(msg)) {} + }; +} // namespace stream::json::detail + +namespace stream::json { + template + struct JsonObjectSerializer; + template + struct JsonSerializer; +} // namespace stream::json diff --git a/src/stream/json/json_factory.hxx b/src/stream/json/json_factory.hxx new file mode 100644 index 00000000..fcc756c7 --- /dev/null +++ b/src/stream/json/json_factory.hxx @@ -0,0 +1,76 @@ +#pragma once + +#include "json_formatter_impl.hxx" +#include "json_formatter.hxx" +#include "json_objects.hxx" +#include "json_parser.hxx" +#include "json_serializer.hxx" +#include "serializers/json_objects_serializer.hxx" +#include "serializers/serializers.hxx" + +#include +#include + +namespace stream::json { + class JsonFactory { + public: + template > + static T FromPath(const std::filesystem::path& path); + template + static void SaveToPath(T& json, const std::filesystem::path& path, detail::JsonFormatter::FormatSettings settings); + }; +} // namespace stream::json + +#include "stream/fmt.hxx" +namespace stream::fmt { + template + struct FormatterType { + static void format(const json::JsonObject& object, FormatterExecutor& executor) { + return executor.write_type(json::FormatAsJson(object)); + } + }; +} // namespace stream::fmt + +#include +#include +#include "stream//fmt/buf/streamio_manager/dynamic_streamio_manager.hxx" +#include "serializers/json_objects_serializer.hxx" +namespace stream::json { + template + T JsonFactory::FromPath(const std::filesystem::path& path) { + std::ifstream file(path.string(), std::ios::in); + + if (file.is_open() == false) throw std::runtime_error("unable to open file"); + + std::string buffer; + + file.seekg(0, std::ios::end); + std::streamsize size = file.tellg(); + file.seekg(0, std::ios::beg); + buffer.resize(static_cast(size)); + file.read(buffer.data(), size); + file.close(); + + fmt::buf::StreamView input(buffer.data(), buffer.size()); + detail::JsonParser parser(input); + T res; + JsonSerializer::parse(res, parser); + return res; + } + + template + void JsonFactory::SaveToPath(T& json, const std::filesystem::path& path, detail::JsonFormatter::FormatSettings settings) { + std::ofstream file(path.string(), std::ios::out); + + if (file.is_open() == false) throw std::runtime_error("unable to open file"); + + fmt::buf::DynamicStreamIOManager StreamIOManager(256); + fmt::buf::StreamIO ostream = fmt::buf::StreamIO::create(StreamIOManager); + detail::JsonFormatter formatter(ostream, settings); + JsonSerializer::format(json, formatter); + + file.write(StreamIOManager.get_buffer(), static_cast(StreamIOManager.get_last_generated_data_size())); + file.flush(); + file.close(); + } +} // namespace stream::json diff --git a/src/stream/json/json_formatter.hxx b/src/stream/json/json_formatter.hxx new file mode 100644 index 00000000..a32dac9d --- /dev/null +++ b/src/stream/json/json_formatter.hxx @@ -0,0 +1,98 @@ +#pragma once + +#include "json_objects.hxx" +#include "stream/fmt/buf/streamio.hxx" +#include "stream/fmt/buf/manip_io.hxx" + +namespace stream::json::detail { + class JsonFormatter { + public: + struct FormatSettings { + std::size_t indent_size = 4; + bool indent_with_spaces = true; + bool one_line = false; + bool ordered_struct = false; + std::int32_t float_precision = 7; + }; + + public: + JsonFormatter(stream::fmt::buf::StreamIO& ostream_) : ostream(ostream_), settings(), indent_(0) {} + JsonFormatter(stream::fmt::buf::StreamIO& ostream_, FormatSettings settings_) : ostream(ostream_), settings(settings_), indent_(0) {} + + public: + template + void format(const T& t); + + struct StructIntermediate; + struct ArrayIntermediate; + StructIntermediate get_struct_intermediate(); + ArrayIntermediate get_array_intermediate(); + + public: + void indent() { + if (settings.one_line) return; + + if (settings.indent_with_spaces) + fmt::buf::ManipIO(ostream).pushback(' ', indent_ * settings.indent_size); + else + fmt::buf::ManipIO(ostream).pushback('\t', indent_ * settings.indent_size); + } + + void NewLine() { + if (settings.one_line) return; + fmt::buf::ManipIO(ostream).pushback('\n'); + indent(); + } + void begin_new_object() { + ++indent_; + } + void end_new_object() { + --indent_; + } + + public: + fmt::buf::StreamIO& ostream; + FormatSettings settings; + + protected: + std::size_t indent_; + }; +} // namespace stream::json::detail + +namespace stream::json::detail { + struct JsonFormatter::StructIntermediate { + public: + StructIntermediate(JsonFormatter& formatter); + ~StructIntermediate(); + + public: + template + void format(const std::string_view name, const T& t); + + public: + JsonFormatter& Formatter; + std::uint32_t Idx; + }; + + struct JsonFormatter::ArrayIntermediate { + public: + ArrayIntermediate(JsonFormatter& formatter); + ~ArrayIntermediate(); + + public: + template + void format(const T& t); + + public: + JsonFormatter& Formatter; + std::uint32_t Idx; + }; + + inline JsonFormatter::StructIntermediate JsonFormatter::get_struct_intermediate() { + return JsonFormatter::StructIntermediate(*this); + } + + inline JsonFormatter::ArrayIntermediate JsonFormatter::get_array_intermediate() { + return JsonFormatter::ArrayIntermediate(*this); + } +} // namespace stream::json::detail diff --git a/src/StreamFormat/Json/JsonFormatter-inl.h b/src/stream/json/json_formatter_impl.hxx similarity index 60% rename from src/StreamFormat/Json/JsonFormatter-inl.h rename to src/stream/json/json_formatter_impl.hxx index 0f48a08c..feca8de5 100644 --- a/src/StreamFormat/Json/JsonFormatter-inl.h +++ b/src/stream/json/json_formatter_impl.hxx @@ -1,38 +1,27 @@ -#include "JsonFormatter.h" +#include "json_formatter.hxx" -#include "JsonSerializer.h" +#include "json_serializer.hxx" -namespace StreamFormat::JSON::Detail -{ - inline JsonFormatter::StructIntermediate::StructIntermediate(JsonFormatter& formatter) - : Formatter(formatter) - , Idx(0) - { +namespace stream::json::detail { + inline JsonFormatter::StructIntermediate::StructIntermediate(JsonFormatter& formatter) : Formatter(formatter), Idx(0) { JsonStructSerializer::FormatBegin(Formatter); } - inline JsonFormatter::StructIntermediate::~StructIntermediate() - { + inline JsonFormatter::StructIntermediate::~StructIntermediate() { JsonStructSerializer::FormatEnd(Formatter); } template - inline void JsonFormatter::StructIntermediate::Format(const std::string_view name, const T& t) - { + inline void JsonFormatter::StructIntermediate::format(const std::string_view name, const T& t) { JsonStructSerializer::FormatObject(name, t, Idx++, Formatter); } - inline JsonFormatter::ArrayIntermediate::ArrayIntermediate(JsonFormatter& formatter) - : Formatter(formatter) - , Idx(0) - { + inline JsonFormatter::ArrayIntermediate::ArrayIntermediate(JsonFormatter& formatter) : Formatter(formatter), Idx(0) { JsonArraySerializer::FormatBegin(Formatter); } - inline JsonFormatter::ArrayIntermediate::~ArrayIntermediate() - { + inline JsonFormatter::ArrayIntermediate::~ArrayIntermediate() { JsonArraySerializer::FormatEnd(Formatter); } template - inline void JsonFormatter::ArrayIntermediate::Format(const T& t) - { + inline void JsonFormatter::ArrayIntermediate::format(const T& t) { JsonArraySerializer::FormatObject(t, Idx++, Formatter); } -} +} // namespace stream::json::detail diff --git a/src/stream/json/json_objects.cxx b/src/stream/json/json_objects.cxx new file mode 100644 index 00000000..be14c878 --- /dev/null +++ b/src/stream/json/json_objects.cxx @@ -0,0 +1,46 @@ +#include "json_objects.hxx" +#include "serializers/json_objects_serializer.hxx" + +namespace stream::json { + void JsonStringObject::ParserExecute(detail::JsonParser& parser) { + JsonSerializer::parse(*this, parser); + } + void JsonStringObject::FormatterExecute(detail::JsonFormatter& formatter) const { + JsonSerializer::format(*this, formatter); + } + + void JsonNumberObject::ParserExecute(detail::JsonParser& parser) { + JsonSerializer::parse(*this, parser); + } + void JsonNumberObject::FormatterExecute(detail::JsonFormatter& formatter) const { + JsonSerializer::format(*this, formatter); + } + + void JsonBooleanObject::ParserExecute(detail::JsonParser& parser) { + JsonSerializer::parse(*this, parser); + } + void JsonBooleanObject::FormatterExecute(detail::JsonFormatter& formatter) const { + JsonSerializer::format(*this, formatter); + } + + void JsonStructObject::ParserExecute(detail::JsonParser& parser) { + JsonSerializer::parse(*this, parser); + } + void JsonStructObject::FormatterExecute(detail::JsonFormatter& formatter) const { + JsonSerializer::format(*this, formatter); + } + + void JsonArrayObject::ParserExecute(detail::JsonParser& parser) { + JsonSerializer::parse(*this, parser); + } + void JsonArrayObject::FormatterExecute(detail::JsonFormatter& formatter) const { + JsonSerializer::format(*this, formatter); + } + + void JsonNullObject::ParserExecute(detail::JsonParser& parser) { + JsonSerializer::parse(*this, parser); + } + void JsonNullObject::FormatterExecute(detail::JsonFormatter& formatter) const { + JsonSerializer::format(*this, formatter); + } +} // namespace stream::json diff --git a/src/stream/json/json_objects.hxx b/src/stream/json/json_objects.hxx new file mode 100644 index 00000000..9cfe7c16 --- /dev/null +++ b/src/stream/json/json_objects.hxx @@ -0,0 +1,227 @@ +#pragma once + +#include "detail.hxx" +#include "stream/fmt.hxx" + +#include +#include +#include +#include +#include + +namespace stream::json::detail { + class JsonParser; + class JsonFormatter; +} // namespace stream::json::detail + +namespace stream::json { + struct JsonObject { + public: + enum class ObjectType { + String, + Number, + Boolean, + Struct, + Array, + Null, + Undefined + }; + + public: + JsonObject() {} + JsonObject(ObjectType type) : type_(type) {} + + virtual ~JsonObject() = default; + + private: + ObjectType type_ = ObjectType::Undefined; + + public: + ObjectType get_type() { + return type_; + } + + JsonObject& operator[](const std::size_t index) { + return get(index); + } + JsonObject& operator[](const std::string_view subObject) { + return get(subObject); + } + + virtual JsonObject& get(const std::size_t) { + throw detail::JsonIndexingError{}; + } + virtual JsonObject& get(const std::string_view) { + throw detail::JsonIndexingError{}; + } + + public: + template + requires std::is_base_of_v + T& as() { + T* t = dynamic_cast(this); + if (t == nullptr) throw detail::JsonCastError{}; + return *t; + } + template + requires std::is_base_of_v + const T& as() const { + const T* t = dynamic_cast(this); + if (t == nullptr) throw detail::JsonCastError{}; + return *t; + } + + template + T read() { + T value; + JsonObjectSerializer::read_object(value, *this); + return value; + } + + template + void write(const T& t) { + JsonObjectSerializer::write_object(t, *this); + } + + std::string to_string() { + return fmt::format_string(*this); + } + + public: + virtual void ParserExecute(detail::JsonParser& parser) = 0; + virtual void FormatterExecute(detail::JsonFormatter& formatter) const = 0; + }; + + struct JsonStringObject final : public JsonObject { + JsonStringObject() : JsonObject(ObjectType::String) {} + JsonStringObject(const std::string_view value) : JsonObject(ObjectType::String), String(value) {} + JsonStringObject(std::string&& value) : JsonObject(ObjectType::String), String(std::move(value)) {} + ~JsonStringObject() override = default; + + public: + std::string String; + + public: + static std::unique_ptr create() { + return std::make_unique(); + } + static std::unique_ptr create(const std::string_view value) { + return std::make_unique(value); + } + static std::unique_ptr create(std::string&& value) { + return std::make_unique(std::move(value)); + } + + public: + void ParserExecute(detail::JsonParser& parser) override; + void FormatterExecute(detail::JsonFormatter& formatter) const override; + }; + + struct JsonNumberObject final : public JsonObject { + JsonNumberObject(double value = 0.0) : JsonObject(ObjectType::Number), Number(value) {} + ~JsonNumberObject() override = default; + + public: + double Number; + + public: + static std::unique_ptr create(double value = 0.0) { + return std::make_unique(value); + } + + public: + void ParserExecute(detail::JsonParser& parser) override; + void FormatterExecute(detail::JsonFormatter& formatter) const override; + }; + + struct JsonBooleanObject final : public JsonObject { + JsonBooleanObject(bool value = false) : JsonObject(ObjectType::Boolean), Boolean(value) {} + ~JsonBooleanObject() override = default; + + public: + bool Boolean; + + public: + static std::unique_ptr create(bool value = false) { + return std::make_unique(value); + } + + public: + void ParserExecute(detail::JsonParser& parser) override; + void FormatterExecute(detail::JsonFormatter& formatter) const override; + }; + + struct JsonStructObject final : public JsonObject { + public: + JsonStructObject() : JsonObject(ObjectType::Struct) {} + ~JsonStructObject() override = default; + + public: + static std::unique_ptr create() { + return std::make_unique(); + } + + public: + std::unordered_map> Objects; + + public: + void add(const std::string& name, std::unique_ptr&& object) { + Objects.insert({name, std::move(object)}); + } + void add(std::string&& name, std::unique_ptr&& object) { + Objects.insert({std::move(name), std::move(object)}); + } + JsonObject& get(const std::string_view subObject) override { + try { + return *Objects.at(std::string(subObject)); + } catch (...) { + throw detail::JsonIndexingError{}; + } + } + + public: + void ParserExecute(detail::JsonParser& parser) override; + void FormatterExecute(detail::JsonFormatter& formatter) const override; + }; + + struct JsonArrayObject final : public JsonObject { + public: + JsonArrayObject() : JsonObject(ObjectType::Array) {} + ~JsonArrayObject() override = default; + + public: + static std::unique_ptr create() { + return std::make_unique(); + } + + public: + std::vector> Objects; + + public: + void add(std::unique_ptr&& object) { + Objects.emplace_back(std::move(object)); + } + JsonObject& get(const std::size_t index) override { + return *Objects[index]; + } + + public: + void ParserExecute(detail::JsonParser& parser) override; + void FormatterExecute(detail::JsonFormatter& formatter) const override; + }; + + struct JsonNullObject final : public JsonObject { + public: + JsonNullObject() : JsonObject(ObjectType::Null) {} + ~JsonNullObject() override = default; + + public: + static std::unique_ptr create() { + return std::make_unique(); + } + + public: + void ParserExecute(detail::JsonParser& parser) override; + void FormatterExecute(detail::JsonFormatter& formatter) const override; + }; +} // namespace stream::json diff --git a/src/stream/json/json_parser.cxx b/src/stream/json/json_parser.cxx new file mode 100644 index 00000000..30a0fe8e --- /dev/null +++ b/src/stream/json/json_parser.cxx @@ -0,0 +1,69 @@ +#include "detail.hxx" + +#include + +#include +#include +#include + +#include "json_serializer.hxx" + +namespace stream::json::detail { + void JsonParser::Intermediate::parse(detail::JsonParser& parser) { + const fmt::buf::TestAccess access(parser.istream); + fmt::buf::TestManip manip(parser.istream); + + manip.IgnoreEveryBlanks(); + const char* const begin = parser.istream.current_pos; + + if (parser.is_json_string_begin()) { + manip.skip_one_of('"'); + while (true) { + manip.GoTo('"'); + if (fmt::buf::Access(parser.istream).get_prev_force() != '\\') { + break; + } + } + manip.skip_one_of('"'); + } else if (parser.is_json_number_begin()) { + float k = NAN; + JsonNumberSerializer::ParseFloat(k, parser); + } else if (parser.is_json_boolean_begin()) { + bool k = false; + JsonBooleanSerializer::ParseBool(k, parser); + } else if (parser.is_json_struct_begin()) { + JsonStructSerializer::LoadAllSubObjects( + *this, parser, [](JsonParser::Intermediate&, std::size_t, [[maybe_unused]] std::string&& str, JsonParser& json_parser) { + JsonParser::Intermediate intermediate; + intermediate.parse(json_parser); + }); + } else if (parser.is_json_array_begin()) { + JsonArraySerializer::LoadAllSubObjects(*this, parser, [](JsonParser::Intermediate&, std::size_t, JsonParser& json_parser) { + JsonParser::Intermediate intermediate; + intermediate.parse(json_parser); + }); + } else if (parser.is_json_null_begin()) { + JsonNullSerializer::ParseNull(parser); + } + + const char* const end = parser.istream.current_pos; + data = std::string_view(begin, end); + }; + + void JsonParser::StructIntermediate::parse(detail::JsonParser& parser) { + JsonStructSerializer::LoadAllSubObjects(*this, parser, + [](JsonParser::StructIntermediate& t, std::size_t, std::string&& name, JsonParser& json_parser) { + JsonParser::Intermediate intermediate; + intermediate.parse(json_parser); + t.Objects.insert({std::move(name), intermediate}); + }); + }; + + void JsonParser::ArrayIntermediate::parse(detail::JsonParser& parser) { + JsonArraySerializer::LoadAllSubObjects(*this, parser, [](JsonParser::ArrayIntermediate& t, std::size_t, JsonParser& json_parser) { + JsonParser::Intermediate intermediate; + intermediate.parse(json_parser); + t.Objects.emplace_back(intermediate); + }); + }; +} // namespace stream::json::detail diff --git a/src/stream/json/json_parser.hxx b/src/stream/json/json_parser.hxx new file mode 100644 index 00000000..91b0ffe8 --- /dev/null +++ b/src/stream/json/json_parser.hxx @@ -0,0 +1,108 @@ +#pragma once + +#include "stream/fmt/buf/stream.hxx" + +#include "json_objects.hxx" + +namespace stream::json::detail { + class JsonParser { + public: + JsonParser() : istream() {} + + JsonParser(fmt::buf::StreamView& input) : istream(input) {} + + public: + inline bool is_json_string_begin() const { + return fmt::buf::TestAccess(istream).is_equal_to('"'); + } + inline bool is_json_number_begin() const { + return fmt::buf::TestAccess(istream).is_a_digit() || fmt::buf::TestAccess(istream).is_equal_to('+', '-', '.'); + } + inline bool is_json_boolean_begin() const { + return fmt::buf::TestAccess(istream).is_equal_to('t', 'f'); + } + inline bool is_json_struct_begin() const { + return fmt::buf::TestAccess(istream).is_equal_to('{'); + } + inline bool is_json_array_begin() const { + return fmt::buf::TestAccess(istream).is_equal_to('['); + } + inline bool is_json_null_begin() const { + return fmt::buf::TestAccess(istream).is_equal_to('n'); + } + + public: + fmt::buf::Stream istream; + + public: + struct Intermediate; + + public: + template + void parse(T& t); + + struct StructIntermediate; + struct ArrayIntermediate; + StructIntermediate get_struct_intermediate(); + ArrayIntermediate get_array_intermediate(); + }; +} // namespace stream::json::detail + +namespace stream::json::detail { + struct JsonParser::Intermediate { + std::string_view data; + + void parse(detail::JsonParser& parser); + + template + void parse(T& t) { + JsonParser parser; + parser.parse(t); + } + }; + + struct JsonParser::StructIntermediate { + public: + friend JsonParser; + + private: + std::unordered_map Objects; + + void parse(detail::JsonParser& parser); + + public: + template + void parse(const std::string& name, T& t) { + if (Objects.contains(name) == false) throw detail::JsonGivenTypeError{}; + Objects[name].parse(t); + } + }; + + struct JsonParser::ArrayIntermediate { + public: + friend JsonParser; + + private: + std::vector Objects; + + void parse(detail::JsonParser& parser); + + public: + template + void parse(const std::size_t idx, T& t) { + if (idx >= Objects.size()) throw detail::JsonGivenTypeError{}; + Objects[idx].parse(t); + } + }; + + inline JsonParser::StructIntermediate JsonParser::get_struct_intermediate() { + JsonParser::StructIntermediate res; + res.parse(*this); + return res; + } + inline JsonParser::ArrayIntermediate JsonParser::get_array_intermediate() { + JsonParser::ArrayIntermediate res; + res.parse(*this); + return res; + } +} // namespace stream::json::detail diff --git a/src/stream/json/json_serializer.hxx b/src/stream/json/json_serializer.hxx new file mode 100644 index 00000000..035e48a9 --- /dev/null +++ b/src/stream/json/json_serializer.hxx @@ -0,0 +1,321 @@ +#pragma once + +#include "json_formatter.hxx" +#include "json_parser.hxx" + +#include "stream/fmt.hxx" +#include "stream/fmt/buf/read_manip.hxx" +#include "stream/fmt/buf/write_manip.hxx" +#include "stream/fmt/buf/utils/buffer_utils.hxx" + +#include +#include + +namespace stream::json { + template + struct JsonSerializer { + static inline void parse(T&, detail::JsonParser&) { +#ifdef UNKOWN_TYPE_MESSAGE + fmt::file_print(std::cerr, "{C:red}JsonSerializer::Parse<{}> not impl", typeid(T).name()); +#endif +#ifdef UNKOWN_TYPE_THROW + throw detail::JsonTypeSerializerNotImpl{}; +#endif +#ifdef UNKOWN_TYPE_FAIL + // FIXME + throw detail::JsonTypeSerializerNotImpl{}; +#endif +#ifdef UNKOWN_TYPE_DEBUG + STREAMFORMAT_DEBUGBREAK(); +#endif + } + + static inline void format(const T&, detail::JsonFormatter& formatter) { + fmt::buf::WriteManip(formatter.ostream).fast_write_sv(std::string_view("Unknown JsonFormatter for type : ")); + fmt::buf::WriteManip(formatter.ostream).fast_write_sv(std::string_view(typeid(T).name())); + +#ifdef UNKOWN_TYPE_MESSAGE + fmt::file_print(std::cerr, "{C:red}JsonSerializer::Format<{}> not impl", typeid(T).name()); +#endif +#ifdef UNKOWN_TYPE_THROW + throw detail::JsonTypeSerializerNotImpl{}; +#endif +#ifdef UNKOWN_TYPE_FAIL + // FIXME + throw detail::JsonTypeSerializerNotImpl{}; +#endif +#ifdef UNKOWN_TYPE_DEBUG + STREAMFORMAT_DEBUGBREAK(); +#endif + } + }; + + template + struct JsonObjectSerializer { + static inline void read_object(T&, const JsonObject&) { +#ifdef UNKOWN_TYPE_MESSAGE + fmt::file_print(std::cerr, "{C:red}JsonObjectSerializer::read_object<{}> not impl", typeid(T).name()); +#endif +#ifdef UNKOWN_TYPE_THROW + throw detail::JsonTypeSerializerNotImpl{}; +#endif +#ifdef UNKOWN_TYPE_FAIL + // FIXME + throw detail::JsonTypeSerializerNotImpl{}; +#endif +#ifdef UNKOWN_TYPE_DEBUG + STREAMFORMAT_DEBUGBREAK(); +#endif + } + + static inline void write_object(const T&, JsonObject&) { +#ifdef UNKOWN_TYPE_MESSAGE + fmt::file_print(std::cerr, "{C:red}JsonObjectSerializer::write_object<{}> not impl", typeid(T).name()); +#endif +#ifdef UNKOWN_TYPE_THROW + throw detail::JsonTypeSerializerNotImpl{}; +#endif +#ifdef UNKOWN_TYPE_FAIL + // FIXME + throw detail::JsonTypeSerializerNotImpl{}; +#endif +#ifdef UNKOWN_TYPE_DEBUG + STREAMFORMAT_DEBUGBREAK(); +#endif + } + }; + + struct JsonStringSerializer { + static inline void ParseSTDString(std::string& t, detail::JsonParser& parser) { + fmt::buf::DynamicStreamIOManager bufferData; + fmt::buf::StreamIO buffer = fmt::buf::StreamIO::create(bufferData); + fmt::buf::utils::parse_escaped_quoted_string(parser.istream, buffer); + fmt::buf::ManipIO(buffer).compute_generated_size(); + t = bufferData.get_last_generated_string_view(); + } + + static inline void FormatSTDString(const std::string_view t, detail::JsonFormatter& formatter) { + fmt::buf::Stream buffer(t.data(), t.size()); + fmt::buf::utils::format_escaped_quoted_string(formatter.ostream, buffer); + } + }; + + struct JsonNumberSerializer { + template + static inline void ParseFloat(FloatType& t, detail::JsonParser& parser) { + fmt::buf::ReadManip(parser.istream).fast_read_float(t); + } + + template + static inline void ParseInteger(IntType& t, detail::JsonParser& parser) { + const char* begin = parser.istream.current_pos; + float tmp = 0; + fmt::buf::ReadManip(parser.istream).fast_read_float(tmp); + const char* end = parser.istream.current_pos; + + parser.istream.current_pos = begin; + fmt::buf::ReadManip(parser.istream).fast_read_integer(t); + parser.istream.current_pos = end; + } + + template + static inline void FormatFloat(const FloatType& t, detail::JsonFormatter& formatter) { + fmt::buf::WriteManip(formatter.ostream).fast_write_float(t, formatter.settings.float_precision); + } + + template + static inline void FormatInteger(const IntType& t, detail::JsonFormatter& formatter) { + fmt::buf::WriteManip(formatter.ostream).fast_write_integer(t); + } + }; + + struct JsonBooleanSerializer { + static inline void ParseBool(bool& t, detail::JsonParser& parser) { + if (fmt::buf::TestManip(parser.istream).is_same_forward("true", 5)) + t = true; + else if (fmt::buf::TestManip(parser.istream).is_same_forward("false", 5)) + t = false; + } + + static inline void FormatBool(const bool& t, detail::JsonFormatter& formatter) { + if (t) + fmt::buf::WriteManip(formatter.ostream).fast_write_literal("true"); + else + fmt::buf::WriteManip(formatter.ostream).fast_write_literal("false"); + } + }; + + struct JsonStructSerializer { + template + static inline void LoadAllSubObjects(T& t, detail::JsonParser& parser, std::function subObjectParsingFunction) { + fmt::buf::TestAccess access(parser.istream); + fmt::buf::TestManip manip(parser.istream); + + manip.skip_one_of('{'); + std::size_t idx = 0; + + while (parser.istream.is_end_of_string() == false) { + manip.GoTo('"', '}'); + if (access.is_equal_to('}')) break; + + std::string name; + JsonStringSerializer::ParseSTDString(name, parser); + + manip.IgnoreEveryBlanks(); + manip.skip_one_of(':'); + manip.IgnoreEveryBlanks(); + + subObjectParsingFunction(t, idx++, std::move(name), parser); + + manip.GoTo(',', '}'); + manip.skip_one_of(','); + } + + manip.skip_one_of('}'); + } + + template + static inline void LoadAllSubObjects(T& t, detail::JsonParser& parserObject) { + LoadAllSubObjects(t, parserObject, [](T& mainObject, std::size_t idx, std::string&& name, detail::JsonParser& parser) { + typename JsonSerializer::StructSubObjectType subObject; + parser.parse(subObject); + JsonSerializer::add_struct_sub_object(mainObject, idx, std::move(name), std::move(subObject)); + }); + } + + static inline void FormatBegin(detail::JsonFormatter& formatter) { + fmt::buf::ManipIO(formatter.ostream).pushback('{'); + } + + static inline void FormatEnd(detail::JsonFormatter& formatter) { + formatter.NewLine(); + fmt::buf::ManipIO(formatter.ostream).pushback('}'); + } + + template + static inline void FormatObject(const std::string_view name, const SubObject& subObject, const std::size_t idx, detail::JsonFormatter& formatter) { + if (idx != 0) fmt::buf::ManipIO(formatter.ostream).pushback(','); + + formatter.begin_new_object(); + formatter.NewLine(); + JsonStringSerializer::FormatSTDString(name, formatter); + fmt::buf::ManipIO(formatter.ostream).pushback(':'); + fmt::buf::ManipIO(formatter.ostream).pushback(' '); + formatter.format(subObject); + formatter.end_new_object(); + } + }; + + struct JsonArraySerializer { + template + static inline void LoadAllSubObjects(T& t, detail::JsonParser& parser, std::function subObjectParsingFunction) { + fmt::buf::TestAccess access(parser.istream); + fmt::buf::TestManip manip(parser.istream); + + manip.skip_one_of('['); + std::size_t idx = 0; + + while (parser.istream.is_end_of_string() == false) { + manip.IgnoreEveryBlanks(); + + if (access.is_equal_to(']')) break; + + subObjectParsingFunction(t, idx++, parser); + + manip.GoTo(',', ']'); + manip.skip_one_of(','); + } + + manip.skip_one_of(']'); + } + + template + static inline void LoadAllSubObjects(T& t, detail::JsonParser& parser) { + LoadAllSubObjects(t, parser, [](T& mainObject, std::size_t idx, detail::JsonParser& json_parser) { + typename JsonSerializer::ArraySubObjectType subObject; + json_parser.parse(subObject); + JsonSerializer::AddArraySubObject(mainObject, idx, std::move(subObject)); + }); + } + + static inline void FormatBegin(detail::JsonFormatter& formatter) { + fmt::buf::ManipIO(formatter.ostream).pushback('['); + } + + static inline void FormatEnd(detail::JsonFormatter& formatter) { + formatter.NewLine(); + fmt::buf::ManipIO(formatter.ostream).pushback(']'); + } + + template + static inline void FormatObject(const SubObject& subObject, const std::size_t idx, detail::JsonFormatter& formatter) { + if (idx != 0) fmt::buf::ManipIO(formatter.ostream).pushback(','); + + formatter.begin_new_object(); + formatter.NewLine(); + formatter.format(subObject); + formatter.end_new_object(); + } + }; + + struct JsonNullSerializer { + static inline void ParseNull(detail::JsonParser& parser) { + fmt::buf::TestManip(parser.istream).is_same_forward("null", 4); + } + + static inline void FormatNull(detail::JsonFormatter& formatter) { + fmt::buf::WriteManip(formatter.ostream).fast_write_literal("null"); + } + }; +} // namespace stream::json + +namespace stream::json::detail { + template + void JsonFormatter::format(const T& t) { + JsonSerializer::format(t, *this); + } + + template + void JsonParser::parse(T& t) { + JsonSerializer::parse(t, *this); + } +} // namespace stream::json::detail + +namespace stream::json { + template + struct FormatAsJson { + public: + FormatAsJson(const T& value) : value(value) {} + + public: + const T& value; + }; +} // namespace stream::json + +#include "stream/fmt.hxx" +namespace stream::fmt { +#ifdef STREAMFORMAT_FORMATTER_DECLARED + template + struct FormatterType, FormatterExecutor> { + static void format(const json::FormatAsJson& json, FormatterExecutor& executor) { + bool ordered_struct = executor.data.specifiers.has("ordered_struct"); + json::detail::JsonFormatter::FormatSettings settings{.ordered_struct = ordered_struct, .float_precision = executor.data.float_precision}; + json::detail::JsonFormatter jsonFormatter(executor.ostream, settings); + json::JsonSerializer::format(json.value, jsonFormatter); + } + }; +#endif + +#ifdef STREAMFORMAT_PARSER_DECLARED + template + struct ParserType, ParserExecutor> { + static void parse(T& json, ParserExecutor& executor) { + json::detail::JsonParser json_parser(*executor.istream.manager); + json_parser.istream.current_pos = executor.istream.current_pos; + // TODO: + // json::JsonSerializer::parse(json.value, json_parser); + executor.istream.current_pos = json_parser.istream.current_pos; + } + }; +#endif +} // namespace stream::fmt diff --git a/src/stream/json/serializers/base_serializers.hxx b/src/stream/json/serializers/base_serializers.hxx new file mode 100644 index 00000000..6827e7d6 --- /dev/null +++ b/src/stream/json/serializers/base_serializers.hxx @@ -0,0 +1,68 @@ +#pragma once + +#include "../json_objects.hxx" +#include "../json_serializer.hxx" + +#include + +namespace stream::json { + template + requires(std::is_integral_v && !std::is_floating_point_v) + struct JsonSerializer { + static inline void parse(T& t, detail::JsonParser& parser) { + JsonNumberSerializer::ParseInteger(t, parser); + } + static inline void format(const T t, detail::JsonFormatter& formatter) { + JsonNumberSerializer::FormatInteger(t, formatter); + } + }; + + template + requires std::is_floating_point_v + struct JsonSerializer { + static inline void parse(T& t, detail::JsonParser& parser) { + JsonNumberSerializer::ParseFloat(t, parser); + } + static inline void format(const T t, detail::JsonFormatter& formatter) { + JsonNumberSerializer::FormatFloat(t, formatter); + } + }; + + template + struct JsonSerializer { + using ArraySubObjectType = T; + static inline void AddArraySubObject(T (&t)[SIZE], std::size_t idx, ArraySubObjectType&& subObject) { + t[idx] = std::move(subObject); + } + + static inline void parse(T (&t)[SIZE], detail::JsonParser& parser) { + if constexpr (fmt::detail::IsCharType::value) { + // TODO + } else { + JsonArraySerializer::LoadAllSubObjects(t, parser); + } + } + + static inline void format(const T (&t)[SIZE], detail::JsonFormatter& formatter) { + if constexpr (fmt::detail::IsCharType::value) { + // TODO + } else { + JsonArraySerializer::FormatBegin(formatter); + for (std::size_t idx = 0; idx < SIZE; ++idx) + JsonArraySerializer::FormatObject(t[idx], idx, formatter); + JsonArraySerializer::FormatEnd(formatter); + } + } + }; + template + struct JsonSerializer { + static inline void parse([[maybe_unused]] T* t, detail::JsonParser& parser) { + if (t == nullptr) throw detail::JsonGivenTypeError{}; + // TODO + } + static inline void format([[maybe_unused]] const T* t, detail::JsonFormatter& formatter) { + if (t == nullptr) throw detail::JsonGivenTypeError{}; + // TODO + } + }; +} // namespace stream::json diff --git a/src/stream/json/serializers/json_objects_serializer.hxx b/src/stream/json/serializers/json_objects_serializer.hxx new file mode 100644 index 00000000..a9ce8ac0 --- /dev/null +++ b/src/stream/json/serializers/json_objects_serializer.hxx @@ -0,0 +1,116 @@ +#pragma once + +#include "../json_objects.hxx" +#include "../json_serializer.hxx" + +#include "std_serializers/json_unordered_map.hxx" +#include "std_serializers/json_vector.hxx" + +#include + +namespace stream::json { + template <> + struct JsonSerializer> { + static inline void parse(std::unique_ptr& t, detail::JsonParser& parser) { + fmt::buf::TestManip(parser.istream).IgnoreEveryBlanks(); + if (parser.is_json_string_begin()) + t = std::make_unique(); + else if (parser.is_json_number_begin()) + t = std::make_unique(); + else if (parser.is_json_boolean_begin()) + t = std::make_unique(); + else if (parser.is_json_struct_begin()) + t = std::make_unique(); + else if (parser.is_json_array_begin()) + t = std::make_unique(); + else if (parser.is_json_null_begin()) + t = std::make_unique(); + + t->ParserExecute(parser); + } + + static inline void format(const std::unique_ptr& t, detail::JsonFormatter& formatter) { + t->FormatterExecute(formatter); + } + }; + + template <> + struct JsonSerializer { + static inline void format(const JsonObject& t, detail::JsonFormatter& formatter) { + t.FormatterExecute(formatter); + } + }; + + template <> + struct JsonSerializer { + static inline void parse(JsonStringObject& t, detail::JsonParser& parser) { + t.String.clear(); + JsonStringSerializer::ParseSTDString(t.String, parser); + } + + static inline void format(const JsonStringObject& t, detail::JsonFormatter& formatter) { + JsonStringSerializer::FormatSTDString(t.String, formatter); + } + }; + + template <> + struct JsonSerializer { + static inline void parse(JsonNumberObject& t, detail::JsonParser& parser) { + JsonNumberSerializer::ParseFloat(t.Number, parser); + } + + static inline void format(const JsonNumberObject& t, detail::JsonFormatter& formatter) { + JsonNumberSerializer::FormatFloat(t.Number, formatter); + } + }; + + template <> + struct JsonSerializer { + static inline void parse(JsonBooleanObject& t, detail::JsonParser& parser) { + JsonBooleanSerializer::ParseBool(t.Boolean, parser); + } + + static inline void format(const JsonBooleanObject& t, detail::JsonFormatter& formatter) { + JsonBooleanSerializer::FormatBool(t.Boolean, formatter); + } + }; + + template <> + struct JsonSerializer { + static inline void parse(JsonNullObject&, detail::JsonParser& parser) { + JsonNullSerializer::ParseNull(parser); + } + + static inline void format(const JsonNullObject&, detail::JsonFormatter& formatter) { + JsonNullSerializer::FormatNull(formatter); + } + }; + + template <> + struct JsonSerializer { + static inline void parse(JsonStructObject& t, detail::JsonParser& parser) { + parser.parse(t.Objects); + } + static inline void format(const JsonStructObject& t, detail::JsonFormatter& formatter) { + if (formatter.settings.ordered_struct == false) { + formatter.format(t.Objects); + return; + } + + std::map objectsOrdered; + for (auto& [name, objects] : t.Objects) + objectsOrdered.insert({name, objects.get()}); + formatter.format(objectsOrdered); + } + }; + + template <> + struct JsonSerializer { + static inline void parse(JsonArrayObject& t, detail::JsonParser& parser) { + parser.parse(t.Objects); + } + static inline void format(const JsonArrayObject& t, detail::JsonFormatter& formatter) { + formatter.format(t.Objects); + } + }; +} // namespace stream::json diff --git a/src/stream/json/serializers/serializers.hxx b/src/stream/json/serializers/serializers.hxx new file mode 100644 index 00000000..20426d0e --- /dev/null +++ b/src/stream/json/serializers/serializers.hxx @@ -0,0 +1,5 @@ +#pragma once + +#include "base_serializers.hxx" +#include "json_objects_serializer.hxx" +#include "std_serializers/basic_std_serializers.hxx" diff --git a/src/stream/json/serializers/std_serializers/basic_std_serializers.hxx b/src/stream/json/serializers/std_serializers/basic_std_serializers.hxx new file mode 100644 index 00000000..80f5b93f --- /dev/null +++ b/src/stream/json/serializers/std_serializers/basic_std_serializers.hxx @@ -0,0 +1,27 @@ +#pragma once + +#include "stream/json/json_serializer.hxx" + +#include + +namespace stream::json { + template <> + struct JsonSerializer { + static inline void parse(std::string& t, detail::JsonParser& parser) { + JsonStringSerializer::ParseSTDString(t, parser); + } + static inline void format(const std::string& t, detail::JsonFormatter& formatter) { + JsonStringSerializer::FormatSTDString(t, formatter); + } + }; + + template <> + struct JsonSerializer { + static inline void parse(std::string_view& t, detail::JsonParser& parser) { + // TODO: + } + static inline void format(const std::string_view& t, detail::JsonFormatter& formatter) { + JsonStringSerializer::FormatSTDString(t, formatter); + } + }; +} // namespace stream::json diff --git a/src/stream/json/serializers/std_serializers/json_map.hxx b/src/stream/json/serializers/std_serializers/json_map.hxx new file mode 100644 index 00000000..4050f143 --- /dev/null +++ b/src/stream/json/serializers/std_serializers/json_map.hxx @@ -0,0 +1,51 @@ +#pragma once + +#include "stream/json/json_serializer.hxx" + +#include + +namespace stream::json { + template + struct JsonSerializer> { + using KeyType = K; + using StructSubObjectType = T; + + static void parse(std::map& t, detail::JsonParser& parser) { + JsonStructSerializer::LoadAllSubObjects>(t, parser); + } + static void add_struct_sub_object(std::map& t, std::size_t /*unused*/, std::string&& name, StructSubObjectType&& sub_object) { + t.insert({std::move(name), std::move(sub_object)}); + } + + static void format(const std::map& t, detail::JsonFormatter& formatter) { + JsonStructSerializer::FormatBegin(formatter); + std::size_t idx = 0; + for (const auto& [name, object] : t) { + JsonStructSerializer::FormatObject(name, object, idx++, formatter); + } + JsonStructSerializer::FormatEnd(formatter); + } + }; + + template + struct JsonSerializer> { + using KeyType = K; + using StructSubObjectType = T; + + static void parse(std::multimap& t, detail::JsonParser& parser) { + JsonStructSerializer::LoadAllSubObjects>(t, parser); + } + static void add_struct_sub_object(std::multimap& t, std::size_t /*unused*/, std::string&& name, StructSubObjectType&& sub_object) { + t.insert({std::move(name), std::move(sub_object)}); + } + + static void format(const std::multimap& t, detail::JsonFormatter& formatter) { + JsonStructSerializer::FormatBegin(formatter); + std::size_t idx = 0; + for (const auto& [name, object] : t) { + JsonStructSerializer::FormatObject(name, object, idx++, formatter); + } + JsonStructSerializer::FormatEnd(formatter); + } + }; +} // namespace stream::json diff --git a/src/StreamFormat/Json/Serializers/STDSerializers/JSON_unordered_map.h b/src/stream/json/serializers/std_serializers/json_unordered_map.hxx similarity index 51% rename from src/StreamFormat/Json/Serializers/STDSerializers/JSON_unordered_map.h rename to src/stream/json/serializers/std_serializers/json_unordered_map.hxx index cc56a68f..83a88f70 100644 --- a/src/StreamFormat/Json/Serializers/STDSerializers/JSON_unordered_map.h +++ b/src/stream/json/serializers/std_serializers/json_unordered_map.hxx @@ -1,26 +1,24 @@ #pragma once -#include "StreamFormat/Json/JsonObjects.h" -#include "StreamFormat/Json/JsonSerializer.h" +#include "stream/json/json_objects.hxx" +#include "stream/json/json_serializer.hxx" #include -namespace StreamFormat::JSON -{ +namespace stream::json { template - struct JsonSerializer> - { + struct JsonSerializer> { using KeyType = K; using StructSubObjectType = T; - static inline void Parse(std::unordered_map& t, Detail::JsonParser& parser) { JsonStructSerializer::LoadAllSubObjects>(t, parser); } - static inline void AddStructSubObject(std::unordered_map& t, std::size_t, std::string&& name, StructSubObjectType&& subObject) - { + static inline void parse(std::unordered_map& t, detail::JsonParser& parser) { + JsonStructSerializer::LoadAllSubObjects>(t, parser); + } + static inline void add_struct_sub_object(std::unordered_map& t, std::size_t, std::string&& name, StructSubObjectType&& subObject) { t.insert({std::move(name), std::move(subObject)}); } - static inline void Format(const std::unordered_map& t, Detail::JsonFormatter& formatter) - { + static inline void format(const std::unordered_map& t, detail::JsonFormatter& formatter) { JsonStructSerializer::FormatBegin(formatter); std::size_t idx = 0; for (const auto& [name, object] : t) @@ -30,22 +28,18 @@ namespace StreamFormat::JSON }; template - struct JsonSerializer> - { + struct JsonSerializer> { using KeyType = K; using StructSubObjectType = T; - static inline void Parse(std::unordered_multimap& t, Detail::JsonParser& parser) - { + static inline void parse(std::unordered_multimap& t, detail::JsonParser& parser) { JsonStructSerializer::LoadAllSubObjects>(t, parser); } - static inline void AddStructSubObject(std::unordered_multimap& t, std::size_t, std::string&& name, StructSubObjectType&& subObject) - { + static inline void add_struct_sub_object(std::unordered_multimap& t, std::size_t, std::string&& name, StructSubObjectType&& subObject) { t.insert({std::move(name), std::move(subObject)}); } - static inline void Format(const std::unordered_multimap& t, Detail::JsonFormatter& formatter) - { + static inline void format(const std::unordered_multimap& t, detail::JsonFormatter& formatter) { JsonStructSerializer::FormatBegin(formatter); std::size_t idx = 0; for (const auto& [name, object] : t) @@ -53,4 +47,4 @@ namespace StreamFormat::JSON JsonStructSerializer::FormatEnd(formatter); } }; -} +} // namespace stream::json diff --git a/src/stream/json/serializers/std_serializers/json_vector.hxx b/src/stream/json/serializers/std_serializers/json_vector.hxx new file mode 100644 index 00000000..f8f7b48f --- /dev/null +++ b/src/stream/json/serializers/std_serializers/json_vector.hxx @@ -0,0 +1,28 @@ +#pragma once + +#include "stream/json/json_objects.hxx" +#include "stream/json/json_serializer.hxx" + +#include + +namespace stream::json { + template + struct JsonSerializer> { + using ArraySubObjectType = T; + + static inline void parse(std::vector& t, detail::JsonParser& parser) { + JsonArraySerializer::LoadAllSubObjects>(t, parser); + } + static inline void AddArraySubObject(std::vector& t, std::size_t, ArraySubObjectType&& subObject) { + t.emplace_back(std::move(subObject)); + } + + static inline void format(const std::vector& t, detail::JsonFormatter& formatter) { + JsonArraySerializer::FormatBegin(formatter); + std::size_t idx = 0; + for (const ArraySubObjectType& subObject : t) + JsonArraySerializer::FormatObject(subObject, idx++, formatter); + JsonArraySerializer::FormatEnd(formatter); + } + }; +} // namespace stream::json diff --git a/src/stream/profiler.hxx b/src/stream/profiler.hxx new file mode 100644 index 00000000..a2714559 --- /dev/null +++ b/src/stream/profiler.hxx @@ -0,0 +1,4 @@ +#pragma once + +#include "profiler/profiler.hxx" +#include "profiler/profiler_factory.hxx" diff --git a/src/stream/profiler/all_events.hxx b/src/stream/profiler/all_events.hxx new file mode 100644 index 00000000..976a8a5d --- /dev/null +++ b/src/stream/profiler/all_events.hxx @@ -0,0 +1,31 @@ +#pragma once + +#include "event.hxx" + +namespace stream::profiler { + class DurationEvent : public Event { + public: + DurationEvent(const std::string& name, const std::string& category = "DurationEvent") : Event(name, category, EventType::Complete) {} + + DurationEvent(std::string&& name, std::string&& category = "DurationEvent") : Event(std::move(name), std::move(category), EventType::Complete) {} + + ~DurationEvent() override = default; + + public: + void start() { + trigger(); + } + void stop() { + info.duration = profiler::get_nanoseconds() - info.time_of_event; + } + }; + + class SampleEvent : public Event { + public: + SampleEvent(const std::string& name, const std::string& category = "SampleEvent") : Event(name, category, EventType::Sample) {} + + SampleEvent(std::string&& name, std::string&& category) : Event(std::move(name), std::move(category), EventType::Sample) {} + + ~SampleEvent() override = default; + }; +} // namespace stream::profiler diff --git a/src/stream/profiler/detail.hxx b/src/stream/profiler/detail.hxx new file mode 100644 index 00000000..d530e7d9 --- /dev/null +++ b/src/stream/profiler/detail.hxx @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace stream::profiler { + inline std::chrono::nanoseconds get_nanoseconds() { + return std::chrono::time_point_cast(std::chrono::high_resolution_clock::now()).time_since_epoch(); + } +}; // namespace stream::profiler diff --git a/src/stream/profiler/event.hxx b/src/stream/profiler/event.hxx new file mode 100644 index 00000000..f789471d --- /dev/null +++ b/src/stream/profiler/event.hxx @@ -0,0 +1,123 @@ +#pragma once + +#include "detail.hxx" +#include "event_data.hxx" +#include "stream/core/prelude.hxx" +#include "stream/fmt.hxx" + +#include +#include +#include +#include + +// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview + +namespace stream::profiler { + int get_pid(); + + enum class EventType : char { + Unknow = '.', + + DurationBegin = 'b', + DurationEnd = 'E', + + AsyncStart = 'b', + AsyncInstant = 'n', + AsyncEnd = 'e', + + FlowStart = 's', + FlowStep = 't', + FlowEnd = 'f', + + Objectcreated = 'N', + Objectsnapshot = 'O', + ObjectDestroyed = 'D', + + MemoryDumpGlobal = 'V', + MemoryDumpProcess = 'v', + + Complete = 'X', + Instant = 'i', + Counter = 'C', + Sample = 'P', + MetaData = 'M', + Mark = 'r', + ClockSyncEvents = 'c', + Context = ',' // '(' ')' + }; + + struct EventInfo { + public: + EventInfo() + : name("Unknow"), + category("Unknow"), + type(EventType::Unknow), + id(0), + time_of_event(profiler::get_nanoseconds()), + duration(0), + pid(get_pid()), + tid(std::hash{}(std::this_thread::get_id())), + data(nullptr) {} + + EventInfo(const std::string& name, const std::string& category, EventType type, EventData* data = nullptr) + : name(name), + category(category), + type(type), + id(0), + time_of_event(profiler::get_nanoseconds()), + duration(0), + pid(get_pid()), + tid(std::hash{}(std::this_thread::get_id())), + data(data) {} + + EventInfo(std::string&& name, std::string&& category, EventType type, EventData* data = nullptr) + : name(std::move(name)), + category(std::move(category)), + type(type), + id(0), + time_of_event(profiler::get_nanoseconds()), + duration(0), + pid(get_pid()), + tid(std::hash{}(std::this_thread::get_id())), + data(data) {} + + public: + std::string name; + std::string category; + EventType type; + std::size_t id; + std::chrono::nanoseconds time_of_event; + std::chrono::nanoseconds duration; + int pid; + std::size_t tid; + std::shared_ptr data; + }; + + struct Event { + public: + Event() = default; + + Event(const std::string& name, const std::string& category, EventType type, EventData* data = nullptr) : info(name, category, type, data) {} + + Event(std::string&& name, std::string&& category, EventType type, EventData* data = nullptr) : info(std::move(name), std::move(category), type, data) {} + + virtual ~Event() = default; + + public: + void trigger() { + info.time_of_event = profiler::get_nanoseconds(); + } + + public: + EventInfo info; + }; +} // namespace stream::profiler + +namespace stream::fmt { + template + struct FormatterType { + static void format(const stream::profiler::EventType& t, FormatterExecutor& executor) { + return executor.ostream.pushback(static_cast(t)); + } + }; +} // namespace stream::fmt diff --git a/src/stream/profiler/event_data.hxx b/src/stream/profiler/event_data.hxx new file mode 100644 index 00000000..2cfd9425 --- /dev/null +++ b/src/stream/profiler/event_data.hxx @@ -0,0 +1,28 @@ +#pragma once + +#include "stream/json.hxx" + +namespace stream::profiler { + class EventData { + public: + virtual ~EventData() = default; + + public: + virtual void to_json(json::detail::JsonFormatter& formatter) const = 0; + virtual void FromJson(json::detail::JsonParser& parser) = 0; + }; + + class EventDataJsonObject final : public EventData { + public: + ~EventDataJsonObject() override = default; + + public: + void to_json(json::detail::JsonFormatter& formatter) const override { + json::JsonSerializer::format(data, formatter); + } + void FromJson(json::detail::JsonParser& parser) override { + json::JsonSerializer::parse(data, parser); + } + json::JsonStructObject data; + }; +} // namespace stream::profiler diff --git a/src/StreamFormat/ProfilerManager/GetPid.cpp b/src/stream/profiler/get_pid.cxx similarity index 61% rename from src/StreamFormat/ProfilerManager/GetPid.cpp rename to src/stream/profiler/get_pid.cxx index a535e715..f1a967b1 100644 --- a/src/StreamFormat/ProfilerManager/GetPid.cpp +++ b/src/stream/profiler/get_pid.cxx @@ -9,12 +9,12 @@ #include #endif -namespace StreamFormat::ProfilerManager -{ - int GetPid() - { +// NOLINTBEGIN(misc-use-internal-linkage) + +namespace stream::profiler { + int get_pid() { #ifdef STREAMFORMAT_PLATFORM_LINUX - return getpid(); +#define return getpid(); #endif #ifdef STREAMFORMAT_PLATFORM_WINDOWS @@ -22,4 +22,6 @@ namespace StreamFormat::ProfilerManager #endif return 0; } -} \ No newline at end of file +} // namespace stream::profiler + +// NOLINTEND(misc-use-internal-linkage) diff --git a/src/stream/profiler/profiler.hxx b/src/stream/profiler/profiler.hxx new file mode 100644 index 00000000..a8dd21c9 --- /dev/null +++ b/src/stream/profiler/profiler.hxx @@ -0,0 +1,44 @@ +#pragma once + +#include "stream/core/prelude.hxx" +#include "stream/flog.hxx" + +#include "all_events.hxx" +#include "event.hxx" +#include "profiler_event_creator.hxx" + +namespace stream::profiler { + class Profiler { + public: + explicit Profiler(std::string&& name) : name(name), logger(name), profiler_duration(name) { + events.clear(); + events.push_back(EventInfo{}); + profiler_duration.start(); + } + + ~Profiler() {} + + public: + void add_event(const Event& event) { + add_event_info(event.info); + } + void add_event_info(const EventInfo& eventInfo) { + events.push_back(eventInfo); + } + inline stream::flog::BasicLogger& get_logger() { + return logger; + } + + public: + static Profiler& get_instance() { + static Profiler profiler("profiler"); + return profiler; + } + + public: + std::string name; + flog::BasicLogger logger; + DurationEvent profiler_duration; + std::vector events; + }; +} // namespace stream::profiler diff --git a/src/stream/profiler/profiler_event_creator.cxx b/src/stream/profiler/profiler_event_creator.cxx new file mode 100644 index 00000000..91cb9ee0 --- /dev/null +++ b/src/stream/profiler/profiler_event_creator.cxx @@ -0,0 +1,67 @@ +#include "profiler_event_creator.hxx" +#include "profiler.hxx" + +namespace stream::profiler { + // TODO(sacha): + // NOLINTBEGIN(bugprone-exception-escape) + ScopeProfile::~ScopeProfile() { + terminate(); + } + // NOLINTEND(bugprone-exception-escape) + + void ScopeProfile::terminate() { + stop(); + + const std::chrono::microseconds us = std::chrono::duration_cast(info.duration); + const std::chrono::milliseconds millis = std::chrono::duration_cast(info.duration); + const std::chrono::seconds seconds = std::chrono::duration_cast(info.duration); + + // NOLINTBEGIN(readability-magic-numbers) + // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + if (seconds.count() > 2) { + profiler_.get_logger().trace("{} : {} seconds", info.name, seconds.count()); + } else if (millis.count() > 5) { + profiler_.get_logger().trace("{} : {} ms", info.name, millis.count()); + } else { + profiler_.get_logger().trace("{} : {} us", info.name, us.count()); + } + // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) + // NOLINTEND(readability-magic-numbers) + + profiler_.add_event(*this); + } + + + ObjectTracker::ObjectTracker(Profiler& profiler, const std::string& name, const std::string& category) : profiler_(profiler), name_(name), category_(category) { + Event const created(name_, category_, EventType::Objectcreated); + profiler_.add_event(created); + } + + // NOLINTBEGIN(readability-magic-numbers) + // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + ObjectTracker::ObjectTracker(Profiler& profiler, std::string&& name, std::string&& category) : profiler_(profiler), name_(std::move(name)), category_(std::move(category)) { + Event created(name_, category_, EventType::Objectcreated); + created.info.id = 10; + profiler_.add_event(created); + } + + ObjectTracker::~ObjectTracker() { + Event destroyed(name_, category_, EventType::ObjectDestroyed); + destroyed.info.id = 10; + profiler_.add_event(destroyed); + } + + void ObjectTracker::snapshot() { + Event snapshot(name_, category_, EventType::Objectsnapshot); + snapshot.info.id = 10; + profiler_.add_event(snapshot); + } + // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) + // NOLINTEND(readability-magic-numbers) + + void EventCounter::snapshot() { + idx_++; + Event const snapshot(name_, category_, EventType::Counter); + profiler_.add_event(snapshot); + } +} // namespace stream::profiler diff --git a/src/stream/profiler/profiler_event_creator.hxx b/src/stream/profiler/profiler_event_creator.hxx new file mode 100644 index 00000000..f982fca2 --- /dev/null +++ b/src/stream/profiler/profiler_event_creator.hxx @@ -0,0 +1,58 @@ +#pragma once + +#include "all_events.hxx" + +namespace stream::profiler { + class Profiler; + + class ScopeProfile : public DurationEvent { + public: + ScopeProfile(Profiler& profiler, const std::string& name, const std::string& category = "ScopeProfiler") : DurationEvent(name, category), profiler_(profiler) { + start(); + } + + ScopeProfile(Profiler& profiler, std::string&& name, std::string&& category = "ScopeProfiler") : DurationEvent(std::move(name), std::move(category)), profiler_(profiler) { + start(); + } + + ~ScopeProfile() override; + + public: + void terminate(); + + private: + Profiler& profiler_; + }; + + class ObjectTracker { + public: + ObjectTracker(Profiler& profiler, const std::string& name, const std::string& category = "Tracker"); + ObjectTracker(Profiler& profiler, std::string&& name, std::string&& category = "Tracker"); + virtual ~ObjectTracker(); + + public: + void snapshot(); + + private: + Profiler& profiler_; + std::string name_; + std::string category_; + }; + + class EventCounter { + public: + EventCounter(Profiler& profiler, const std::string& name, const std::string& category = "EventCounter") : profiler_(profiler), name_(name), category_(category), idx_(0) {} + + EventCounter(Profiler& profiler, std::string&& name, std::string&& category = "EventCounter") + : profiler_(profiler), name_(std::move(name)), category_(std::move(category)), idx_(0) {} + + public: + void snapshot(); + + private: + Profiler& profiler_; + std::string name_; + std::string category_; + std::uint64_t idx_; + }; +} // namespace stream::profiler diff --git a/src/stream/profiler/profiler_factory.cxx b/src/stream/profiler/profiler_factory.cxx new file mode 100644 index 00000000..d399a726 --- /dev/null +++ b/src/stream/profiler/profiler_factory.cxx @@ -0,0 +1,20 @@ +#include "profiler_factory.hxx" +#include "profiler_json_serializers.hxx" + +#include + +namespace stream::profiler { + void ProfilerFactory::to_json(Profiler& profiler, std::filesystem::path path) { + profiler.profiler_duration.stop(); + profiler.events[0] = profiler.profiler_duration.info; + + if (path == "") { + path = std::string(profiler.name) + ".json"; + } + + std::ofstream file(path.string(), std::ios::out); + json::FormatAsJson const format_profiler(profiler); + fmt::file_print(file, format_profiler); + file.close(); + } +} // namespace stream::profiler diff --git a/src/stream/profiler/profiler_factory.hxx b/src/stream/profiler/profiler_factory.hxx new file mode 100644 index 00000000..b89b63f1 --- /dev/null +++ b/src/stream/profiler/profiler_factory.hxx @@ -0,0 +1,12 @@ +#pragma once + +#include "profiler.hxx" + +#include + +namespace stream::profiler { + class ProfilerFactory { + public: + static void to_json(Profiler& profiler, std::filesystem::path path = ""); + }; +} // namespace stream::profiler diff --git a/src/stream/profiler/profiler_json_serializers.hxx b/src/stream/profiler/profiler_json_serializers.hxx new file mode 100644 index 00000000..8480af8a --- /dev/null +++ b/src/stream/profiler/profiler_json_serializers.hxx @@ -0,0 +1,86 @@ +#pragma once + +#include "profiler_factory.hxx" +#include "stream/json.hxx" + +namespace stream::json { + template <> + struct JsonSerializer { + static inline void format(const profiler::Profiler& t, detail::JsonFormatter& formatter) { + auto intermediate = formatter.get_struct_intermediate(); + intermediate.format("displayTimeUnit", "us"); + intermediate.format("traceEvents", t.events); + } + + static inline void parse(profiler::Profiler& t, detail::JsonParser& parser) { + auto intermediate = parser.get_struct_intermediate(); + intermediate.parse("traceEvents", t.events); + } + }; + + template <> + struct JsonSerializer { + static inline void format(const profiler::EventType& t, detail::JsonFormatter& formatter) { + formatter.format(static_cast(t)); + } + + static inline void parse(profiler::EventType& t, detail::JsonParser& parser) { + parser.parse(reinterpret_cast(t)); + } + }; + + template <> + struct JsonSerializer { + static inline void format(const profiler::EventData& t, detail::JsonFormatter& formatter) { + t.to_json(formatter); + } + + static inline void parse(profiler::EventData& t, detail::JsonParser& parser) { + t.FromJson(parser); + } + }; + + template <> + struct JsonSerializer { + static inline void format(const profiler::EventInfo& t, detail::JsonFormatter& formatter) { + auto intermediate = formatter.get_struct_intermediate(); + intermediate.format("name", t.name); + intermediate.format("cat", t.category); + intermediate.format("ph", t.type); + intermediate.format("pid", t.pid); + intermediate.format("tid", t.tid); + intermediate.format("ts", t.time_of_event.count()); + intermediate.format("dur", t.duration.count()); + intermediate.format("id", t.id); + if (t.data != nullptr) intermediate.format("args", *t.data); + } + + static inline void parse(profiler::EventInfo& t, detail::JsonParser& parser) { + auto intermediate = parser.get_struct_intermediate(); + intermediate.parse("name", t.name); + intermediate.parse("cat", t.category); + intermediate.parse("ph", t.type); + intermediate.parse("pid", t.pid); + intermediate.parse("tid", t.tid); + std::uint64_t time_of_event = 0; + intermediate.parse("ts", time_of_event); + t.time_of_event = std::chrono::microseconds(time_of_event); + std::uint64_t duration = 0; + intermediate.parse("dur", t.duration); + t.duration = std::chrono::microseconds(duration); + intermediate.parse("id", t.id); + intermediate.parse("args", *t.data); + } + }; + + template <> + struct JsonSerializer { + static inline void format(const profiler::Event& t, detail::JsonFormatter& formatter) { + return JsonSerializer::format(t.info, formatter); + } + + static inline void parse(profiler::Event& t, detail::JsonParser& parser) { + return JsonSerializer::parse(t.info, parser); + } + }; +} // namespace stream::json diff --git a/src/stream/profiler/profiler_macros.hxx b/src/stream/profiler/profiler_macros.hxx new file mode 100644 index 00000000..7805dc71 --- /dev/null +++ b/src/stream/profiler/profiler_macros.hxx @@ -0,0 +1,16 @@ +#pragma once + +#ifdef STREAMFORMAT_PROFILING_ENABLE + +#define SFP_PROFILE_FUNCTION() stream::profiler::ScopeProfile profile##__LINE__(stream::profiler::Profiler::get_instance(), __FUNCSIG__, "Function") +#define SFP_PROFILE_FUNCTION_FMT(...) \ + stream::profiler::ScopeProfile profile##__LINE__(stream::profiler::Profiler::get_instance(), stream::profiler::fmt::format_string(__VA_ARGS__), "Function") +#define SFP_SAVE_DEFAULT_PROFILER() stream::profiler::ProfilerFactory::to_json(stream::profiler::Profiler::get_instance()) + +#else // STREAMFORMAT_PROFILING_ENABLE + +#define SFP_PROFILE_FUNCTION() +#define SFP_PROFILE_FUNCTION_FMT(...) +#define SFP_SAVE_DEFAULT_PROFILER() + +#endif // STREAMFORMAT_PROFILING_ENABLE diff --git a/src/stream/tester/copy_move_check.hxx b/src/stream/tester/copy_move_check.hxx new file mode 100644 index 00000000..ae2ec020 --- /dev/null +++ b/src/stream/tester/copy_move_check.hxx @@ -0,0 +1,68 @@ +#pragma once + +#include "stream/flog.hxx" + +namespace stream::tester { + // NOLINTBEGIN + class CopyMoveCheck { + public: + static inline flog::BasicLogger logger; + + public: + explicit CopyMoveCheck(const std::string& name) : name_(name) { + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Default (copy string) Constructor", "TestCopy(const std::string& name)"); + } + + explicit CopyMoveCheck(std::string&& name) : name_(std::move(name)) { + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Default (move string) Constructor", "TestCopy(std::string&& name)"); + } + + CopyMoveCheck(CopyMoveCheck& other) : name_("Copy of " + other.name_) { + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Copy Constructor", "TestCopy(TestCopy&)"); + } + + CopyMoveCheck(const CopyMoveCheck& other) : name_("Copy of " + other.name_) { + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Const Copy Constructor", "TestCopy(const TestCopy&)"); + } + + CopyMoveCheck(CopyMoveCheck&& other) : name_("Move of " + other.name_) { + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Move Constructor", "TestCopy(TestCopy&&)"); + } + + CopyMoveCheck(const CopyMoveCheck&& other) : name_("Move of " + other.name_) { + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Const Move Constructor", "TestCopy(const TestCopy&&)"); + } + + CopyMoveCheck& operator=(CopyMoveCheck& other) { + name_ = "Copy Of " + other.name_; + + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Copy Assignment", "TestCopy& operator=(TestCopy&)"); + return *this; + } + + CopyMoveCheck& operator=(const CopyMoveCheck& other) { + name_ = "Copy Of " + other.name_; + + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Const Copy Assignment", "TestCopy& operator=(const TestCopy&)"); + return *this; + } + + CopyMoveCheck& operator=(CopyMoveCheck&& other) { + name_ = "Move Of " + other.name_; + + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Move Assignment", "TestCopy& operator=(TestCopy&&)"); + return *this; + } + + CopyMoveCheck& operator=(const CopyMoveCheck&& other) { + name_ = "Move Of " + other.name_; + + logger.info("CopyMoveCheck {} : {:C:red} ( {:C:red} )", name_, "Const Move Assignment", "TestCopy& operator=(const TestCopy&&)"); + return *this; + } + + private: + std::string name_; + }; + // NOLINTEND +} // namespace stream::tester diff --git a/src/stream/tester/test_suite/all_test_suite.hxx b/src/stream/tester/test_suite/all_test_suite.hxx new file mode 100644 index 00000000..58627b70 --- /dev/null +++ b/src/stream/tester/test_suite/all_test_suite.hxx @@ -0,0 +1,2 @@ +#include "basic_test.hxx" +#include "test_suite.hxx" diff --git a/src/stream/tester/test_suite/basic_test.hxx b/src/stream/tester/test_suite/basic_test.hxx new file mode 100644 index 00000000..7aeb5020 --- /dev/null +++ b/src/stream/tester/test_suite/basic_test.hxx @@ -0,0 +1,86 @@ +#pragma once + +#include "test_suite.hxx" + +#include "stream/core/prelude.hxx" + +namespace stream::tester::detail { + struct TestFunction : public Test { + public: + using FuncType = std::function; + + public: + TestFunction(std::string_view name, TestSuite& link, FuncType func_, const fmt::detail::FileLocation& location) : Test(name, link, location), func(func_) { + link.tests.insert({std::string{name}, this}); + } + + ~TestFunction() override = default; + + protected: + TestStatus run_impl() override { + func(*this); + return TestStatus::ok; + } + + public: + void test_assert(bool assert, const std::string_view assertView, int line); + template + void test_eq(T result, std::convertible_to auto expected, std::string_view testView, int line); + template + void test_not_eq(T result, std::convertible_to auto notExpected, std::string_view testView, int line); + + template + void assert_optional(std::optional result, std::string_view testView, int line); + + public: + FuncType func; + }; + + template + void TestFunction::test_eq(T result, std::convertible_to auto expected, std::string_view testView, [[maybe_unused]] int line) { + T expected_as_T = static_cast(expected); + if (result != expected_as_T) { + link.test_logger.error("{C:red}{} return {} instead of {}", testView, result, expected, FORMAT_SV("test_name", name)); + throw TestFailure{}; + } + link.test_logger.trace("{C:green}{} return {}", testView, result, FORMAT_SV("test_name", name)); + } + template + void TestFunction::test_not_eq(T result, std::convertible_to auto notExpected, std::string_view testView, [[maybe_unused]] int line) { + if (result == static_cast(notExpected)) { + link.test_logger.error("{C:red}{} return {} but that result was prohibited", testView, result, FORMAT_SV("test_name", name)); + throw TestFailure{}; + } + link.test_logger.trace("{C:green}{} return {}", testView, result, FORMAT_SV("test_name", name)); + } + inline void TestFunction::test_assert(bool assert, std::string_view assertView, [[maybe_unused]] int line) { + if (assert == false) { + link.test_logger.error("{C:red}ASSERT FAILED : {}", assertView, FORMAT_SV("test_name", name)); + throw TestFailure{}; + } + link.test_logger.trace("{C:green}ASSERT SUCCED : {}", assertView, FORMAT_SV("test_name", name)); + } + + template + void TestFunction::assert_optional(std::optional result, std::string_view testView, int line) { + if (result.has_value() == false) { + link.test_logger.error("{C:red}{} didn't return any value", testView, FORMAT_SV("test_name", name)); + throw TestFailure{}; + } + } +} // namespace stream::tester::detail + +#define STREAMFORMAT_TESTINTERNAL_FUNC_DECLARE_EXEC(TestSuiteName, TestName) \ + void STREAMFORMAT_TESTINTERNAL_FUNC_EXEC_NAME(TestSuiteName, TestName)(stream::tester::detail::TestFunction & link); +#define STREAMFORMAT_TESTINTERNAL_FUNC_CREATE(TestSuiteName, TestName, ...) \ + volatile stream::tester::detail::TestFunction STREAMFORMAT_TESTINTERNAL_FUNC_NAME(TestSuiteName, TestName)( \ + #TestName, STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName), STREAMFORMAT_TESTINTERNAL_FUNC_EXEC_NAME(TestSuiteName, TestName), STREAMFORMAT_FMT_FILE_LOCATION()) + +#define SFT_TEST_FUNC(TestSuiteName, TestName) \ + STREAMFORMAT_TESTINTERNAL_FUNC_DECLARE_EXEC(TestSuiteName, TestName) \ + STREAMFORMAT_TESTINTERNAL_FUNC_CREATE(TestSuiteName, TestName); \ + void STREAMFORMAT_TESTINTERNAL_FUNC_EXEC_NAME(TestSuiteName, TestName)(stream::tester::detail::TestFunction & link) + +#define SFT_ASSERT(Test) link.test_assert(Test, #Test, __LINE__) +#define SFT_EQ(Test, Expected) link.test_eq(Test, Expected, #Test, __LINE__) +#define SFT_NEQ(Test, NotExpected) link.test_not_eq(Test, NotExpected, #Test, __LINE__) diff --git a/src/stream/tester/test_suite/test_suite.cxx b/src/stream/tester/test_suite/test_suite.cxx new file mode 100644 index 00000000..a3f39bd2 --- /dev/null +++ b/src/stream/tester/test_suite/test_suite.cxx @@ -0,0 +1,157 @@ +#include "test_suite.hxx" + +#include + +#include "stream/profiler.hxx" + +namespace stream::tester { + bool TestSuitesManager::exec_all_test_suites() { + detail::TestStatusBank status; + + for (auto& [name, test_suite] : test_suites) { + status.add(test_suite->exec_all_tests()); + } + + flog::BasicLogger logger("TestSuite"); + if (status.is_all_ok()) { + logger.info("{C:white}RESULT => {C:+black}{}", status); + } else { + logger.error("{C:white}RESULT => {C:+black}{}", status); + } + + return status.error_status() != 0u; + } +} // namespace stream::tester + +namespace stream::tester::detail { + TestStatusBank TestSuite::exec_all_tests() { + if (parent == nullptr) { + // NOLINTBEGIN(cppcoreguidelines-owning-memory) + profiler = new profiler::Profiler("TestSuite_" + name); + // NOLINTEND(cppcoreguidelines-owning-memory) + } else { + profiler = &get_profiler(); + } + init_logger(); + + logger.info("{C:+black}{}", "BEGIN"); + profiler::DurationEvent test_suite_duration(get_full_name(), "Profile"); + test_suite_duration.start(); + bool first_test_suite = true; + TestStatusBank test_suite_status; + profiler::DurationEvent tests_duration("tests", "Profile"); + tests_duration.start(); + for (auto& [name, test] : tests) { + first_test_suite = false; + profiler::DurationEvent current_test_duration(test->name, "Profile"); + TestStatus test_status = TestStatus::fail; + current_test_duration.start(); + if (TestSuitesManager::performance_test.enable == false) { + test_status = test->run(); + } else { + for (std::uint32_t i = 0; i < TestSuitesManager::performance_test.nb_samples; ++i) { + test_status = test->run(); + if (test_status != TestStatus::ok) { + break; + } + } + } + current_test_duration.stop(); + if (test_status != TestStatus::ok) { + } + test_suite_status.add_test_status(test_status); + logger.debug("{} -> {}", test_status, name); + profiler->add_event(current_test_duration); + } + tests_duration.stop(); + + profiler::DurationEvent groups_duration("Groups", "Profile"); + groups_duration.start(); + for (auto& [name, test_suite] : test_suites_linked) { + if (first_test_suite) { + first_test_suite = false; + } else { + std::cout << std::endl; + } + test_suite_status.add(test_suite->exec_all_tests()); + } + groups_duration.stop(); + test_suite_duration.stop(); + profiler->add_event(tests_duration); + profiler->add_event(groups_duration); + profiler->add_event(test_suite_duration); + + if (test_suite_status.is_all_ok()) { + logger.info("{C:+black}{}", test_suite_status); + } else { + logger.error("{C:+black}{}", test_suite_status); + } + + if (parent == nullptr) { + profiler::ProfilerFactory::to_json(*profiler); + delete profiler; + } + + return test_suite_status; + } + + void TestSuite::init_logger() { + if (TestSuitesManager::verbose == false) { + logger.set_severity(flog::LogSeverity::Debug); + test_logger.set_severity(flog::LogSeverity::Debug); + } else { + logger.set_severity(flog::LogSeverity::Trace); + test_logger.set_severity(flog::LogSeverity::Trace); + } + + std::string time_pattern; + if (TestSuitesManager::print_time) { + time_pattern = "[{logtime:pattern='default'}] "; + } + + if (parent == nullptr) { + logger.set_name(name); + logger.set_real_pattern("{C:+black}" + time_pattern + "{name} >> {color}{data}"); + test_logger.set_name(name + ".{test_name}"); + test_logger.set_real_pattern("{C:+black}" + time_pattern + "{name} >> {color}{data}"); + } else { + std::string const corrected_name = get_corrected_size_name(); + logger.set_name(corrected_name); + logger.set_real_pattern("{C:+black}" + time_pattern + "{name} >> {color}{data}"); + test_logger.set_name(corrected_name + ".{test_name}"); + test_logger.set_real_pattern("{C:+black}" + time_pattern + "{name} >> {color}{data}"); + } + } + + std::string TestSuite::get_full_name() const { + if (parent == nullptr) { + return name; + } + return parent->get_full_name() + "::" + name; + } + + std::string TestSuite::get_corrected_size_name() { + if (parent == nullptr) { + return name; + } + std::size_t biggest_name = 0; + for (auto& [name, test_suite] : parent->test_suites_linked) { + std::size_t const tmp = test_suite->name.size(); + biggest_name = std::max(tmp, biggest_name); + } + std::string res = get_full_name(); + biggest_name -= name.size(); + res.reserve(res.size() + biggest_name); + for (std::uint32_t i = 0; i < biggest_name; ++i) { + res.push_back(' '); + } + return res; + } + + profiler::Profiler& TestSuite::get_profiler() const { + if (parent == nullptr) { + return *profiler; + } + return parent->get_profiler(); + } +} // namespace stream::tester::detail diff --git a/src/stream/tester/test_suite/test_suite.hxx b/src/stream/tester/test_suite/test_suite.hxx new file mode 100644 index 00000000..0145879b --- /dev/null +++ b/src/stream/tester/test_suite/test_suite.hxx @@ -0,0 +1,239 @@ +#pragma once + +#include "stream/flog.hxx" +#include "stream/fmt.hxx" +#include "stream/profiler.hxx" + +#include "stream/fmt/serializers/compilation_data.hxx" + +#include +#include +#include + +namespace stream::tester { + class TestFailure {}; + + enum class TestStatus : int { + ok, + fail, + Crash + }; +} // namespace stream::tester + +namespace stream::tester::detail { + class TestSuite; + class Test { + public: + Test(std::string_view name_, TestSuite& link, const fmt::detail::FileLocation& location) : name(name_), link(link), location(location), last_status(TestStatus::ok) {} + + virtual ~Test() = default; + + protected: + virtual TestStatus run_impl() = 0; + + public: + TestStatus run() { + try { + return last_status = run_impl(); + } catch (const TestFailure&) { + return last_status = TestStatus::fail; + } catch (...) { + return last_status = TestStatus::Crash; + } + } + + public: + std::string name; + TestSuite& link; + fmt::detail::FileLocation location; + TestStatus last_status; + }; + + struct TestStatusBank { + void reset() { + tests_done = 0; + tests_ok = 0; + tests_failed = 0; + tests_crash = 0; + } + + void add_test_status(TestStatus status) { + tests_done++; + switch (status) { + case TestStatus::ok: + tests_ok++; + break; + case TestStatus::fail: + tests_failed++; + break; + case TestStatus::Crash: + tests_crash++; + break; + } + } + + void add(TestStatusBank status) { + tests_done += status.tests_done; + tests_ok += status.tests_ok; + tests_failed += status.tests_failed; + tests_crash += status.tests_crash; + } + + bool is_all_ok() { + return tests_done == tests_ok && tests_crash == 0 && tests_failed == 0; + } + + std::uint32_t error_status() { + return tests_done - tests_ok; + } + + std::uint32_t tests_done = 0; + std::uint32_t tests_ok = 0; + std::uint32_t tests_failed = 0; + std::uint32_t tests_crash = 0; + }; + + class TestSuite; +} // namespace stream::tester::detail +namespace stream::tester { + struct performance_testData { + bool enable = false; + std::uint32_t nb_samples = 10; + }; + + struct ConcurrencySpecificationData { + bool enable = false; + }; + + class TestSuitesManager { + public: + static bool exec_all_test_suites(); + static inline std::unordered_map test_suites; + + public: + static inline bool verbose = false; + static inline bool print_time = false; + static inline performance_testData performance_test = performance_testData{}; + static inline ConcurrencySpecificationData concurrency_specification = ConcurrencySpecificationData{}; + }; +} // namespace stream::tester +namespace stream::tester::detail { + struct TestSuiteData { + bool redirect_stdout = false; + bool redirect_stdin = false; + bool redirect_stderr = false; + }; + + class TestSuite { + public: + TestSuite(std::string_view name_, TestSuiteData extra_ = TestSuiteData{}, TestSuite* parent_ = nullptr) + : name(name_), tests(), extra(extra_), logger(), test_logger(), profiler(nullptr), parent(parent_) { + if (parent == nullptr) + TestSuitesManager::test_suites.insert({name, this}); + else + parent->test_suites_linked.insert({name, this}); + } + + std::string name; + std::unordered_map tests; + std::unordered_map test_suites_linked; + + TestSuiteData extra; + flog::BasicLogger logger; + flog::BasicLogger test_logger; + profiler::Profiler* profiler; + + TestSuite* parent; + + public: + void init_logger(); + + private: + std::string get_full_name() const; + std::string get_corrected_size_name(); + profiler::Profiler& get_profiler() const; + + public: + TestStatusBank exec_all_tests(); + }; +} // namespace stream::tester::detail + +namespace stream::fmt { + template + struct FormatterType { + static void format(const stream::tester::detail::TestSuite& t, FormatterExecutor& executor) { + return executor.ostream.fast_write_sv(t.name); + } + }; + + template + struct FormatterType { + static void format(const stream::tester::detail::Test& t, FormatterExecutor& executor) { + buf::WriteManip(executor.ostream).fast_write_sv(t.link.name); + buf::WriteManip(executor.ostream).fast_write_literal("::"); + buf::WriteManip(executor.ostream).fast_write_sv(t.name); + } + }; + + template + struct FormatterType { + static void format(const stream::tester::TestStatus& status, FormatterExecutor& executor) { + switch (status) { + case stream::tester::TestStatus::ok: + return executor.run("[ {:C:green,^5} ]", "OK"); + case stream::tester::TestStatus::fail: + return executor.run("[ {:C:red,^5} ]", "FAIL"); + case stream::tester::TestStatus::Crash: + return executor.run("[ {:C:magenta,^5} ]", "CRASH"); + } + } + }; + + template + struct FormatterType { + static void format(const stream::tester::detail::TestStatusBank& status_bank, FormatterExecutor& executor) { + buf::WriteManip(executor.ostream).fast_write_literal("tests_done "); + executor.run("{:C:white}", status_bank.tests_done); + + buf::WriteManip(executor.ostream).fast_write_literal(" | testsOK "); + if (status_bank.tests_ok == status_bank.tests_done) { + executor.run("{:C:green}", status_bank.tests_ok); + } else { + executor.run("{:C:yellow}", status_bank.tests_ok); + } + + buf::WriteManip(executor.ostream).fast_write_literal(" | testsFAIL "); + if (status_bank.tests_failed == 0) { + executor.run("{:C:green}", status_bank.tests_failed); + } else { + executor.run("{:C:red}", status_bank.tests_failed); + } + + buf::WriteManip(executor.ostream).fast_write_literal(" | TestCrash "); + if (status_bank.tests_crash == 0) { + executor.run("{:C:green}", status_bank.tests_crash); + } else { + executor.run("{:C:magenta}", status_bank.tests_crash); + } + } + }; +} // namespace stream::fmt + +//-------------------- Base --------------------// +#define STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName) TestSuite_##TestSuiteName +#define STREAMFORMAT_TESTINTERNAL_FUNC_NAME(TestSuiteName, TestName) TestSuite_##TestSuiteName##TestName +#define STREAMFORMAT_TESTINTERNAL_FUNC_EXEC_NAME(TestSuiteName, TestName) TestSuite_##TestSuiteName##TestName##_ExecMethod +#define STREAMFORMAT_TESTINTERNAL_SUITE_EXTRA(...) \ + stream::tester::detail::TestSuiteData { \ + __VA_ARGS__ \ + } + +//-------------------- TestSuite --------------------// +#define SFT_TEST_SUITE(TestSuiteName, ...) \ + stream::tester::detail::TestSuite STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName)(#TestSuiteName, STREAMFORMAT_TESTINTERNAL_SUITE_EXTRA(__VA_ARGS__)) +#define SFT_TEST_GROUP(TestSuiteName, GroupName, ...) \ + stream::tester::detail::TestSuite STREAMFORMAT_TESTINTERNAL_SUITE_NAME(GroupName)(#GroupName, STREAMFORMAT_TESTINTERNAL_SUITE_EXTRA(__VA_ARGS__), \ + &STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName)) + +#define SFT_TEST_SUITE_DECLARATION(TestSuiteName, ...) stream::tester::detail::TestSuite STREAMFORMAT_TESTINTERNAL_SUITE_NAME(TestSuiteName) +#define SFT_TEST_GROUP_DECLARATION(TestSuiteName, GroupName, ...) stream::tester::detail::TestSuite STREAMFORMAT_TESTINTERNAL_SUITE_NAME(GroupName) diff --git a/src/StreamFormat/Tester/TestsMacros.h b/src/stream/tester/tests_macros.hxx similarity index 60% rename from src/StreamFormat/Tester/TestsMacros.h rename to src/stream/tester/tests_macros.hxx index 5c1daa44..38c1da3f 100644 --- a/src/StreamFormat/Tester/TestsMacros.h +++ b/src/stream/tester/tests_macros.hxx @@ -1,28 +1,25 @@ #pragma once -#include "StreamFormat/FLog.h" +#include "stream/flog.hxx" -#define STREAMFORMAT_TEST_TRACE(...) StreamFormat::Test::TestCore::GetLogger().Trace(__VA_ARGS__) -#define STREAMFORMAT_TEST_INFO(...) StreamFormat::Test::TestCore::GetLogger().Info(__VA_ARGS__) -#define STREAMFORMAT_TEST_WARN(...) StreamFormat::Test::TestCore::GetLogger().Warn(__VA_ARGS__) -#define STREAMFORMAT_TEST_ERROR(...) StreamFormat::Test::TestCore::GetLogger().Error(__VA_ARGS__) -#define STREAMFORMAT_TEST_FATAL(...) StreamFormat::Test::TestCore::GetLogger().Fatal(__VA_ARGS__) -#define STREAMFORMAT_TEST_OK(...) StreamFormat::Test::TestCore::GetLogger().Ok(__VA_ARGS__) -#define STREAMFORMAT_TEST_FAIL(...) StreamFormat::Test::TestCore::GetLogger().Fail(__VA_ARGS__) -#define STREAMFORMAT_TEST_BASIC(...) StreamFormat::Test::TestCore::GetLogger().Basic(__VA_ARGS__) +#define STREAMFORMAT_TEST_TRACE(...) stream::Test::TestCore::get_logger().trace(__VA_ARGS__) +#define STREAMFORMAT_TEST_INFO(...) stream::Test::TestCore::get_logger().info(__VA_ARGS__) +#define STREAMFORMAT_TEST_WARN(...) stream::Test::TestCore::get_logger().warn(__VA_ARGS__) +#define STREAMFORMAT_TEST_ERROR(...) stream::Test::TestCore::get_logger().error(__VA_ARGS__) +#define STREAMFORMAT_TEST_FATAL(...) stream::Test::TestCore::get_logger().fatal(__VA_ARGS__) +#define STREAMFORMAT_TEST_OK(...) stream::Test::TestCore::get_logger().ok(__VA_ARGS__) +#define STREAMFORMAT_TEST_FAIL(...) stream::Test::TestCore::get_logger().fail(__VA_ARGS__) +#define STREAMFORMAT_TEST_BASIC(...) stream::Test::TestCore::get_logger().basic(__VA_ARGS__) -namespace StreamFormat::Test -{ - class TestCore - { +namespace stream::test { + class TestCore { public: - static FLog::BasicLogger& GetLogger() - { - static FLog::BasicLogger instance("StreamFormat-Test", "{name} {color} -> {data}"); - return instance; + static flog::BasicLogger& get_logger() { + static flog::BasicLogger g_instance("stream-Test", "{name} {color} -> {data}"); + return g_instance; } }; -} +} // namespace stream::test // Assert log if false #define STREAMFORMAT_TEST_ASSERT(x) \ @@ -30,29 +27,29 @@ namespace StreamFormat::Test // Check if false #define STREAMFORMAT_TEST_TEST(x) \ - if (x) \ + if (x) \ STREAMFORMAT_TEST_OK("TEST OK : {:C:green}", #x); \ - else \ + else \ STREAMFORMAT_TEST_FAIL("TEST FAIL : {:C:red}", #x) // Check if equal with file printed #define STREAMFORMAT_TEST_EQ(x, y) \ - if (x == y) \ + if ((x) == (y)) \ STREAMFORMAT_TEST_OK("{C:green}{} == {}", #x, #y); \ - else \ + else \ STREAMFORMAT_TEST_FAIL("{C:red}{} == {}", #x, #y) // Check if not equal with file printed #define STREAMFORMAT_TEST_NEQ(x, y) \ - if (x != y) \ + if ((x) != (y)) \ STREAMFORMAT_TEST_OK("{C:green}{} != {}", #x, #y); \ - else \ + else \ STREAMFORMAT_TEST_FAIL("{C:red}{} != {}", #x, #y) #define STREAMFORMAT_TEST_FN(fn, resExpected) \ { \ auto res = fn; \ - if (res == resExpected) \ + if (res == (resExpected)) \ STREAMFORMAT_TEST_OK("{C:green}{} return {}", #fn, res); \ else \ STREAMFORMAT_TEST_FAIL("{C:red}{} return {} instead of {}", #fn, res, resExpected); \ @@ -70,11 +67,11 @@ namespace StreamFormat::Test #ifdef STREAMFORMAT_SFTM_ENABLE -#define SFTM_ASSERT(x) STREAMFORMAT_TEST_ASSERT(x) -#define SFTM_TEST(x) STREAMFORMAT_TEST_TEST(x) -#define SFTM_EQ(x, y) STREAMFORMAT_TEST_EQ(x, y) -#define SFTM_NEQ(x, y) STREAMFORMAT_TEST_NEQ(x, y) -#define SFTM_FN(fn, resExpected) STREAMFORMAT_TEST_FN(fn, resExpected) +#define SFTM_ASSERT(x) STREAMFORMAT_TEST_ASSERT(x) +#define SFTM_TEST(x) STREAMFORMAT_TEST_TEST(x) +#define SFTM_EQ(x, y) STREAMFORMAT_TEST_EQ(x, y) +#define SFTM_NEQ(x, y) STREAMFORMAT_TEST_NEQ(x, y) +#define SFTM_FN(fn, resExpected) STREAMFORMAT_TEST_FN(fn, resExpected) #define SFTM_FNFMT(fn, resExpected, ...) STREAMFORMAT_TEST_FNFMT(fn, resExpected, __VA_ARGS__) #endif /* STREAMFORMAT_SFTM_ENABLE */ diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel new file mode 100644 index 00000000..e2fea317 --- /dev/null +++ b/tests/BUILD.bazel @@ -0,0 +1,24 @@ +"" + +load("@rules_cc//cc:defs.bzl", "cc_test") + +cc_test( + name = "units", + srcs = [ "tests.cxx" ] + glob([ "fmt/*.hxx", "fmt/*.cxx" ]), + copts = select({ + "@rules_cc//cc/compiler:msvc-cl": ["/std:c++latest"], + "//conditions:default": [ + "-std=c++20", + "-Wall", "-Wextra", "-Wpedantic", + "-Wshadow", + "-Wconversion", "-Wsign-conversion", + "-Werror=return-type" + ], + }), + deps = [ "//:stream" ], + linkopts = select({ + "@rules_cc//cc/compiler:msvc-cl": [""], + "//conditions:default": ["-pthread"], + }), + visibility = ["//visibility:public"], +) diff --git a/tests/fmt/base_fmt_tests.hxx b/tests/fmt/base_fmt_tests.hxx new file mode 100644 index 00000000..ffeeb494 --- /dev/null +++ b/tests/fmt/base_fmt_tests.hxx @@ -0,0 +1,5 @@ +#pragma once + +#include "stream/tester/test_suite/all_test_suite.hxx" + +inline SFT_TEST_SUITE(FMT); diff --git a/tests/fmt/complex_pattern.cxx b/tests/fmt/complex_pattern.cxx new file mode 100644 index 00000000..d4b27667 --- /dev/null +++ b/tests/fmt/complex_pattern.cxx @@ -0,0 +1,20 @@ +#include "stream/fmt.hxx" +#include "stream/tester/test_suite/all_test_suite.hxx" + +#include "base_fmt_tests.hxx" + +// NOLINTBEGIN(misc-const-correctness) +// NOLINTBEGIN(readability-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) +SFT_TEST_GROUP(FMT, COMPLEX_PATTERN); + +#define TEST_FMT(fmt_test, expected, ...) SFT_EQ(stream::fmt::format_string(fmt_test, __VA_ARGS__), std::string(expected)) + +SFT_TEST_FUNC(COMPLEX_PATTERN, UNESCAPED_ESCAPE_PATTERN) { + TEST_FMT("{0}", "9", 9); + TEST_FMT("{{0}|", "{9|", 9); + TEST_FMT("{{0},", "{9,", 9); +} +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers) +// NOLINTEND(readability-magic-numbers) +// NOLINTEND(misc-const-correctness) diff --git a/tests/fmt/globber.cxx b/tests/fmt/globber.cxx new file mode 100644 index 00000000..50a77d79 --- /dev/null +++ b/tests/fmt/globber.cxx @@ -0,0 +1,73 @@ +#include "base_fmt_tests.hxx" + +#include "stream/fmt/context/parser_executor/utility_functions.hxx" + +#include "stream/fmt/buf/utils/buffer_globber_manip.hxx" + +// NOLINTBEGIN(misc-const-correctness) +// NOLINTBEGIN(readability-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) +SFT_TEST_GROUP(FMT, GLOBBER); +#define TEST_GLOBBER(data, glob) \ + { \ + stream::fmt::buf::StreamView p_buffer(data); \ + stream::fmt::buf::StreamView p_glob(glob); \ + stream::fmt::buf::Globber::buffer_exec_glob(p_buffer, p_glob); \ + SFT_ASSERT(p_buffer.is_end_of_string()); \ + } + +SFT_TEST_FUNC(GLOBBER, BASIC_WILDCARD){TEST_GLOBBER("qwerty", "qwerty") TEST_GLOBBER("qwerty", "q?erty") TEST_GLOBBER("qwerty", "q?????") TEST_GLOBBER("qwerty", "qwer?y") + TEST_GLOBBER("qwerty", "qwert?") TEST_GLOBBER("qwerty", "??????") TEST_GLOBBER("qwerty", "*") TEST_GLOBBER("qwerty", "******") + TEST_GLOBBER("qwerty", "*?**?*")} + +SFT_TEST_GROUP(FMT, PARSE_GLOBBER); +SFT_TEST_FUNC(PARSE_GLOBBER, PG_BASIC_WILDCARD) { + int k = 0; + stream::fmt::parse("|123|", "|{}|", k); + SFT_EQ(k, 123); + + { + // char test[5]; + // stream::fmt::parse("|test|", "|{}|", test); + // SFT_EQ(std::string(test), std::string("test")); + } + + { + // char test[4]; + // stream::fmt::parse("|test|", "|{:no-zero-end}|", test); + // SFT_EQ(std::string(test, 4), std::string("test")); + } + + { + // char test[4]; + // stream::fmt::parse("|test|", "|{}t|", test); + // SFT_EQ(std::string(test), std::string("tes")); + } + + { + // char test[11]; + // stream::fmt::parse("|test123456|", "|{}|", test); + // SFT_EQ(std::string(test), std::string("test123456")); + } + + { + // char test[11]; + // stream::fmt::parse("|test123456|", "|{:glob='*1'}23456|", test); + // SFT_EQ(std::string(test), std::string("test1")); + } + + { + // char test[11]; + // just glob = '????' but compiler are anrgy about trigraph on '??' + // stream::fmt::parse("|test123456|", + // "|{:glob='?" + // "?" + // "?" + // "?'}123456|", + // test); + // SFT_EQ(std::string(test), std::string("test")); + } +} +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers) +// NOLINTEND(readability-magic-numbers) +// NOLINTEND(misc-const-correctness) diff --git a/tests/fmt/index.cxx b/tests/fmt/index.cxx new file mode 100644 index 00000000..479a8a44 --- /dev/null +++ b/tests/fmt/index.cxx @@ -0,0 +1,18 @@ +#include "stream/fmt.hxx" +#include "stream/tester/test_suite/all_test_suite.hxx" + +#include "base_fmt_tests.hxx" + +// NOLINTBEGIN(misc-const-correctness) +// NOLINTBEGIN(readability-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) +/* +SFT_TEST_GROUP(FMT, INDEX); + +SFT_TEST_FUNC(INDEX, ReIndexing) +{ +} +*/ +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers) +// NOLINTEND(readability-magic-numbers) +// NOLINTEND(misc-const-correctness) diff --git a/tests/fmt/limits.cxx b/tests/fmt/limits.cxx new file mode 100644 index 00000000..661420a4 --- /dev/null +++ b/tests/fmt/limits.cxx @@ -0,0 +1,129 @@ +#include "stream/fmt.hxx" +#include "stream/tester/test_suite/all_test_suite.hxx" + +#include "base_fmt_tests.hxx" + +// NOLINTBEGIN(misc-const-correctness) +// NOLINTBEGIN(readability-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays) +// NOLINTBEGIN(hicpp-avoid-c-arrays) +// NOLINTBEGIN(modernize-avoid-c-arrays) +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-pro-bounds-constant-array-index) + +// NOLINTBEGIN(cppcoreguidelines-pro-bounds-array-to-pointer-decay) +// NOLINTBEGIN(hicpp-no-array-decay) + +SFT_TEST_GROUP(FMT, LIMITS); + +#define SFT_TEST_FUNC_LowBufferSize(k) \ + SFT_TEST_FUNC(LIMITS, LowBufferSize##k) { \ + char buffer[k] = {0}; \ + stream::fmt::format_in_char(buffer, "0123456789"); \ + for (int i = 0; i < (k); ++i) \ + SFT_EQ(buffer[i] - '0', i); \ + } + +SFT_TEST_FUNC_LowBufferSize(10); +SFT_TEST_FUNC_LowBufferSize(9); +SFT_TEST_FUNC_LowBufferSize(8); +SFT_TEST_FUNC_LowBufferSize(7); +SFT_TEST_FUNC_LowBufferSize(6); +SFT_TEST_FUNC_LowBufferSize(5); +SFT_TEST_FUNC_LowBufferSize(4); +SFT_TEST_FUNC_LowBufferSize(3); +SFT_TEST_FUNC_LowBufferSize(2); +SFT_TEST_FUNC_LowBufferSize(1); + +SFT_TEST_FUNC(LIMITS, PlainLowBufferSize10) { + char buffer[10] = {0}; + stream::fmt::format_in_char(buffer, "0123456789"); + for (int i = 0; i < 10; ++i) { + SFT_EQ(buffer[i] - '0', i); + } +} + +SFT_TEST_FUNC(LIMITS, PlainLowBufferSize1) { + char buffer[1] = {0}; + stream::fmt::format_in_char(buffer, "0"); + for (int i = 0; i < 1; ++i) { + SFT_EQ(buffer[i] - '0', i); + } +} + +#define SFT_TEST_FUNC_LowBufferSizeArray(k) \ + SFT_TEST_FUNC(LIMITS, LowBufferSizeArray##k) { \ + char buffer[k] = {0}; \ + const char fmt_buffer[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; \ + stream::fmt::buf::StreamView format(fmt_buffer, k); \ + stream::fmt::buf::GivenStreamIOManager manager(buffer, k); \ + stream::fmt::detail::format_in_manager(manager, false, format); \ + for (int i = 0; i < (k); ++i) \ + SFT_EQ(buffer[i] - '0', i); \ + } + +SFT_TEST_FUNC_LowBufferSizeArray(10); +SFT_TEST_FUNC_LowBufferSizeArray(9); +SFT_TEST_FUNC_LowBufferSizeArray(8); +SFT_TEST_FUNC_LowBufferSizeArray(7); +SFT_TEST_FUNC_LowBufferSizeArray(6); +SFT_TEST_FUNC_LowBufferSizeArray(5); +SFT_TEST_FUNC_LowBufferSizeArray(4); +SFT_TEST_FUNC_LowBufferSizeArray(3); +SFT_TEST_FUNC_LowBufferSizeArray(2); +SFT_TEST_FUNC_LowBufferSizeArray(1); + +SFT_TEST_FUNC(LIMITS, PlainLowBufferSizeArray10) { + char buffer[10] = {0}; + const char fmt_buffer[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + stream::fmt::buf::StreamView const fmt(fmt_buffer, 10); + stream::fmt::buf::GivenStreamIOManager manager(buffer, 10); + stream::fmt::detail::format_in_manager(manager, false, fmt); + for (int i = 0; i < 10; ++i) { + SFT_EQ(buffer[i] - '0', i); + } +} + +SFT_TEST_FUNC(LIMITS, PlainLowBufferSizeArray1) { + char buffer[1] = {0}; + const char fmt_buffer[] = {'0'}; + stream::fmt::buf::StreamView const fmt(fmt_buffer, 1); + stream::fmt::buf::GivenStreamIOManager manager(buffer, 1); + stream::fmt::detail::format_in_manager(manager, false, fmt); + for (int i = 0; i < 1; ++i) { + SFT_EQ(buffer[i] - '0', i); + } +} + +SFT_TEST_FUNC(LIMITS, LowBufferSizeArray10FMT30) { + char buffer[10] = {0}; + const char fmt_buffer[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', + '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + stream::fmt::buf::StreamView const fmt(fmt_buffer, 30); + stream::fmt::buf::GivenStreamIOManager manager(buffer, 10); + stream::fmt::detail::format_in_manager(manager, false, fmt); + for (int k = 0; k < 10; ++k) { + SFT_EQ(buffer[k] - '0', k); + } +} + +SFT_TEST_FUNC(LIMITS, LowBufferSizeArray5Number9) { + char buffer[10] = {0}; + stream::fmt::buf::StreamView const fmt("{}"); + stream::fmt::buf::GivenStreamIOManager manager(buffer, 10); + std::uint64_t i = 9'876'543'210; + stream::fmt::detail::format_in_manager(manager, false, fmt, i); + for (int k = 0; k < 10; ++k) { + SFT_EQ(buffer[k] - '0', 9 - k); + } +} +// NOLINTEND(hicpp-no-array-decay) +// NOLINTEND(cppcoreguidelines-pro-bounds-array-to-pointer-decay) + +// NOLINTEND(cppcoreguidelines-pro-bounds-constant-array-index) +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers) +// NOLINTEND(modernize-avoid-c-arrays) +// NOLINTEND(hicpp-avoid-c-arrays) +// NOLINTEND(cppcoreguidelines-avoid-c-arrays) +// NOLINTEND(readability-magic-numbers) +// NOLINTEND(misc-const-correctness) diff --git a/Tests/FMT/Shift.cpp b/tests/fmt/shift.cxx similarity index 87% rename from Tests/FMT/Shift.cpp rename to tests/fmt/shift.cxx index 8193347a..eaaae73a 100644 --- a/Tests/FMT/Shift.cpp +++ b/tests/fmt/shift.cxx @@ -1,30 +1,30 @@ -#include "StreamFormat/FMT.h" -#include "StreamFormat/Tester/TestSuite/AllTestSuite.h" +#include "stream/fmt.hxx" +#include "stream/tester/test_suite/all_test_suite.hxx" -#include "BaseFMTTests.h" +#include "base_fmt_tests.hxx" -PCT_TEST_GROUP(FMT, SHIFT); +// NOLINTBEGIN(misc-const-correctness) +// NOLINTBEGIN(readability-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) +SFT_TEST_GROUP(FMT, SHIFT); -#define TEST_FMT(fmt_test, expected, ...) PCT_EQ(StreamFormat::FMT::FormatString(fmt_test, __VA_ARGS__), expected) +#define TEST_FMT(fmt_test, expected, ...) SFT_EQ(stream::fmt::format_string(fmt_test, __VA_ARGS__), expected) -PCT_TEST_GROUP(SHIFT, NUMBER_SHIFT); -PCT_TEST_GROUP(NUMBER_SHIFT, ONE_DIGIT); -PCT_TEST_FUNC(ONE_DIGIT, Right) -{ +SFT_TEST_GROUP(SHIFT, NUMBER_SHIFT); +SFT_TEST_GROUP(NUMBER_SHIFT, ONE_DIGIT); +SFT_TEST_FUNC(ONE_DIGIT, Right) { TEST_FMT("|{:>9 }|", "| 7|", 7); TEST_FMT("|{:>9: }|", "| 7|", 7); TEST_FMT("|{:>9:0}|", "|000000007|", 7); TEST_FMT("|{:>9:*}|", "|********7|", 7); } -PCT_TEST_FUNC(ONE_DIGIT, Left) -{ +SFT_TEST_FUNC(ONE_DIGIT, Left) { TEST_FMT("|{:<9 }|", "|7 |", 7); TEST_FMT("|{:<9: }|", "|7 |", 7); TEST_FMT("|{:<9:0}|", "|7 |", 7); TEST_FMT("|{:<9:*}|", "|7********|", 7); } -PCT_TEST_FUNC(ONE_DIGIT, Center) -{ +SFT_TEST_FUNC(ONE_DIGIT, Center) { TEST_FMT("|{:^10 }|", "| 7 |", 7); TEST_FMT("|{:^10:-|-}|", "|-----7----|", 7); TEST_FMT("|{:^10:*|*}|", "|*****7****|", 7); @@ -36,8 +36,7 @@ PCT_TEST_FUNC(ONE_DIGIT, Center) TEST_FMT("|{:^11:<|>}|", "|<<<<<7>>>>>|", 7); TEST_FMT("|{:^11:>|<}|", "|>>>>>7<<<<<|", 7); } -PCT_TEST_FUNC(ONE_DIGIT, CenterRight) -{ +SFT_TEST_FUNC(ONE_DIGIT, CenterRight) { TEST_FMT("|{:^>10:-|-}|", "|-----7----|", 7); TEST_FMT("|{:^>10:*|*}|", "|*****7****|", 7); TEST_FMT("|{:^>10:<|>}|", "|<<<<<7>>>>|", 7); @@ -48,8 +47,7 @@ PCT_TEST_FUNC(ONE_DIGIT, CenterRight) TEST_FMT("|{:^>11:<|>}|", "|<<<<<7>>>>>|", 7); TEST_FMT("|{:^>11:>|<}|", "|>>>>>7<<<<<|", 7); } -PCT_TEST_FUNC(ONE_DIGIT, CenterLeft) -{ +SFT_TEST_FUNC(ONE_DIGIT, CenterLeft) { TEST_FMT("|{:^<10:-|-}|", "|----7-----|", 7); TEST_FMT("|{:^<10:*|*}|", "|****7*****|", 7); TEST_FMT("|{:^<10:<|>}|", "|<<<<7>>>>>|", 7); @@ -61,23 +59,20 @@ PCT_TEST_FUNC(ONE_DIGIT, CenterLeft) TEST_FMT("|{:^<11:>|<}|", "|>>>>>7<<<<<|", 7); } -PCT_TEST_GROUP(NUMBER_SHIFT, TWO_DIGIT); -PCT_TEST_FUNC(TWO_DIGIT, Right) -{ +SFT_TEST_GROUP(NUMBER_SHIFT, TWO_DIGIT); +SFT_TEST_FUNC(TWO_DIGIT, Right) { TEST_FMT("|{:>10 }|", "| 14|", 14); TEST_FMT("|{:>10: }|", "| 14|", 14); TEST_FMT("|{:>10:0}|", "|0000000014|", 14); TEST_FMT("|{:>10:*}|", "|********14|", 14); } -PCT_TEST_FUNC(TWO_DIGIT, Left) -{ +SFT_TEST_FUNC(TWO_DIGIT, Left) { TEST_FMT("|{:<10 }|", "|14 |", 14); TEST_FMT("|{:<10: }|", "|14 |", 14); TEST_FMT("|{:<10:0}|", "|14 |", 14); TEST_FMT("|{:<10:*}|", "|14********|", 14); } -PCT_TEST_FUNC(TWO_DIGIT, Center) -{ +SFT_TEST_FUNC(TWO_DIGIT, Center) { TEST_FMT("|{:^10 }|", "| 14 |", 14); TEST_FMT("|{:^10:-|-}|", "|----14----|", 14); TEST_FMT("|{:^10:*|*}|", "|****14****|", 14); @@ -89,8 +84,7 @@ PCT_TEST_FUNC(TWO_DIGIT, Center) TEST_FMT("|{:^11:<|>}|", "|<<<<<14>>>>|", 14); TEST_FMT("|{:^11:>|<}|", "|>>>>>14<<<<|", 14); } -PCT_TEST_FUNC(TWO_DIGIT, CenterRight) -{ +SFT_TEST_FUNC(TWO_DIGIT, CenterRight) { TEST_FMT("|{:^>10:-|-}|", "|----14----|", 14); TEST_FMT("|{:^>10:*|*}|", "|****14****|", 14); TEST_FMT("|{:^>10:<|>}|", "|<<<<14>>>>|", 14); @@ -101,8 +95,7 @@ PCT_TEST_FUNC(TWO_DIGIT, CenterRight) TEST_FMT("|{:^>11:<|>}|", "|<<<<<14>>>>|", 14); TEST_FMT("|{:^>11:>|<}|", "|>>>>>14<<<<|", 14); } -PCT_TEST_FUNC(TWO_DIGIT, CenterLeft) -{ +SFT_TEST_FUNC(TWO_DIGIT, CenterLeft) { TEST_FMT("|{:^<10:-|-}|", "|----14----|", 14); TEST_FMT("|{:^<10:*|*}|", "|****14****|", 14); TEST_FMT("|{:^<10:<|>}|", "|<<<<14>>>>|", 14); @@ -114,23 +107,20 @@ PCT_TEST_FUNC(TWO_DIGIT, CenterLeft) TEST_FMT("|{:^<11:>|<}|", "|>>>>14<<<<<|", 14); } -PCT_TEST_GROUP(NUMBER_SHIFT, THREE_DIGIT); -PCT_TEST_FUNC(THREE_DIGIT, Right) -{ +SFT_TEST_GROUP(NUMBER_SHIFT, THREE_DIGIT); +SFT_TEST_FUNC(THREE_DIGIT, Right) { TEST_FMT("|{:>11 }|", "| 105|", 105); TEST_FMT("|{:>11: }|", "| 105|", 105); TEST_FMT("|{:>11:0}|", "|00000000105|", 105); TEST_FMT("|{:>11:*}|", "|********105|", 105); } -PCT_TEST_FUNC(THREE_DIGIT, Left) -{ +SFT_TEST_FUNC(THREE_DIGIT, Left) { TEST_FMT("|{:<11 }|", "|105 |", 105); TEST_FMT("|{:<11: }|", "|105 |", 105); TEST_FMT("|{:<11:0}|", "|105 |", 105); TEST_FMT("|{:<11:*}|", "|105********|", 105); } -PCT_TEST_FUNC(THREE_DIGIT, Center) -{ +SFT_TEST_FUNC(THREE_DIGIT, Center) { TEST_FMT("|{:^10 }|", "| 105 |", 105); TEST_FMT("|{:^10:-|-}|", "|----105---|", 105); TEST_FMT("|{:^10:*|*}|", "|****105***|", 105); @@ -142,8 +132,7 @@ PCT_TEST_FUNC(THREE_DIGIT, Center) TEST_FMT("|{:^11:<|>}|", "|<<<<105>>>>|", 105); TEST_FMT("|{:^11:>|<}|", "|>>>>105<<<<|", 105); } -PCT_TEST_FUNC(THREE_DIGIT, CenterRight) -{ +SFT_TEST_FUNC(THREE_DIGIT, CenterRight) { TEST_FMT("|{:^>10:-|-}|", "|----105---|", 105); TEST_FMT("|{:^>10:*|*}|", "|****105***|", 105); TEST_FMT("|{:^>10:<|>}|", "|<<<<105>>>|", 105); @@ -154,8 +143,7 @@ PCT_TEST_FUNC(THREE_DIGIT, CenterRight) TEST_FMT("|{:^>11:<|>}|", "|<<<<105>>>>|", 105); TEST_FMT("|{:^>11:>|<}|", "|>>>>105<<<<|", 105); } -PCT_TEST_FUNC(THREE_DIGIT, CenterLeft) -{ +SFT_TEST_FUNC(THREE_DIGIT, CenterLeft) { TEST_FMT("|{:^<10:-|-}|", "|---105----|", 105); TEST_FMT("|{:^<10:*|*}|", "|***105****|", 105); TEST_FMT("|{:^<10:<|>}|", "|<<<105>>>>|", 105); @@ -167,24 +155,21 @@ PCT_TEST_FUNC(THREE_DIGIT, CenterLeft) TEST_FMT("|{:^<11:>|<}|", "|>>>>105<<<<|", 105); } -PCT_TEST_GROUP(SHIFT, STRING_SHIFT); -PCT_TEST_GROUP(STRING_SHIFT, ARRAY); -PCT_TEST_FUNC(ARRAY, Right) -{ +SFT_TEST_GROUP(SHIFT, STRING_SHIFT); +SFT_TEST_GROUP(STRING_SHIFT, ARRAY); +SFT_TEST_FUNC(ARRAY, Right) { TEST_FMT("|{:>10 }|", "| test|", "test"); TEST_FMT("|{:>10: }|", "| test|", "test"); TEST_FMT("|{:>10:0}|", "|000000test|", "test"); TEST_FMT("|{:>10:*}|", "|******test|", "test"); } -PCT_TEST_FUNC(ARRAY, Left) -{ +SFT_TEST_FUNC(ARRAY, Left) { TEST_FMT("|{:<10 }|", "|test |", "test"); TEST_FMT("|{:<10: }|", "|test |", "test"); TEST_FMT("|{:<10:0}|", "|test000000|", "test"); TEST_FMT("|{:<10:*}|", "|test******|", "test"); } -PCT_TEST_FUNC(ARRAY, Center) -{ +SFT_TEST_FUNC(ARRAY, Center) { TEST_FMT("|{:^10 }|", "| test |", "test"); TEST_FMT("|{:^10:-|-}|", "|---test---|", "test"); TEST_FMT("|{:^10:*|*}|", "|***test***|", "test"); @@ -196,8 +181,7 @@ PCT_TEST_FUNC(ARRAY, Center) TEST_FMT("|{:^11:<|>}|", "|<<<>>|", "test"); TEST_FMT("|{:^11:>|<}|", "|>>>>test<<<|", "test"); } -PCT_TEST_FUNC(ARRAY, CenterRight) -{ +SFT_TEST_FUNC(ARRAY, CenterRight) { TEST_FMT("|{:^>10:-|-}|", "|---test---|", "test"); TEST_FMT("|{:^>10:*|*}|", "|***test***|", "test"); TEST_FMT("|{:^>10:<|>}|", "|<<>>|", "test"); @@ -208,8 +192,7 @@ PCT_TEST_FUNC(ARRAY, CenterRight) TEST_FMT("|{:^>11:<|>}|", "|<<<>>|", "test"); TEST_FMT("|{:^>11:>|<}|", "|>>>>test<<<|", "test"); } -PCT_TEST_FUNC(ARRAY, CenterLeft) -{ +SFT_TEST_FUNC(ARRAY, CenterLeft) { TEST_FMT("|{:^<10:-|-}|", "|---test---|", "test"); TEST_FMT("|{:^<10:*|*}|", "|***test***|", "test"); TEST_FMT("|{:^<10:<|>}|", "|<<>>|", "test"); @@ -221,9 +204,8 @@ PCT_TEST_FUNC(ARRAY, CenterLeft) TEST_FMT("|{:^<11:>|<}|", "|>>>test<<<<|", "test"); } -PCT_TEST_GROUP(STRING_SHIFT, POINTER); -PCT_TEST_FUNC(POINTER, Right) -{ +SFT_TEST_GROUP(STRING_SHIFT, POINTER); +SFT_TEST_FUNC(POINTER, Right) { const char* test = "test"; TEST_FMT("|{:>10 }|", "| test|", test); TEST_FMT("|{:>10: }|", "| test|", test); @@ -236,8 +218,7 @@ PCT_TEST_FUNC(POINTER, Right) TEST_FMT("|{:>10:0, size=4}|", "|000000test|", test_with_size); TEST_FMT("|{:>10:*, size=4}|", "|******test|", test_with_size); } -PCT_TEST_FUNC(POINTER, Left) -{ +SFT_TEST_FUNC(POINTER, Left) { const char* test = "test"; TEST_FMT("|{:<10 }|", "|test |", test); TEST_FMT("|{:<10: }|", "|test |", test); @@ -250,8 +231,7 @@ PCT_TEST_FUNC(POINTER, Left) TEST_FMT("|{:<10:0, size=4}|", "|test000000|", test_with_size); TEST_FMT("|{:<10:*, size=4}|", "|test******|", test_with_size); } -PCT_TEST_FUNC(POINTER, Center) -{ +SFT_TEST_FUNC(POINTER, Center) { const char* test = "test"; TEST_FMT("|{:^10 }|", "| test |", test); TEST_FMT("|{:^10:-|-}|", "|---test---|", test); @@ -276,8 +256,7 @@ PCT_TEST_FUNC(POINTER, Center) TEST_FMT("|{:^11:<|>, size=4}|", "|<<<>>|", test_with_size); TEST_FMT("|{:^11:>|<, size=4}|", "|>>>>test<<<|", test_with_size); } -PCT_TEST_FUNC(POINTER, CenterRight) -{ +SFT_TEST_FUNC(POINTER, CenterRight) { const char* test = "test"; TEST_FMT("|{:^>10:-|-}|", "|---test---|", test); TEST_FMT("|{:^>10:*|*}|", "|***test***|", test); @@ -300,8 +279,7 @@ PCT_TEST_FUNC(POINTER, CenterRight) TEST_FMT("|{:^>11:<|>, size=4}|", "|<<<>>|", test_with_size); TEST_FMT("|{:^>11:>|<, size=4}|", "|>>>>test<<<|", test_with_size); } -PCT_TEST_FUNC(POINTER, CenterLeft) -{ +SFT_TEST_FUNC(POINTER, CenterLeft) { const char* test = "test"; TEST_FMT("|{:^<10:-|-}|", "|---test---|", test); TEST_FMT("|{:^<10:*|*}|", "|***test***|", test); @@ -324,3 +302,6 @@ PCT_TEST_FUNC(POINTER, CenterLeft) TEST_FMT("|{:^<11:<|>, size=4}|", "|<<>>>|", test_with_size); TEST_FMT("|{:^<11:>|<, size=4}|", "|>>>test<<<<|", test_with_size); } +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers) +// NOLINTEND(readability-magic-numbers) +// NOLINTEND(misc-const-correctness) diff --git a/tests/fmt/specifier.cxx b/tests/fmt/specifier.cxx new file mode 100644 index 00000000..daa3ccdc --- /dev/null +++ b/tests/fmt/specifier.cxx @@ -0,0 +1,60 @@ +#include "stream/fmt.hxx" +#include "stream/tester/test_suite/all_test_suite.hxx" + +#include "base_fmt_tests.hxx" + +// NOLINTBEGIN(misc-const-correctness) +// NOLINTBEGIN(readability-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays) +// NOLINTBEGIN(hicpp-avoid-c-arrays) +// NOLINTBEGIN(modernize-avoid-c-arrays) +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-pro-bounds-constant-array-index) +SFT_TEST_GROUP(FMT, SPECIFIER); + +#define TEST_FMT_ARRAY_SPECIFIERS(fmt_test, test_data, expected) SFT_EQ(stream::fmt::format_string(fmt_test, test_data), expected) + +SFT_TEST_FUNC(SPECIFIER, BEGIN_END) { + int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + TEST_FMT_ARRAY_SPECIFIERS("{}", data, "{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }"); + + TEST_FMT_ARRAY_SPECIFIERS("{:begin=6}", data, "{ 6, 7, 8, 9 }"); + TEST_FMT_ARRAY_SPECIFIERS("{:size=5}", data, "{ 0, 1, 2, 3, 4 }"); + TEST_FMT_ARRAY_SPECIFIERS("{:begin=3, size=5}", data, "{ 3, 4, 5, 6, 7 }"); + + TEST_FMT_ARRAY_SPECIFIERS("{:begin='{', begin=3, size=5}", data, "{3, 4, 5, 6, 7 }"); + TEST_FMT_ARRAY_SPECIFIERS("{:end='}', begin=3, size=5}", data, "{ 3, 4, 5, 6, 7}"); + TEST_FMT_ARRAY_SPECIFIERS("{:begin='{', end='}', begin=3, size=5}", data, "{3, 4, 5, 6, 7}"); + TEST_FMT_ARRAY_SPECIFIERS("{:begin='[', end='}', begin=3, size=5}", data, "[3, 4, 5, 6, 7}"); + TEST_FMT_ARRAY_SPECIFIERS("{:begin='[', end=']', begin=3, size=5}", data, "[3, 4, 5, 6, 7]"); + + TEST_FMT_ARRAY_SPECIFIERS("{:join=' ', begin='[', end=']', begin=3, size=5}", data, "[3 4 5 6 7]"); + + TEST_FMT_ARRAY_SPECIFIERS("{:join=' | ', begin='[', end=']', begin=3, size=5}", data, "[3 | 4 | 5 | 6 | 7]"); +} + +SFT_TEST_FUNC(SPECIFIER, BEGIN_END_NESTED_SPECS) { + int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + TEST_FMT_ARRAY_SPECIFIERS("{::#x}", data, "{ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9 }"); + + TEST_FMT_ARRAY_SPECIFIERS("{:begin=6, :#x}", data, "{ 0x6, 0x7, 0x8, 0x9 }"); + TEST_FMT_ARRAY_SPECIFIERS("{:size=5, :#x}", data, "{ 0x0, 0x1, 0x2, 0x3, 0x4 }"); + TEST_FMT_ARRAY_SPECIFIERS("{:begin=3, size=5, :#x}", data, "{ 0x3, 0x4, 0x5, 0x6, 0x7 }"); + + TEST_FMT_ARRAY_SPECIFIERS("{:begin='{', begin=3, size=5, :#x}", data, "{0x3, 0x4, 0x5, 0x6, 0x7 }"); + TEST_FMT_ARRAY_SPECIFIERS("{:end='}', begin=3, size=5, :#x}", data, "{ 0x3, 0x4, 0x5, 0x6, 0x7}"); + TEST_FMT_ARRAY_SPECIFIERS("{:begin='{', end='}', begin=3, size=5, :#x}", data, "{0x3, 0x4, 0x5, 0x6, 0x7}"); + TEST_FMT_ARRAY_SPECIFIERS("{:begin='[', end='}', begin=3, size=5, :#x}", data, "[0x3, 0x4, 0x5, 0x6, 0x7}"); + TEST_FMT_ARRAY_SPECIFIERS("{:begin='[', end=']', begin=3, size=5, :#x}", data, "[0x3, 0x4, 0x5, 0x6, 0x7]"); + + TEST_FMT_ARRAY_SPECIFIERS("{:join=' ', begin='[', end=']', begin=3, size=5, :#x}", data, "[0x3 0x4 0x5 0x6 0x7]"); + + TEST_FMT_ARRAY_SPECIFIERS("{:join=' | ', begin='[', end=']', begin=3, size=5, :#x}", data, "[0x3 | 0x4 | 0x5 | 0x6 | 0x7]"); +} +// NOLINTEND(cppcoreguidelines-pro-bounds-constant-array-index) +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers) +// NOLINTEND(modernize-avoid-c-arrays) +// NOLINTEND(hicpp-avoid-c-arrays) +// NOLINTEND(cppcoreguidelines-avoid-c-arrays) +// NOLINTEND(readability-magic-numbers) +// NOLINTEND(misc-const-correctness) diff --git a/Tests/FMT/TextProperties.cpp b/tests/fmt/text_properties.cxx similarity index 63% rename from Tests/FMT/TextProperties.cpp rename to tests/fmt/text_properties.cxx index ba9351f2..51d76167 100644 --- a/Tests/FMT/TextProperties.cpp +++ b/tests/fmt/text_properties.cxx @@ -1,39 +1,39 @@ -#include "StreamFormat/FMT.h" -#include "StreamFormat/Tester/TestSuite/AllTestSuite.h" +#include "stream/fmt.hxx" +#include "stream/tester/test_suite/all_test_suite.hxx" -#include "BaseFMTTests.h" +#include "base_fmt_tests.hxx" -PCT_TEST_GROUP(FMT, TEXT_PROPERTIES); +// NOLINTBEGIN(misc-const-correctness) +// NOLINTBEGIN(readability-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) +SFT_TEST_GROUP(FMT, TEXT_PROPERTIES); -#define TEST_FMT(fmt_test, expected) PCT_EQ(Escaper(StreamFormat::FMT::FormatString(fmt_test, 0)), Escaper(expected)) +#define TEST_FMT(fmt_test, expected) SFT_EQ(escaper(stream::fmt::format_string(fmt_test, 0)), escaper(expected)) -static std::string Escaper(const std::string& str) -{ - std::string res; - for (char c : str) - { - if (c != '\033') - { - res.push_back(c); - continue; - } +namespace { + std::string escaper(const std::string& str) { + std::string res; + for (char const c : str) { + if (c != '\033') { + res.push_back(c); + continue; + } - res.push_back('\\'); - res.push_back('e'); + res.push_back('\\'); + res.push_back('e'); + } + return res; } - return res; -} +} // namespace -PCT_TEST_GROUP(TEXT_PROPERTIES, ESCAPER_VALIDATING); -#define TEST_ESCAPER(str, str_res) PCT_EQ(Escaper(str), str_res) -PCT_TEST_FUNC(ESCAPER_VALIDATING, BasicTest) -{ +SFT_TEST_GROUP(TEXT_PROPERTIES, ESCAPER_VALIDATING); +#define TEST_ESCAPER(str, str_res) SFT_EQ(escaper(str), str_res) +SFT_TEST_FUNC(ESCAPER_VALIDATING, BasicTest) { TEST_ESCAPER("\033", "\\e"); TEST_ESCAPER("\033k", "\\ek"); } -PCT_TEST_FUNC(TEXT_PROPERTIES, BasicColor) -{ +SFT_TEST_FUNC(TEXT_PROPERTIES, basic_color) { TEST_FMT("123", "123"); TEST_FMT("{C:black} 123 ", "\033[30m 123 \033[39m"); @@ -55,8 +55,7 @@ PCT_TEST_FUNC(TEXT_PROPERTIES, BasicColor) TEST_FMT("{C:+white} 123 ", "\033[97m 123 \033[39m"); } -PCT_TEST_FUNC(TEXT_PROPERTIES, DoubleBasicColor) -{ +SFT_TEST_FUNC(TEXT_PROPERTIES, DoubleBasicColor) { TEST_FMT("123", "123"); TEST_FMT("{C:black} 1 {C:white} 23 ", "\033[30m 1 \033[37m 23 \033[39m"); @@ -78,21 +77,21 @@ PCT_TEST_FUNC(TEXT_PROPERTIES, DoubleBasicColor) TEST_FMT("{C:+white} 1 {C:+cyan} 23 ", "\033[97m 1 \033[96m 23 \033[39m"); } -class TEST_FMT_ContextOut -{ -}; -STREAMFORMAT_AUTO_FORMATTER_T(TEST_FMT_ContextOut, "{C:red} TEST_FMT_ContextOut {} ", 0); +class TestFmtContextOut {}; +STREAMFORMAT_AUTO_FORMATTER_T(TestFmtContextOut, "{C:red} TEST_FMT_ContextOut {} ", 0); -#define TEST_FMT_CONTEXT(fmt_test, expected) PCT_EQ(Escaper(StreamFormat::FMT::FormatString(fmt_test, TEST_FMT_ContextOut{})), Escaper(expected)) +#define TEST_FMT_CONTEXT(fmt_test, expected) SFT_EQ(escaper(stream::fmt::format_string(fmt_test, TestFmtContextOut{})), escaper(expected)) -PCT_TEST_FUNC(TEXT_PROPERTIES, ContextOut) -{ +SFT_TEST_FUNC(TEXT_PROPERTIES, ContextOut) { TEST_FMT_CONTEXT("{}", "\033[31m TEST_FMT_ContextOut 0 \033[39m"); TEST_FMT_CONTEXT("{} 123 ", "\033[31m TEST_FMT_ContextOut 0 \033[39m 123 "); - // TODO : check before doing a Detail::TextPropertiesExecution, should only have one \033[31m + // TODO(sacha): check before doing a detail::TextPropertiesExecution, should only have one \033[31m TEST_FMT_CONTEXT("{C:red}{} 123 ", "\033[31m TEST_FMT_ContextOut 0 123 \033[39m"); TEST_FMT_CONTEXT("{C:+red}{} 123 ", "\033[91m\033[31m TEST_FMT_ContextOut 0 \033[91m 123 \033[39m"); } +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers) +// NOLINTEND(readability-magic-numbers) +// NOLINTEND(misc-const-correctness) diff --git a/tests/tests.cxx b/tests/tests.cxx new file mode 100644 index 00000000..70bb2135 --- /dev/null +++ b/tests/tests.cxx @@ -0,0 +1,8 @@ + +#include "stream/tester/test_suite/all_test_suite.hxx" +#include "stream/default_logger.hxx" + +int main() { + stream::tester::TestSuitesManager::verbose = false; + return static_cast(stream::tester::TestSuitesManager::exec_all_test_suites()); +}