diff --git a/.github/release-please-manifest.json b/.github/release-please-manifest.json index 8249311..38dc7f3 100644 --- a/.github/release-please-manifest.json +++ b/.github/release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.1.3" + ".": "2.1.4" } diff --git a/.github/workflows/cmake-multiple-platform.yml b/.github/workflows/cmake-multiple-platform.yml index 746304e..9b993da 100644 --- a/.github/workflows/cmake-multiple-platform.yml +++ b/.github/workflows/cmake-multiple-platform.yml @@ -133,6 +133,8 @@ jobs: mkdir -p build/output/bin cp build/*${{ env.PROJECT_NAME }}.* build/output/bin/ cp build/${{ env.PROJECT_NAME }}.pmodule build/output/ + # Cleanup dev files + find build/output -type f \( -name "*.exp" -o -name "*.ilk" -o -name "*.lib" -o -name "*.pdb" \) -delete - name: Upload artifacts uses: actions/upload-artifact@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 21a54f7..309ca05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.1.4](https://github.com/untrustedmodders/plugify-module-cpp/compare/v2.1.3...v2.1.4) (2025-10-06) + + +### Bug Fixes + +* added drop-down list to `converter` & fix "f-string: single '}'" & added PAUSE tag to .bat ([9757312](https://github.com/untrustedmodders/plugify-module-cpp/commit/9757312f9118d16e371518b6e17c711ef4d62f8d)) +* disable asan in debug ([eb7a09c](https://github.com/untrustedmodders/plugify-module-cpp/commit/eb7a09cb3308822f10162e314fe9b3cf616ff4d3)) +* improve san and debug symbols on windows ([c5fe825](https://github.com/untrustedmodders/plugify-module-cpp/commit/c5fe82565d2e106cedb9bb68d97df4a78fe42153)) +* update external/plugify ([7c9407a](https://github.com/untrustedmodders/plugify-module-cpp/commit/7c9407aa883e9ef246760b1ddddf2f1cf32ed26b)) +* update plugify ([6f0327c](https://github.com/untrustedmodders/plugify-module-cpp/commit/6f0327ca5764c0ce149caa2b3b59188195f45985)) +* update plugify ([7f521f1](https://github.com/untrustedmodders/plugify-module-cpp/commit/7f521f1511df515d75cf638b695f9a90996bf39e)) +* update plugify ([1b12f46](https://github.com/untrustedmodders/plugify-module-cpp/commit/1b12f469619711602b588897467a7457aa3b9ec1)) +* update tests ([cb9a674](https://github.com/untrustedmodders/plugify-module-cpp/commit/cb9a67469933f23255401da355a4f1e6a24ce3f9)) + ## [2.1.3](https://github.com/untrustedmodders/plugify-module-cpp/compare/v2.1.2...v2.1.3) (2025-09-27) diff --git a/CMakeLists.txt b/CMakeLists.txt index 74ebec3..97e38c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,7 @@ if(LINUX) set(PLUGIFY_USE_STATIC_STDLIB ON CACHE INTERNAL "") set(PLUGIFY_USE_ABI0 OFF CACHE INTERNAL "") endif() -set(PLUGIFY_USE_SANITIZER ON CACHE INTERNAL "") +set(PLUGIFY_USE_SANITIZER OFF CACHE INTERNAL "") add_subdirectory(external/plugify) # @@ -66,6 +66,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE ${CPPLM_LINK_LIBRARIES}) if(MSVC) target_compile_options(${PROJECT_NAME} PRIVATE /W4 /WX /Zc:preprocessor $<$:/Zi>) + target_link_options(${PROJECT_NAME} PRIVATE $<$:/DEBUG /OPT:REF /OPT:ICF>) else() target_compile_options(${PROJECT_NAME} PRIVATE -Wextra -Wshadow -Wconversion -Wpedantic -Werror $<$:-g1>) endif() @@ -76,9 +77,14 @@ elseif(UNIX) target_link_options(${PROJECT_NAME} PRIVATE "-Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/sym/version_script.lds") endif() -if(PLUGIFY_HAS_SANITIZER) - target_compile_options(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>) - target_link_libraries(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>) +if(PLUGIFY_USE_SANITIZER) + if(MSVC) + target_compile_options(${PROJECT_NAME} PRIVATE $<$: /fsanitize=address>) + target_compile_definitions(${PROJECT_NAME} PRIVATE $<$: _DISABLE_VECTOR_ANNOTATION>) + else() + target_compile_options(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fsanitize=leak -fsanitize=undefined>) + target_link_libraries(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fsanitize=leak -fsanitize=undefined>) + endif() endif() include(GenerateExportHeader) diff --git a/external/plugify b/external/plugify index 48e6e0a..df3298e 160000 --- a/external/plugify +++ b/external/plugify @@ -1 +1 @@ -Subproject commit 48e6e0ac974c2a44dffcfc327bc71871c5fae0c9 +Subproject commit df3298ef363adec30bb621004cebd4f0ebd9ee19 diff --git a/generator/converter.py b/generator/converter.py new file mode 100644 index 0000000..9352c97 --- /dev/null +++ b/generator/converter.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python3 +""" +Convert JSON manifest to README markdown table format +""" + +import json +import sys +from typing import Dict, List, Any + + +def format_type(param_type: str, is_ref: bool = False) -> str: + """Format a parameter type for display in signature""" + # Add reference indicator if needed + if is_ref: + return f"{param_type}&" + return param_type + + +def format_signature(method: Dict[str, Any]) -> str: + """Format method signature from JSON data""" + func_name = method.get('funcName', method.get('name', 'Unknown')) + + # Format parameters + params = [] + for param in method.get('paramTypes', []): + param_name = param.get('name', '') + param_type = param.get('type', 'any') + is_ref = param.get('ref', False) + + formatted_type = format_type(param_type, is_ref) + params.append(f"{param_name}: {formatted_type}") + + # Format return type + ret_type = method.get('retType', {}) + return_type = ret_type.get('type', 'void') + + # Construct signature + signature = f"{func_name}({', '.join(params)}): {return_type}" + + return signature + + +def escape_pipe(text: str) -> str: + """Escape pipe characters in text for markdown tables""" + return text.replace('|', '\\|') + + +def generate_markdown_table(methods: List[Dict[str, Any]], group_by: bool = False) -> str: + """Generate markdown table from methods list""" + lines = [] + + if group_by: + # Group methods by their 'group' field + grouped = {} + for method in methods: + group = method.get('group', 'Other') + if group not in grouped: + grouped[group] = [] + grouped[group].append(method) + + # Generate table for each group + for group_name in sorted(grouped.keys()): + lines.append(f"\n### {group_name}\n") + lines.append(f"
Open methods list \n") + lines.append("| Function | Signature | Description |") + lines.append("|----------|-----------|-------------|") + + for method in grouped[group_name]: + name = method.get('name', 'Unknown') + signature = format_signature(method) + description = method.get('description', '') + + # Escape pipe characters + name = escape_pipe(name) + signature = escape_pipe(signature) + description = escape_pipe(description) + + lines.append(f"| {name} | `{signature}` | {description} |") + + lines.append("\n
\n") + else: + # Single table for all methods + lines.append(f"
Open methods list \n") + lines.append("| Function | Signature | Description |") + lines.append("|----------|-----------|-------------|") + + for method in methods: + name = method.get('name', 'Unknown') + signature = format_signature(method) + description = method.get('description', '') + + # Escape pipe characters + name = escape_pipe(name) + signature = escape_pipe(signature) + description = escape_pipe(description) + + lines.append(f"| {name} | `{signature}` | {description} |") + + lines.append("\n
\n") + return '\n'.join(lines) + + +def main(): + """Main function to convert JSON to README table""" + + # Check command line arguments + if len(sys.argv) < 2: + print("Usage: python json_to_readme.py [output.md]") + print("\nOptions:") + print(" --group Group methods by their 'group' field") + sys.exit(1) + + input_file = sys.argv[1] + output_file = None + group_by = False + + # Parse arguments + for i, arg in enumerate(sys.argv[2:], 2): + if arg == '--group': + group_by = True + else: + output_file = arg + + # If no output file specified, use input filename with .md extension + if not output_file: + output_file = input_file.rsplit('.', 1)[0] + '_methods.md' + + try: + # Read JSON file + with open(input_file, 'r', encoding='utf-8') as f: + data = json.load(f) + + # Extract methods + methods = data.get('methods', []) + + if not methods: + print("Warning: No methods found in JSON file") + sys.exit(1) + + # Generate markdown table + markdown_content = f"# API Methods\n\n" + markdown_content += f"Generated from: {input_file}\n\n" + markdown_content += f"Total methods: {len(methods)}\n\n" + markdown_content += generate_markdown_table(methods, group_by) + + # Write to output file + with open(output_file, 'w', encoding='utf-8') as f: + f.write(markdown_content) + + print(f"Successfully converted {len(methods)} methods") + print(f"Output written to: {output_file}") + + # Print summary of groups if available + groups = set(m.get('group', 'Other') for m in methods) + if len(groups) > 1: + print(f"Found {len(groups)} groups: {', '.join(sorted(groups))}") + print("Tip: Use --group flag to group methods in the output") + + except FileNotFoundError: + print(f"Error: File '{input_file}' not found") + sys.exit(1) + except json.JSONDecodeError as e: + print(f"Error: Invalid JSON in file '{input_file}': {e}") + sys.exit(1) + except Exception as e: + print(f"Error: {e}") + sys.exit(1) + + +# Alternative function for direct string conversion (can be imported and used in other scripts) +def json_string_to_markdown_table(json_string: str, group_by: bool = False) -> str: + """Convert JSON string directly to markdown table string""" + try: + data = json.loads(json_string) + methods = data.get('methods', []) + + if not methods: + return "No methods found in JSON" + + return generate_markdown_table(methods, group_by) + except json.JSONDecodeError as e: + return f"Error parsing JSON: {e}" + except Exception as e: + return f"Error: {e}" + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/generator/generator.py b/generator/generator.py index 1a52c4c..c60a995 100644 --- a/generator/generator.py +++ b/generator/generator.py @@ -329,7 +329,7 @@ def gen_param(index: int, param: dict) -> str: return generate_name(param.get('name', f'p{index}')) case ParamGen.TypesNames: if param.get('default'): - return f'{type_name} {generate_name(param.get("name", f"p{index}"))} = {param["default"]}}' + return f'{type_name} {generate_name(param.get("name", f"p{index}"))} = {param["default"]}' return f'{type_name} {generate_name(param.get("name", f"p{index}"))}' case _: return '' diff --git a/generator/run_generator.bat b/generator/run_generator.bat index dfc3b75..35325f9 100644 --- a/generator/run_generator.bat +++ b/generator/run_generator.bat @@ -47,3 +47,4 @@ for %%F in (%*) do ( ) echo All files processed successfully. +PAUSE diff --git a/test/cross_call_master/CMakeLists.txt b/test/cross_call_master/CMakeLists.txt index 2bce098..729339a 100644 --- a/test/cross_call_master/CMakeLists.txt +++ b/test/cross_call_master/CMakeLists.txt @@ -44,8 +44,8 @@ endif() if(LINUX) target_compile_definitions(${PROJECT_NAME} PRIVATE _GLIBCXX_USE_CXX11_ABI=1) target_link_libraries(${PROJECT_NAME} PRIVATE -static-libstdc++ -static-libgcc) - #target_compile_options(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>) - #target_link_libraries(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>) + #target_compile_options(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fsanitize=leak -fsanitize=undefined>) + #target_link_libraries(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fsanitize=leak -fsanitize=undefined>) endif() include(GenerateExportHeader) diff --git a/test/cross_call_master/plugin.cpp b/test/cross_call_master/plugin.cpp index 3f14eee..fb53fc6 100644 --- a/test/cross_call_master/plugin.cpp +++ b/test/cross_call_master/plugin.cpp @@ -1322,7 +1322,7 @@ class CrossCallMaster final : public plg::IPluginEntry { _tests.Add("ParamRefArrays", [](SimpleTests::Test &test) { const auto boolArrayExpected = plg::vector{true}; const auto char8ArrayExpected = plg::vector{'a', 'b', 'c'}; - const auto char16ArrayExpected = plg::vector{'d', 'e', 'f'}; + const auto char16ArrayExpected = plg::vector{u'd', u'e', u'f'}; const auto sbyteArrayExpected = plg::vector{-3, -2, -1, 0, 1, 2, 3}; const auto shortArrayExpected = plg::vector{-4, -3, -2, -1, 0, 1, 2, 3, 4}; const auto intArrayExpected = plg::vector{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; @@ -1339,7 +1339,7 @@ class CrossCallMaster final : public plg::IPluginEntry { const auto stringArrayExpected = plg::vector{"1", "12", "123", "1234", "12345", "123456"}; plg::vector boolArray{true, false, true}; plg::vector char8Array{'A', 'B', 'C'}; - plg::vector char16Array{'D', 'E', 'F'}; + plg::vector char16Array{u'D', u'E', u'F'}; plg::vector sbyteArray{-1, -2, -3}; plg::vector shortArray{10, 20, 30}; plg::vector intArray{100, 200, 300}; @@ -1824,7 +1824,7 @@ class CrossCallMaster final : public plg::IPluginEntry { int16_t i16 = 30; // Changed to random int16_t bool b = false; // Changed to random bool plg::vec4 vec4{4.5f, 5.6f, 6.7f, 7.8f}; // Changed to random values - plg::vector vecC16{'D', 'E'}; // Changed to random chars + plg::vector vecC16{u'D', u'E'}; // Changed to random chars char16_t ch16 = L'B'; // Changed to random character int32_t i32 = 50; // Changed to random int32_t const plg::mat4x4 expected = MockFunc8(vec3, vecU32, i16, b, vec4, vecC16, ch16, i32); @@ -1944,7 +1944,7 @@ class CrossCallMaster final : public plg::IPluginEntry { plg::vector vecU32{5, 6, 7}; // Changed to random values bool b = false; // Changed to random bool float f = 3.14f; // Changed to random float - plg::vector vecC16{'D', 'E'}; // Changed to random chars + plg::vector vecC16{u'D', u'E'}; // Changed to random chars uint8_t u8 = 6; // Changed to random uint8_t int32_t i32 = 25; // Changed to random int32_t plg::vec2 vec2{5.6f, 7.8f}; // Changed to random values @@ -4409,7 +4409,7 @@ PLUGIN_API plg::mat4x4 CallFunc8Callback(cross_call_worker::Func8 func) { int16_t i16 = 10; bool b = true; plg::vec4 vec4{1.0f, 2.0f, 3.0f, 4.0f}; - plg::vector vecC16{'A', 'B'}; + plg::vector vecC16{u'A', u'B'}; char16_t ch16 = L'A'; int32_t i32 = 20; return func(vec3, vecU32, i16, b, vec4, vecC16, ch16, i32); @@ -4533,7 +4533,7 @@ PLUGIN_API int16_t CallFunc15Callback(cross_call_worker::Func15 func) { plg::vector vecU32{1, 2, 3}; bool b = true; float f = 1.23f; - plg::vector vecC16{'A', 'B'}; + plg::vector vecC16{u'A', u'B'}; uint8_t u8 = 5; int32_t i32 = 20; plg::vec2 vec2{1.0f, 2.0f}; diff --git a/test/cross_call_worker/CMakeLists.txt b/test/cross_call_worker/CMakeLists.txt index 0433929..0f8cc59 100644 --- a/test/cross_call_worker/CMakeLists.txt +++ b/test/cross_call_worker/CMakeLists.txt @@ -44,8 +44,8 @@ endif() if(LINUX) target_compile_definitions(${PROJECT_NAME} PRIVATE _GLIBCXX_USE_CXX11_ABI=1) target_link_libraries(${PROJECT_NAME} PRIVATE -static-libstdc++ -static-libgcc) - #target_compile_options(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>) - #target_link_libraries(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>) + #target_compile_options(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fsanitize=leak -fsanitize=undefined>) + #target_link_libraries(${PROJECT_NAME} PRIVATE $<$: -fsanitize=address -fsanitize=leak -fsanitize=undefined>) endif() target_compile_definitions(${PROJECT_NAME} PRIVATE diff --git a/version.txt b/version.txt index ac2cdeb..7d2ed7c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.1.3 +2.1.4