Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new codegen output api #53

Merged
merged 5 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions ecsact/codegen/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
Expand Down Expand Up @@ -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();

/**
Expand Down
62 changes: 57 additions & 5 deletions ecsact/codegen/plugin.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,62 @@
#include <cstring>
#include <iterator>
#include <format>
#include <span>
#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<int32_t>(std::size(filenames));
}
}

/**
* Helper type to give a more C++ friendly write function
* @example
Expand All @@ -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;
Expand All @@ -42,29 +94,29 @@ 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);
}
}

void write_(const char* str_data, int32_t str_data_len) {
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<int32_t>(str.size()));
write_fn(filename_index, str.data(), static_cast<int32_t>(str.size()));
}
}
}
Expand Down
22 changes: 12 additions & 10 deletions ecsact_codegen_plugin_validate/plugin_validate.cc
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#include "ecsact/codegen/plugin_validate.hh"

#include <unordered_set>
#include <string_view>
#include <boost/dll/shared_library.hpp>
#include <boost/dll/library_info.hpp>
#include "ecsact/runtime/meta.h"
#include "ecsact/runtime/dylib.h"

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) {
Expand Down Expand Up @@ -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;
}

Expand Down