Skip to content

Commit

Permalink
feat: new codegen output api (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
zaucy authored Aug 9, 2024
1 parent 9ec86f0 commit 1f671ac
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 15 deletions.
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

0 comments on commit 1f671ac

Please sign in to comment.