diff --git a/ecsact/codegen/plugin.h b/ecsact/codegen/plugin.h index 2c63891..372e70c 100644 --- a/ecsact/codegen/plugin.h +++ b/ecsact/codegen/plugin.h @@ -28,10 +28,15 @@ * @NOTE: it is _NOT_ assumed that @p str is null-terminated, you must set * @p str_len properly. * + * @param filename_index - index from output filenames from @ref + * ecsact_codegen_output_filenames. If @ref ecsact_codegen_output_filenames is + * not defined by the plugin then this parameter must be 0, otherwise it is + * an error to give a filename index >= to the output filenames length. * @param str - array of characters of length @p str_len * @param str_len - length of array of characters @p str */ typedef void (*ecsact_codegen_write_fn_t)( // + int32_t filename_index, const char* str, int32_t str_len ); @@ -73,11 +78,27 @@ typedef enum ecsact_codegen_report_type { * @param msg_len - length of array of characters @p msg */ typedef void (*ecsact_codegen_report_fn_t)( // + int32_t filename_index, ecsact_codegen_report_type report_type, const char* msg, int32_t msg_len ); +/** + * @param package_id the package + * @param out_filenames filenames to write to. if `nullptr` this parameter is + * should be ignored. May only write to a max of @p max_filenames. + * @param out_filenames_length Must write the length of filenames this plugin + * writes to + */ +ECSACT_CODEGEN_PLUGIN_API void ecsact_codegen_output_filenames( // + ecsact_package_id package_id, + char* const* out_filenames, + int32_t max_filenames, + int32_t max_filename_length, + int32_t* out_filenames_length +); + ECSACT_CODEGEN_PLUGIN_API const char* ecsact_codegen_plugin_name(); /** diff --git a/ecsact/codegen/plugin.hh b/ecsact/codegen/plugin.hh index 1597794..00a6c1f 100644 --- a/ecsact/codegen/plugin.hh +++ b/ecsact/codegen/plugin.hh @@ -7,11 +7,62 @@ #include #include #include +#include #include "ecsact/runtime/common.h" #include "ecsact/codegen/plugin.h" namespace ecsact { +/** + * Helper function to implement the pesky ecsact_codegen_output_filenames C API. + * @example + * ```cpp + * auto ecsact_codegen_output_filenames( // + * ecsact_package_id package_id, + * char* const* out_filenames, + * int32_t max_filenames, + * int32_t max_filename_length, + * int32_t* out_filenames_length + * ) -> void { + * auto package_filename = + * ecsact::meta::package_file_path(package_id).filename(); + * + * // Generate a .h and .cpp file for each package + * ecsact::set_codegen_plugin_output_filenames( + * { + * package_filename.string() + ".h", + * package_filename.string() + ".cpp", + * }, + * out_filenames, + * max_filenames, + * max_filename_length, + * out_filenames_length + * ); + * } + * ``` + */ +inline auto set_codegen_plugin_output_filenames( + const auto& filenames, + char* const* out_filenames, + int32_t max_filenames, + int32_t max_filename_length, + int32_t* out_filenames_length +) -> void { + if(out_filenames != nullptr) { + for(auto i = 0; max_filenames > i; ++i) { + if(i >= std::size(filenames)) { + break; + } + auto filename = std::data(filenames) + i; + strcpy_s(out_filenames[i], max_filename_length, filename->c_str()); + } + } + + if(out_filenames_length != nullptr) { + *out_filenames_length = static_cast(std::size(filenames)); + } +} + /** * Helper type to give a more C++ friendly write function * @example @@ -28,6 +79,7 @@ namespace ecsact { */ struct codegen_plugin_context { const ecsact_package_id package_id; + const int32_t filename_index; const ecsact_codegen_write_fn_t write_fn; const ecsact_codegen_report_fn_t report_fn; int indentation = 0; @@ -42,7 +94,7 @@ struct codegen_plugin_context { int32_t str_data_len ) { if(report_fn != nullptr) { - report_fn(report_type, str_data, str_data_len); + report_fn(filename_index, report_type, str_data, str_data_len); } } @@ -50,21 +102,21 @@ struct codegen_plugin_context { assert(indentation >= 0); if(indentation <= 0) { - write_fn(str_data, str_data_len); + write_fn(filename_index, str_data, str_data_len); } else { std::string_view str(str_data, str_data_len); auto indent_str = get_indent_str(); auto nl_idx = str.find('\n'); while(nl_idx != std::string_view::npos) { - write_fn(str.data(), nl_idx + 1); - write_fn(indent_str.data(), indent_str.size()); + write_fn(filename_index, str.data(), nl_idx + 1); + write_fn(filename_index, indent_str.data(), indent_str.size()); str = std::string_view(str.data() + nl_idx + 1, str.size() - nl_idx - 1); nl_idx = str.find('\n'); } if(!str.empty()) { - write_fn(str.data(), static_cast(str.size())); + write_fn(filename_index, str.data(), static_cast(str.size())); } } } diff --git a/ecsact_codegen_plugin_validate/plugin_validate.cc b/ecsact_codegen_plugin_validate/plugin_validate.cc index 171972b..aad066a 100644 --- a/ecsact_codegen_plugin_validate/plugin_validate.cc +++ b/ecsact_codegen_plugin_validate/plugin_validate.cc @@ -1,5 +1,7 @@ #include "ecsact/codegen/plugin_validate.hh" +#include +#include #include #include #include "ecsact/runtime/meta.h" @@ -7,6 +9,7 @@ namespace fs = std::filesystem; namespace dll = boost::dll; +using namespace std::string_view_literals; using ecsact::codegen::plugin_validate_result; plugin_validate_result ecsact::codegen::plugin_validate(fs::path plugin_path) { @@ -81,17 +84,16 @@ plugin_validate_result ecsact::codegen::plugin_validate(fs::path plugin_path) { } } + const auto valid_symbols = std::unordered_set{ + "ecsact_codegen_output_filenames"sv, + "ecsact_codegen_plugin"sv, + "ecsact_codegen_plugin_name"sv, + "ecsact_dylib_has_fn"sv, + "ecsact_dylib_set_fn_addr"sv, + }; + for(auto symbol : symbols) { - if(symbol == "ecsact_codegen_plugin") { - continue; - } - if(symbol == "ecsact_codegen_plugin_name") { - continue; - } - if(symbol == "ecsact_dylib_set_fn_addr") { - continue; - } - if(symbol == "ecsact_dylib_has_fn") { + if(valid_symbols.contains(symbol)) { continue; }