diff --git a/cmake/string_catalog.cmake b/cmake/string_catalog.cmake index 09db54bc..3dc27ac7 100644 --- a/cmake/string_catalog.cmake +++ b/cmake/string_catalog.cmake @@ -2,7 +2,7 @@ function(gen_str_catalog) set(options "") set(oneValueArgs OUTPUT_CPP OUTPUT_XML OUTPUT_JSON GEN_STR_CATALOG OUTPUT_LIB) - set(multiValueArgs INPUT_JSON INPUT_LIBS) + set(multiValueArgs INPUT_JSON INPUT_LIBS INPUT_HEADERS) cmake_parse_arguments(SC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -19,13 +19,15 @@ function(gen_str_catalog) endforeach() list(TRANSFORM SC_INPUT_JSON PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") + list(TRANSFORM SC_INPUT_HEADERS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") add_custom_command( OUTPUT ${SC_OUTPUT_CPP} ${SC_OUTPUT_JSON} ${SC_OUTPUT_XML} COMMAND ${Python3_EXECUTABLE} ${SC_GEN_STR_CATALOG} --input ${UNDEFS} - --json_input ${SC_INPUT_JSON} --cpp_output ${SC_OUTPUT_CPP} - --json_output ${SC_OUTPUT_JSON} --xml_output ${SC_OUTPUT_XML} + --json_input ${SC_INPUT_JSON} --cpp_headers ${SC_INPUT_HEADERS} + --cpp_output ${SC_OUTPUT_CPP} --json_output ${SC_OUTPUT_JSON} + --xml_output ${SC_OUTPUT_XML} DEPENDS ${UNDEFS} ${INPUT_JSON} ${SC_GEN_STR_CATALOG}) add_library(${SC_OUTPUT_LIB} STATIC ${SC_OUTPUT_CPP}) diff --git a/include/sc/format.hpp b/include/sc/format.hpp index 19b1d46a..c4c4c085 100644 --- a/include/sc/format.hpp +++ b/include/sc/format.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -22,10 +23,12 @@ namespace sc { namespace detail { template -concept compile_time_field = requires { T::value; }; +concept compile_time_field = + std::same_as>; template [[nodiscard]] CONSTEVAL auto field_value(T) { - if constexpr (std::is_enum_v) { + if constexpr (std::is_enum_v) { return stdx::enum_as_string(); } else { return T::value; diff --git a/include/sc/string_constant.hpp b/include/sc/string_constant.hpp index e0a5a0e2..17c32729 100644 --- a/include/sc/string_constant.hpp +++ b/include/sc/string_constant.hpp @@ -10,16 +10,17 @@ namespace sc { template struct string_constant { + using value_type = std::basic_string_view; + private: - using view_t = std::basic_string_view; constexpr static std::array storage{chars...}; using size_type = int; - using const_iterator = typename view_t::const_iterator; + using const_iterator = typename value_type::const_iterator; constexpr static size_type npos = std::numeric_limits::max(); public: - constexpr static view_t value{storage.data(), sizeof...(chars)}; + constexpr static value_type value{storage.data(), sizeof...(chars)}; constexpr static auto begin() noexcept { return std::cbegin(storage); } constexpr static auto end() noexcept { return std::cend(storage); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8558d8d0..17b2b49c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -94,7 +94,9 @@ gen_str_catalog( catalog1_lib catalog2_lib INPUT_JSON - log/catalog_extra.json) + log/catalog_extra.json + INPUT_HEADERS + log/catalog_enums.hpp) add_unit_test( log_catalog_test diff --git a/test/log/catalog2_lib.cpp b/test/log/catalog2_lib.cpp index 63081e98..e35114ca 100644 --- a/test/log/catalog2_lib.cpp +++ b/test/log/catalog2_lib.cpp @@ -1,4 +1,5 @@ #include "catalog_concurrency.hpp" +#include "catalog_enums.hpp" #include #include @@ -16,9 +17,16 @@ struct test_log_args_destination { } // namespace auto log_two_rt_args() -> void; +auto log_rt_enum_arg() -> void; auto log_two_rt_args() -> void { auto cfg = logging::mipi::config{test_log_args_destination{}}; cfg.logger.log_msg( format("D string with {} and {} placeholder"_sc, 1, 2)); } + +auto log_rt_enum_arg() -> void { + auto cfg = logging::mipi::config{test_log_args_destination{}}; + cfg.logger.log_msg( + format("E string with {} placeholder"_sc, E::value)); +} diff --git a/test/log/catalog_app.cpp b/test/log/catalog_app.cpp index 9a7e453b..3fadb826 100644 --- a/test/log/catalog_app.cpp +++ b/test/log/catalog_app.cpp @@ -10,6 +10,8 @@ extern int log_calls; extern auto log_zero_args() -> void; extern auto log_one_ct_arg() -> void; extern auto log_one_rt_arg() -> void; +extern auto log_two_rt_args() -> void; +extern auto log_rt_enum_arg() -> void; TEST_CASE("log zero arguments", "[catalog]") { test_critical_section::count = 0; @@ -34,3 +36,19 @@ TEST_CASE("log one runtime argument", "[catalog]") { CHECK(test_critical_section::count == 2); CHECK(log_calls == 1); } + +TEST_CASE("log two runtime arguments", "[catalog]") { + log_calls = 0; + test_critical_section::count = 0; + log_two_rt_args(); + CHECK(test_critical_section::count == 2); + CHECK(log_calls == 1); +} + +TEST_CASE("log runtime enum argument", "[catalog]") { + log_calls = 0; + test_critical_section::count = 0; + log_rt_enum_arg(); + CHECK(test_critical_section::count == 2); + CHECK(log_calls == 1); +} diff --git a/test/log/catalog_enums.hpp b/test/log/catalog_enums.hpp new file mode 100644 index 00000000..152892d7 --- /dev/null +++ b/test/log/catalog_enums.hpp @@ -0,0 +1,3 @@ +#pragma once + +enum struct E { value = 42 }; diff --git a/tools/gen_str_catalog.py b/tools/gen_str_catalog.py index 72fd3aa5..fc8af98f 100755 --- a/tools/gen_str_catalog.py +++ b/tools/gen_str_catalog.py @@ -111,9 +111,10 @@ def make_cpp_defn(types, msg): }}""" -def write_cpp(messages, filename): +def write_cpp(messages, extra_headers, filename): with open(filename, "w") as f: - f.write("#include \n\n") + f.write("\n".join(f'#include "{h}"' for h in extra_headers)) + f.write("\n#include \n\n") cpp_defns = (make_cpp_defn(k, v) for k, v in messages.items()) f.write("\n".join(cpp_defns)) @@ -200,6 +201,13 @@ def parse_cmdline(): default=[], help="Extra JSON inputs to copy into the output.", ) + parser.add_argument( + "--cpp_headers", + type=str, + nargs="*", + default=[], + help="Extra C++ headers to include in the C++ output.", + ) parser.add_argument( "--client_name", type=str, @@ -235,7 +243,7 @@ def main(): raise Exception(f"{str(e)} from file {args.input}") if args.cpp_output: - write_cpp(messages, args.cpp_output) + write_cpp(messages, args.cpp_headers, args.cpp_output) if args.json_output: write_json(messages, args.json_input, args.json_output)