From d8e1a6e79077c7ae63d7d1b5241e0dd8dd9dd3ff Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Thu, 8 May 2025 17:12:34 -0400 Subject: [PATCH 01/25] Renamed function generateFile() to generateOutputFile(). --- src/bin2cpp/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index 4678988..28dea6b 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -138,7 +138,7 @@ struct ARGUMENTS }; //pre-declarations -bool generateFile(const Context & c, const std::string & output_file_path, bin2cpp::IGenerator * generator); +bool generateOutputFile(const Context & c, const std::string & output_file_path, bin2cpp::IGenerator * generator); APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * generator); APP_ERROR_CODES processInputDirectory(const Context & c, bin2cpp::IGenerator * generator); APP_ERROR_CODES processManagerFiles(const Context & c); @@ -600,11 +600,11 @@ APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * genera } //process files - bool headerResult = generateFile(c, outputHeaderPath, generator); + bool headerResult = generateOutputFile(c, outputHeaderPath, generator); if (!headerResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; - bool cppResult = generateFile(c, outputCppPath, generator); + bool cppResult = generateOutputFile(c, outputCppPath, generator); if (!cppResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; @@ -745,7 +745,7 @@ FILE_UPDATE_MODE getFileUpdateMode(const std::string & input_file_path, const st return UPDATING; } -bool generateFile(const Context & c, const std::string & output_file_path, bin2cpp::IGenerator * generator) +bool generateOutputFile(const Context & c, const std::string & output_file_path, bin2cpp::IGenerator * generator) { FILE_UPDATE_MODE mode = getFileUpdateMode(c.inputFilePath, output_file_path, c.overrideExistingFiles); @@ -799,11 +799,11 @@ APP_ERROR_CODES processManagerFiles(const Context & c) generator.setContext(c); //process files - bool headerResult = generateFile(c, outputHeaderPath, &generator); + bool headerResult = generateOutputFile(c, outputHeaderPath, &generator); if (!headerResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; - bool cppResult = generateFile(c, outputCppPath, &generator); + bool cppResult = generateOutputFile(c, outputCppPath, &generator); if (!cppResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; From a8a5fa2deda502ea249908ccd949858d9c6eb044 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Thu, 8 May 2025 17:20:16 -0400 Subject: [PATCH 02/25] Moved bin2cpp::Dictionary definition to types.h. --- src/bin2cpp/CMakeLists.txt | 1 + src/bin2cpp/common.h | 3 ++- src/bin2cpp/enums.h | 2 +- src/bin2cpp/types.h | 41 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/bin2cpp/types.h diff --git a/src/bin2cpp/CMakeLists.txt b/src/bin2cpp/CMakeLists.txt index 324d89c..223afad 100644 --- a/src/bin2cpp/CMakeLists.txt +++ b/src/bin2cpp/CMakeLists.txt @@ -28,6 +28,7 @@ add_executable(bin2cpp SegmentGenerator.h StringGenerator.cpp StringGenerator.h + types.h wildcard.cpp wildcard.h Win32ResourceGenerator.cpp diff --git a/src/bin2cpp/common.h b/src/bin2cpp/common.h index cec0925..c26557f 100644 --- a/src/bin2cpp/common.h +++ b/src/bin2cpp/common.h @@ -31,9 +31,10 @@ #include #include +#include "types.h" + namespace bin2cpp { - typedef std::set Dictionary; /// ///Returns the application version number. diff --git a/src/bin2cpp/enums.h b/src/bin2cpp/enums.h index a5398aa..5ad5355 100644 --- a/src/bin2cpp/enums.h +++ b/src/bin2cpp/enums.h @@ -43,4 +43,4 @@ namespace bin2cpp }; //bin2cpp -#endif //IGENERATOR_H +#endif //ENUMS_H diff --git a/src/bin2cpp/types.h b/src/bin2cpp/types.h new file mode 100644 index 0000000..5f3bc09 --- /dev/null +++ b/src/bin2cpp/types.h @@ -0,0 +1,41 @@ +/********************************************************************************** + * MIT License + * + * Copyright (c) 2018 Antoine Beauchamp + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *********************************************************************************/ + +#ifndef TYPES_H +#define TYPES_H + +#include +#include + +namespace bin2cpp +{ + + /// + ///A set of names stored as a Distionnary + /// + typedef std::set Dictionary; + +}; //bin2cpp + +#endif //TYPES_H From 8d89e5809f21763fcd5bc8bc88e5b51813c1fa14 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 11 May 2025 09:30:37 -0400 Subject: [PATCH 03/25] Created interface `INameProvider`. Moved functions `getDefaultFunctionIdentifier()` and `getDefaultHeaderFile()` from main.cpp to LegacyNameProvider.h. --- src/bin2cpp/CMakeLists.txt | 3 ++ src/bin2cpp/INameProvider.h | 53 +++++++++++++++++++++++++ src/bin2cpp/LegacyNameProvider.cpp | 64 ++++++++++++++++++++++++++++++ src/bin2cpp/LegacyNameProvider.h | 48 ++++++++++++++++++++++ src/bin2cpp/main.cpp | 42 +++++--------------- 5 files changed, 178 insertions(+), 32 deletions(-) create mode 100644 src/bin2cpp/INameProvider.h create mode 100644 src/bin2cpp/LegacyNameProvider.cpp create mode 100644 src/bin2cpp/LegacyNameProvider.h diff --git a/src/bin2cpp/CMakeLists.txt b/src/bin2cpp/CMakeLists.txt index 223afad..326f03b 100644 --- a/src/bin2cpp/CMakeLists.txt +++ b/src/bin2cpp/CMakeLists.txt @@ -21,6 +21,9 @@ add_executable(bin2cpp crc32.h enums.h IGenerator.h + INameProvider.h + LegacyNameProvider.cpp + LegacyNameProvider.h main.cpp ManagerGenerator.cpp ManagerGenerator.h diff --git a/src/bin2cpp/INameProvider.h b/src/bin2cpp/INameProvider.h new file mode 100644 index 0000000..173e233 --- /dev/null +++ b/src/bin2cpp/INameProvider.h @@ -0,0 +1,53 @@ +/********************************************************************************** + * MIT License + * + * Copyright (c) 2018 Antoine Beauchamp + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *********************************************************************************/ + +#ifndef INAME_PROVIDER_H +#define INAME_PROVIDER_H + +#include "types.h" + +namespace bin2cpp +{ + + class INameProvider + { + public: + + /// + ///Get the name of a function identifier based on a given file path. + /// + ///The new context. + virtual std::string getDefaultFunctionIdentifier(const std::string & path, Dictionary & dict) = 0; + + /// + ///Get the name of a function identifier based on a given file path. + /// + ///The new context. + virtual std::string getDefaultHeaderFile(const std::string& path) = 0; + + }; + +}; //bin2cpp + +#endif //INAME_PROVIDER_H diff --git a/src/bin2cpp/LegacyNameProvider.cpp b/src/bin2cpp/LegacyNameProvider.cpp new file mode 100644 index 0000000..5020242 --- /dev/null +++ b/src/bin2cpp/LegacyNameProvider.cpp @@ -0,0 +1,64 @@ +/********************************************************************************** + * MIT License + * + * Copyright (c) 2018 Antoine Beauchamp + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *********************************************************************************/ + +#include "LegacyNameProvider.h" + +#include "common.h" + +#include "rapidassist/strings.h" +#include "rapidassist/filesystem.h" + +namespace bin2cpp +{ + LegacyNameProvider::LegacyNameProvider() + { + } + + LegacyNameProvider::~LegacyNameProvider() + { + } + + std::string LegacyNameProvider::getDefaultFunctionIdentifier(const std::string& path, Dictionary& dict) + { + std::string output; + + //use the file name without extension as 'identifier'. + output = getUniqueFunctionIdentifierFromPath(path.c_str(), dict); + output = ra::strings::CapitalizeFirstCharacter(output); + + return output; + } + + std::string LegacyNameProvider::getDefaultHeaderFile(const std::string& path) + { + std::string output; + + //use the file name without extension as 'headerfile'. + output = ra::filesystem::GetFilenameWithoutExtension(path.c_str()); + output += ".h"; + + return output; + } + +}; //bin2cpp \ No newline at end of file diff --git a/src/bin2cpp/LegacyNameProvider.h b/src/bin2cpp/LegacyNameProvider.h new file mode 100644 index 0000000..29a1bd0 --- /dev/null +++ b/src/bin2cpp/LegacyNameProvider.h @@ -0,0 +1,48 @@ +/********************************************************************************** + * MIT License + * + * Copyright (c) 2018 Antoine Beauchamp + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *********************************************************************************/ + +#ifndef LEGACYNAMEPROVIDER_H +#define LEGACYNAMEPROVIDER_H + +#include "INameProvider.h" + +namespace bin2cpp +{ + /// + ///This is the legacy name generator which generates names for version 3.0.1 and before. + /// + class LegacyNameProvider : public virtual INameProvider + { + public: + LegacyNameProvider(); + virtual ~LegacyNameProvider(); + + //INameProvider methods + virtual std::string getDefaultFunctionIdentifier(const std::string& path, Dictionary& dict); + virtual std::string getDefaultHeaderFile(const std::string& path); + }; + +}; //bin2cpp + +#endif //LEGACYNAMEPROVIDER_H diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index 28dea6b..e9d806b 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -31,6 +31,8 @@ #include "Win32ResourceGenerator.h" #include "ManagerGenerator.h" #include "Context.h" +#include "INameProvider.h" +#include "LegacyNameProvider.h" #include #include @@ -140,11 +142,9 @@ struct ARGUMENTS //pre-declarations bool generateOutputFile(const Context & c, const std::string & output_file_path, bin2cpp::IGenerator * generator); APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * generator); -APP_ERROR_CODES processInputDirectory(const Context & c, bin2cpp::IGenerator * generator); +APP_ERROR_CODES processInputDirectory(const Context & c, bin2cpp::INameProvider* nameProvider, bin2cpp::IGenerator * generator); APP_ERROR_CODES processManagerFiles(const Context & c); APP_ERROR_CODES processPlainOutput(const Context & c, bin2cpp::IGenerator * generator); -std::string getDefaultFunctionIdentifier(const Context & c, Dictionary & identifiers_dictionary); -std::string getDefaultHeaderFile(const Context & c); void printHeader() { @@ -230,7 +230,7 @@ int main(int argc, char* argv[]) args.version = false; Context c; - + INameProvider& nameProvider = LegacyNameProvider(); std::string dummy; //help @@ -344,14 +344,14 @@ int main(int argc, char* argv[]) if (!ra::cli::ParseArgument("identifier", c.functionIdentifier, argc, argv)) { //identifier is not manually specified. - c.functionIdentifier = getDefaultFunctionIdentifier(c, identifiers_dictionary); + c.functionIdentifier = nameProvider.getDefaultFunctionIdentifier(c.inputFilePath, identifiers_dictionary); } //headerfile if (!ra::cli::ParseArgument("headerfile", c.headerFilename, argc, argv)) { //use the file name without extension as 'headerfile'. - c.headerFilename = getDefaultHeaderFile(c); + c.headerFilename = nameProvider.getDefaultHeaderFile(c.inputFilePath); } } @@ -499,7 +499,7 @@ int main(int argc, char* argv[]) } else if (c.hasInputDir) { - APP_ERROR_CODES error = processInputDirectory(c, generator); + APP_ERROR_CODES error = processInputDirectory(c, &nameProvider, generator); if (error != APP_ERROR_SUCCESS) { ra::logging::Log(ra::logging::LOG_ERROR, "%s.", getErrorCodeDescription(error)); @@ -521,28 +521,6 @@ int main(int argc, char* argv[]) return APP_ERROR_SUCCESS; } -std::string getDefaultFunctionIdentifier(const Context & c, Dictionary & identifiers_dictionary) -{ - std::string output; - - //use the file name without extension as 'identifier'. - output = getUniqueFunctionIdentifierFromPath(c.inputFilePath.c_str(), identifiers_dictionary); - output = ra::strings::CapitalizeFirstCharacter(output); - - return output; -} - -std::string getDefaultHeaderFile(const Context & c) -{ - std::string output; - - //use the file name without extension as 'headerfile'. - output = ra::filesystem::GetFilenameWithoutExtension(c.inputFilePath.c_str()); - output += ".h"; - - return output; -} - APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * generator) { // printing info @@ -612,7 +590,7 @@ APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * genera return APP_ERROR_SUCCESS; } -APP_ERROR_CODES processInputDirectory(const Context& c, bin2cpp::IGenerator * generator) +APP_ERROR_CODES processInputDirectory(const Context& c, bin2cpp::INameProvider * nameProvider, bin2cpp::IGenerator * generator) { //check if input dir exists if (!ra::filesystem::DirectoryExists(c.inputDirPath.c_str())) @@ -680,10 +658,10 @@ APP_ERROR_CODES processInputDirectory(const Context& c, bin2cpp::IGenerator * ge cCopy.inputFilePath = file; //use the file name without extension as 'headerfile'. - cCopy.headerFilename = getDefaultHeaderFile(cCopy); + cCopy.headerFilename = nameProvider->getDefaultHeaderFile(cCopy.inputFilePath); //use the file name without extension as 'identifier'. - cCopy.functionIdentifier = getDefaultFunctionIdentifier(cCopy, identifiers_dictionary); + cCopy.functionIdentifier = nameProvider->getDefaultFunctionIdentifier(cCopy.inputFilePath, identifiers_dictionary); //build a relative file path std::string relative_file_path = file; From fc9fedafd998e1face89d4bb22ce053956e21029 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 11 May 2025 09:37:25 -0400 Subject: [PATCH 04/25] Created CodeGenerationEnum enum and supporting function `parseCode()` and `getDefaultCodeSourceFileExtension()`. --- src/bin2cpp/common.cpp | 28 ++++++++++++++++++++++++++++ src/bin2cpp/common.h | 15 +++++++++++++++ src/bin2cpp/enums.h | 16 +++++++++++----- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/bin2cpp/common.cpp b/src/bin2cpp/common.cpp index a94f6fd..49fa69e 100755 --- a/src/bin2cpp/common.cpp +++ b/src/bin2cpp/common.cpp @@ -364,4 +364,32 @@ namespace bin2cpp return output; } + CodeGenerationEnum parseCode(const std::string& value) + { + std::string value_upper = ra::strings::Uppercase(value); + if ( value_upper == "C" ) + return CodeGenerationEnum::CODE_GENERATION_C; + if ( value_upper == "CPP" || value_upper == "C++" ) + return CodeGenerationEnum::CODE_GENERATION_CPP; + return CodeGenerationEnum::CODE_GENERATION_UNKNOW; + } + + const std::string& getDefaultCodeSourceFileExtension(CodeGenerationEnum code) + { + static const std::string EMPTY = ""; + static const std::string CPP = "cpp"; + static const std::string C = "c"; + switch ( code ) + { + case CODE_GENERATION_UNKNOW: + return EMPTY; + case CODE_GENERATION_CPP: + return CPP; + case CODE_GENERATION_C: + return C; + default: + return EMPTY; + }; + } + }; //bin2cpp diff --git a/src/bin2cpp/common.h b/src/bin2cpp/common.h index c26557f..d0d2e01 100644 --- a/src/bin2cpp/common.h +++ b/src/bin2cpp/common.h @@ -32,6 +32,7 @@ #include #include "types.h" +#include "enums.h" namespace bin2cpp { @@ -142,6 +143,20 @@ namespace bin2cpp ///Returns the combined string. std::string strJoin(const std::vector& values, char separator); + /// + ///Parse a CodeGenerationEnum from a string. + /// + ///The string value representing of the code language. + ///Returns a valid CodeGenerationEnum value. Returns CODE_GENERATION_UNKNOW on parsing error. + CodeGenerationEnum parseCode(const std::string& value); + + /// + ///Get the default source file extension for the given CodeGenerationEnum. + /// + ///The code generation language. + ///Returns a valid file extension valu that matches the given code. Returns an empty string otherwise. + const std::string & getDefaultCodeSourceFileExtension(CodeGenerationEnum code); + }; //bin2cpp #endif //BIN2CPP_COMMON_H diff --git a/src/bin2cpp/enums.h b/src/bin2cpp/enums.h index 5ad5355..82a7539 100644 --- a/src/bin2cpp/enums.h +++ b/src/bin2cpp/enums.h @@ -24,22 +24,28 @@ #ifndef ENUMS_H #define ENUMS_H - -#include -#include "Context.h" namespace bin2cpp { /// - ///Defines the different type of cpp encoding. - ///See setCppEncoder() and getCppEncoder() functions. + ///Defines the different types of cpp encoding. /// enum CppEncoderEnum { CPP_ENCODER_OCT, CPP_ENCODER_HEX, }; + + /// + ///Defines the different types of programming language code output. + /// + enum CodeGenerationEnum + { + CODE_GENERATION_UNKNOW, + CODE_GENERATION_CPP, + CODE_GENERATION_C, + }; }; //bin2cpp From 22dbb60829d3693dc3caddfe7678cce3fad516ae Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 11 May 2025 09:52:17 -0400 Subject: [PATCH 05/25] Implemented `--code` argument support to specify the programming language output for code generation. --- src/bin2cpp/Context.cpp | 2 ++ src/bin2cpp/Context.h | 1 + src/bin2cpp/main.cpp | 29 +++++++++++++++++++++++++++-- test/bin2cpp_unittest/TestCLI.cpp | 13 ++++++++----- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/bin2cpp/Context.cpp b/src/bin2cpp/Context.cpp index fcd5e6a..dee7bbc 100644 --- a/src/bin2cpp/Context.cpp +++ b/src/bin2cpp/Context.cpp @@ -69,6 +69,7 @@ namespace bin2cpp this->generatorName = other.generatorName ; this->directoryIncludeFilters = other.directoryIncludeFilters ; this->directoryExcludeFilters = other.directoryExcludeFilters ; + this->code = other.code ; } return *this; } @@ -101,6 +102,7 @@ namespace bin2cpp generatorName.clear(); directoryIncludeFilters.clear(); directoryExcludeFilters.clear(); + code = CodeGenerationEnum::CODE_GENERATION_CPP; } diff --git a/src/bin2cpp/Context.h b/src/bin2cpp/Context.h index 315d32f..3262713 100644 --- a/src/bin2cpp/Context.h +++ b/src/bin2cpp/Context.h @@ -72,6 +72,7 @@ namespace bin2cpp std::string generatorName; std::vector directoryIncludeFilters; std::vector directoryExcludeFilters; + CodeGenerationEnum code; void reset(); diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index e9d806b..0a78798 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -59,7 +59,8 @@ enum APP_ERROR_CODES APP_ERROR_TOOMANYARGUMENTS, APP_ERROR_INPUTDIRNOTFOUND, AAP_ERROR_NOTSUPPORTED, - APP_ERROR_OPERATIONHASFAILED + APP_ERROR_OPERATIONHASFAILED, + APP_ERROR_INVALIDVALUE, }; enum FILE_UPDATE_MODE @@ -75,6 +76,7 @@ static const size_t DEFAULT_CHUNK_SIZE = 200; static const char * DEFAULT_NAMESPACE = "bin2cpp"; static const char * DEFAULT_BASECLASSNAME = "File"; static const CppEncoderEnum DEFAULT_ENCODING = CPP_ENCODER_OCT; +static const CodeGenerationEnum DEFAULT_CODE_GENERATION = CODE_GENERATION_CPP; static Dictionary identifiers_dictionary; // unique values for identifiers static Dictionary output_files_dictionary; // unique values for output file names #define DIRECTORY_FILTER_SEPARATOR_STR ":" @@ -108,6 +110,9 @@ const char * getErrorCodeDescription(const APP_ERROR_CODES & error_code) case APP_ERROR_OPERATIONHASFAILED: return "Operation has failed"; break; + case APP_ERROR_INVALIDVALUE: + return "Invalid value"; + break; default: return "Unknown error"; }; @@ -198,6 +203,7 @@ void printUsage() " --keepdirs Keep the directory structure. Forces the output files to have the same\n" " directory structure as the input files. Valid only when --dir is used.\n" " --plainoutput Print the encoded string in plain format to stdout. Useful for scripts and integration with third party application.\n" + " --code Define the programming language output for code generation. Supported values are 'c', 'cpp', 'c++'.\n" " --override Tells bin2cpp to overwrite the destination files.\n" " --noheader Do not print program header to standard output.\n" " --quiet Do not log any message to standard output.\n" @@ -338,6 +344,25 @@ int main(int argc, char* argv[]) //optional arguments + std::string codeStr; + if ( ra::cli::ParseArgument("code", codeStr, argc, argv) ) + { + CodeGenerationEnum codeTmp = parseCode(codeStr); + if ( codeTmp == CodeGenerationEnum::CODE_GENERATION_UNKNOW ) + { + APP_ERROR_CODES error = APP_ERROR_INVALIDVALUE; + ra::logging::Log(ra::logging::LOG_ERROR, "%s (code)", getErrorCodeDescription(error)); + printUsage(); + return error; + } + + c.code = codeTmp; + } + else + { + c.code = DEFAULT_CODE_GENERATION; + } + if (c.hasInputFile) { //identifier @@ -417,7 +442,7 @@ int main(int argc, char* argv[]) c.cppEncoder = CPP_ENCODER_HEX; else { - APP_ERROR_CODES error = APP_ERROR_MISSINGARGUMENTS; + APP_ERROR_CODES error = APP_ERROR_INVALIDVALUE; ra::logging::Log(ra::logging::LOG_ERROR, "%s (encoding)", getErrorCodeDescription(error)); printUsage(); return error; diff --git a/test/bin2cpp_unittest/TestCLI.cpp b/test/bin2cpp_unittest/TestCLI.cpp index 5a6ca0b..1ce7046 100755 --- a/test/bin2cpp_unittest/TestCLI.cpp +++ b/test/bin2cpp_unittest/TestCLI.cpp @@ -48,12 +48,15 @@ extern const std::string & gGeneratedFilesDir; enum APP_ERROR_CODES { - APP_ERROR_SUCCESS, + APP_ERROR_SUCCESS = 0, APP_ERROR_MISSINGARGUMENTS, APP_ERROR_INPUTFILENOTFOUND, APP_ERROR_UNABLETOCREATEOUTPUTFILES, APP_ERROR_TOOMANYARGUMENTS, - APP_ERROR_INPUTDIRNOTFOUND + APP_ERROR_INPUTDIRNOTFOUND, + AAP_ERROR_NOTSUPPORTED, + APP_ERROR_OPERATIONHASFAILED, + APP_ERROR_INVALIDVALUE, }; namespace TestCLIUtils @@ -1224,7 +1227,7 @@ TEST_F(TestCLI, testAutomaticIdentifierHeaderfile) ASSERT_TRUE(deleteFile(cppFilePath.c_str())); } -TEST_F(TestCLI, testErrorMissingArgumentEncoding) +TEST_F(TestCLI, testErrorInvalidArgumentEncoding) { static const std::string expectedFilePath = getExpectedFilePath(); static const std::string outputFilePath = getActualFilePath(); @@ -1258,7 +1261,7 @@ TEST_F(TestCLI, testErrorMissingArgumentEncoding) #if defined(__linux__) || defined(__APPLE__) returnCode = WEXITSTATUS(returnCode); #endif - ASSERT_EQ(APP_ERROR_MISSINGARGUMENTS, returnCode) << "The command line '" << cmdline.c_str() << "' returned " << returnCode; + ASSERT_EQ(APP_ERROR_INVALIDVALUE, returnCode) << "The command line '" << cmdline.c_str() << "' returned " << returnCode; //load output file ra::strings::StringVector lines; @@ -1266,7 +1269,7 @@ TEST_F(TestCLI, testErrorMissingArgumentEncoding) ASSERT_TRUE(loaded); //assert standard output log - ASSERT_TEXT_IN_FILE(true, outputFilePath.c_str(), "Error: Missing arguments (encoding)"); + ASSERT_TEXT_IN_FILE(true, outputFilePath.c_str(), "Error: Invalid value (encoding)"); //cleanup ASSERT_TRUE(deleteFile(outputFilePath.c_str())); From b2c1416e0abde05755243a182cfdbe9046615b12 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 11 May 2025 10:01:12 -0400 Subject: [PATCH 06/25] Modified IGenerator interface to add support for generating C source and header files with functions `createCHeaderFile()` and `createCSourceFile()`. Modified main.cpp to properly parse CodeGenerationEnum and generate *.h/*.c files when `--code=c` is specified. --- src/bin2cpp/BaseGenerator.cpp | 26 +++++++++++---- src/bin2cpp/BaseGenerator.h | 2 ++ src/bin2cpp/IGenerator.h | 14 ++++++++ src/bin2cpp/bin2cpp.samples.txt | 4 +-- src/bin2cpp/common.cpp | 16 +++++++++ src/bin2cpp/common.h | 14 ++++++++ src/bin2cpp/main.cpp | 58 +++++++++++++++++++++++++-------- 7 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/bin2cpp/BaseGenerator.cpp b/src/bin2cpp/BaseGenerator.cpp index 46d0c19..98f5d3c 100755 --- a/src/bin2cpp/BaseGenerator.cpp +++ b/src/bin2cpp/BaseGenerator.cpp @@ -61,13 +61,13 @@ namespace bin2cpp std::string BaseGenerator::getGetterFunctionName() { - //Uppercase function identifier - std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mContext.functionIdentifier); + //Uppercase function identifier + std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mContext.functionIdentifier); std::string getter; - getter.append("get"); - getter.append(functionIdentifier); - getter.append("File"); + getter.append("get"); + getter.append(functionIdentifier); + getter.append("File"); return getter; } @@ -75,7 +75,7 @@ namespace bin2cpp { //Build header file path std::string headerPath = cpp_file_path; - ra::strings::Replace(headerPath, ".cpp", ".h"); + ra::strings::Replace(headerPath, ".cpp", ".h"); return headerPath; } @@ -83,7 +83,7 @@ namespace bin2cpp { //Build header file path std::string cppPath = header_file_path; - ra::strings::Replace(cppPath, ".cpp", ".h"); + ra::strings::Replace(cppPath, ".cpp", ".h"); return cppPath; } @@ -320,4 +320,16 @@ namespace bin2cpp return true; } + bool BaseGenerator::createCHeaderFile(const char* file_path) + { + // not supported yet + return false; + } + + bool BaseGenerator::createCSourceFile(const char* file_path) + { + // not supported yet + return false; + } + }; //bin2cpp \ No newline at end of file diff --git a/src/bin2cpp/BaseGenerator.h b/src/bin2cpp/BaseGenerator.h index 0fcfd6e..cdeb216 100644 --- a/src/bin2cpp/BaseGenerator.h +++ b/src/bin2cpp/BaseGenerator.h @@ -46,6 +46,8 @@ namespace bin2cpp //same header file for all generators virtual bool createCppHeaderFile(const char * header_file_path); virtual bool printFileContent(); + virtual bool createCHeaderFile(const char* file_path); + virtual bool createCSourceFile(const char* file_path); protected: diff --git a/src/bin2cpp/IGenerator.h b/src/bin2cpp/IGenerator.h index d7b487e..5b459cb 100644 --- a/src/bin2cpp/IGenerator.h +++ b/src/bin2cpp/IGenerator.h @@ -61,6 +61,20 @@ namespace bin2cpp ///Returns true when the file was created. Returns false otherwise. virtual bool createCppSourceFile(const char * cpp_file_path) = 0; + /// + ///Creates a header file for embedding a given file into C source code. + /// + ///The path of the header file (*.h) to generate. + ///Returns true when the file was created. Returns false otherwise. + virtual bool createCHeaderFile(const char* file_path) = 0; + + /// + ///Creates a C source file for embedding a given file into C source code. + /// + ///The path of the source file (*.c) to generate. + ///Returns true when the file was created. Returns false otherwise. + virtual bool createCSourceFile(const char* file_path) = 0; + /// ///Print the encoded file content to stdout /// diff --git a/src/bin2cpp/bin2cpp.samples.txt b/src/bin2cpp/bin2cpp.samples.txt index 88c7520..f6c68b7 100644 --- a/src/bin2cpp/bin2cpp.samples.txt +++ b/src/bin2cpp/bin2cpp.samples.txt @@ -1,8 +1,6 @@ +--file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --file=.\generated_files\testText1000\testText1000.bin --output=.\generated_files\testText1000 --headerfile=_testText1000.h --identifier=testText1000 --chunksize=450 --override --file=.\generated_files\testSequential1000\testSequential1000.bin --output=.\generated_files\testSequential1000 --headerfile=_testSequential1000.h --identifier=testSequential1000 --chunksize=180 --override ---file=C:\Temp\foobar.bin --output=C:\Temp --headerfile=_testFoo.h --identifier=testFoo --override ---file=C:\Temp\foobar.bin --output=C:\Temp --headerfile=_testFoo.h --identifier=testFoo --override --noheader ---dir=D:\Temp\foobar --output=C:\Temp\foobar --override –noheader --file=..\..\test\bin2cpp_unittest\generated_files\testIssue28\testIssue28.bin --output=..\..\test\bin2cpp_unittest\generated_files\testIssue28 --headerfile=_testIssue28.h --identifier=testIssue28 --managerfile=FileManager.h --override --file=..\..\test\bin2cpp_unittest\generated_files\testIssue28\testIssue28.bin --output=..\..\test\bin2cpp_unittest\generated_files\testIssue28 --headerfile=_testIssue28.h --identifier=testIssue28 --managerfile=FileManager.h --override --file=..\..\test\bin2cpp_unittest\generated_files\testSequential1000\testSequential1000.bin --headerfile="generated/foo-data.h" --output=. --identifier=TestLongPath diff --git a/src/bin2cpp/common.cpp b/src/bin2cpp/common.cpp index 49fa69e..796a38e 100755 --- a/src/bin2cpp/common.cpp +++ b/src/bin2cpp/common.cpp @@ -94,6 +94,22 @@ namespace bin2cpp return false; } + bool isCHeaderFile(const std::string & path) + { + std::string extension = ra::strings::Uppercase(ra::filesystem::GetFileExtention(path)); + if (extension == "H") + return true; + return false; + } + + bool isCSourceFile(const std::string & path) + { + std::string extension = ra::strings::Uppercase(ra::filesystem::GetFileExtention(path)); + if (extension == "C") + return true; + return false; + } + std::string getCppIncludeGuardMacroName(const std::string & path) { static const std::string EMPTY_STRING; diff --git a/src/bin2cpp/common.h b/src/bin2cpp/common.h index d0d2e01..48aca46 100644 --- a/src/bin2cpp/common.h +++ b/src/bin2cpp/common.h @@ -64,6 +64,20 @@ namespace bin2cpp ///Returns true if path is a c++ source file. Returns false otherwise. bool isCppSourceFile(const std::string & path); + /// + ///Determine if a given path is a C header file. + /// + ///An valid file path. + ///Returns true if path is a C header file. Returns false otherwise. + bool isCHeaderFile(const std::string & path); + + /// + ///Determine if a given path is a C source file. + /// + ///An valid file path. + ///Returns true if path is a C source file. Returns false otherwise. + bool isCSourceFile(const std::string & path); + /// ///Determine the appropriate macro name for the include guard of the given c++ header file. ///See also https://en.wikipedia.org/wiki/Include_guard diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index 0a78798..f287b4f 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -73,8 +73,10 @@ enum FILE_UPDATE_MODE //default values static const size_t DEFAULT_CHUNK_SIZE = 200; -static const char * DEFAULT_NAMESPACE = "bin2cpp"; -static const char * DEFAULT_BASECLASSNAME = "File"; +static const char * DEFAULT_NAMESPACE_CPP = "bin2cpp"; +static const char * DEFAULT_NAMESPACE_C = "bin2c"; +static const char * DEFAULT_BASECLASS_NAME_CPP = "File"; +static const char * DEFAULT_BASECLASS_NAME_C = "Bin2cFile"; static const CppEncoderEnum DEFAULT_ENCODING = CPP_ENCODER_OCT; static const CodeGenerationEnum DEFAULT_CODE_GENERATION = CODE_GENERATION_CPP; static Dictionary identifiers_dictionary; // unique values for identifiers @@ -391,12 +393,31 @@ int main(int argc, char* argv[]) if (!ra::cli::ParseArgument("namespace", c.codeNamespace, argc, argv)) { - c.codeNamespace = DEFAULT_NAMESPACE; + switch ( c.code ) + { + default: + case CODE_GENERATION_CPP: + c.codeNamespace = DEFAULT_NAMESPACE_CPP; + break; + case CODE_GENERATION_C: + c.codeNamespace = DEFAULT_NAMESPACE_C; + break; + }; + } if (!ra::cli::ParseArgument("baseclass", c.baseClass, argc, argv)) { - c.baseClass = DEFAULT_BASECLASSNAME; + switch ( c.code ) + { + default: + case CODE_GENERATION_CPP: + c.baseClass = DEFAULT_BASECLASS_NAME_CPP; + break; + case CODE_GENERATION_C: + c.baseClass = DEFAULT_BASECLASS_NAME_C; + break; + }; } c.registerFiles = ra::cli::ParseArgument("registerfile", dummy, argc, argv); @@ -567,8 +588,9 @@ APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * genera return APP_ERROR_INPUTFILENOTFOUND; //prepare output files path - std::string headerExtention = ra::filesystem::GetFileExtention(c.headerFilename); - std::string cppFilename = c.headerFilename.substr(0, c.headerFilename.size() - headerExtention.size()) + "cpp"; // strip out header file's extension and add 'cpp'. + const std::string headerExtention = ra::filesystem::GetFileExtention(c.headerFilename); + const std::string & sourceExtension = getDefaultCodeSourceFileExtension(c.code); + std::string sourceFilename = c.headerFilename.substr(0, c.headerFilename.size() - headerExtention.size()) + sourceExtension; // strip out header file's extension and add 'cpp'. //create a copy of the context. //we may have already generated files from a previous call to processInputFile(). @@ -577,11 +599,11 @@ APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * genera //build unique output relative file paths cCopy.headerFilename = bin2cpp::getUniqueFilePath(cCopy.headerFilename, output_files_dictionary); - cppFilename = bin2cpp::getUniqueFilePath(cppFilename, output_files_dictionary); + sourceFilename = bin2cpp::getUniqueFilePath(sourceFilename, output_files_dictionary); //build full absolute paths std::string outputHeaderPath = cCopy.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cCopy.headerFilename; - std::string outputCppPath = cCopy.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cppFilename; + std::string outputSourcePath = cCopy.outputDirPath + ra::filesystem::GetPathSeparatorStr() + sourceFilename; //configure the generator generator->setContext(cCopy); @@ -607,7 +629,7 @@ APP_ERROR_CODES processInputFile(const Context & c, bin2cpp::IGenerator * genera if (!headerResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; - bool cppResult = generateOutputFile(c, outputCppPath, generator); + bool cppResult = generateOutputFile(c, outputSourcePath, generator); if (!cppResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; @@ -760,16 +782,26 @@ bool generateOutputFile(const Context & c, const std::string & output_file_path, //generate file bool result = false; - if (isCppHeaderFile(output_file_path)) + if (c.code == CODE_GENERATION_CPP && isCppHeaderFile(output_file_path)) { - //generate header + //generate C++ header result = generator->createCppHeaderFile(output_file_path.c_str()); } - else + else if ( c.code == CODE_GENERATION_CPP) { - //generate cpp + //generate C++ source result = generator->createCppSourceFile(output_file_path.c_str()); } + else if ( c.code == CODE_GENERATION_C && isCHeaderFile(output_file_path) ) + { + //generate C header + result = generator->createCHeaderFile(output_file_path.c_str()); + } + else if ( c.code == CODE_GENERATION_C ) + { + //generate C source + result = generator->createCSourceFile(output_file_path.c_str()); + } if (!result) { //there was an error generating file From 2253490216785320a3bc74aaa674055aafd54855 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 11 May 2025 10:03:15 -0400 Subject: [PATCH 07/25] Created a valid implementation of IGenerator::createCHeaderFile() in BAseGenrator and a valid implementation of IGenerator::createCSourceFile() in SegmentGenerator. --- src/bin2cpp/BaseGenerator.cpp | 128 ++++++++++++++++++++++++- src/bin2cpp/BaseGenerator.h | 2 + src/bin2cpp/SegmentGenerator.cpp | 159 ++++++++++++++++++++++++++++++- src/bin2cpp/SegmentGenerator.h | 1 + 4 files changed, 286 insertions(+), 4 deletions(-) diff --git a/src/bin2cpp/BaseGenerator.cpp b/src/bin2cpp/BaseGenerator.cpp index 98f5d3c..c98dfdd 100755 --- a/src/bin2cpp/BaseGenerator.cpp +++ b/src/bin2cpp/BaseGenerator.cpp @@ -61,13 +61,32 @@ namespace bin2cpp std::string BaseGenerator::getGetterFunctionName() { + + std::string getter; + switch ( mContext.code ) + { + default: + case CODE_GENERATION_CPP: + { //Uppercase function identifier std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mContext.functionIdentifier); - std::string getter; getter.append("get"); getter.append(functionIdentifier); getter.append("File"); + } + break; + case CODE_GENERATION_C: + { + //Uppercase function identifier + std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); + + getter.append("bin2c_get_file_"); + getter.append(functionIdentifier); + } + break; + }; + return getter; } @@ -75,7 +94,17 @@ namespace bin2cpp { //Build header file path std::string headerPath = cpp_file_path; + switch ( mContext.code ) + { + default: + case CODE_GENERATION_CPP: ra::strings::Replace(headerPath, ".cpp", ".h"); + break; + case CODE_GENERATION_C: + ra::strings::Replace(headerPath, ".c", ".h"); + break; + }; + return headerPath; } @@ -83,7 +112,17 @@ namespace bin2cpp { //Build header file path std::string cppPath = header_file_path; + switch ( mContext.code ) + { + default: + case CODE_GENERATION_CPP: ra::strings::Replace(cppPath, ".cpp", ".h"); + break; + case CODE_GENERATION_C: + ra::strings::Replace(cppPath, ".c", ".h"); + break; + }; + return cppPath; } @@ -225,6 +264,50 @@ namespace bin2cpp return output; } + std::string BaseGenerator::getFileClassFileName() + { + std::string output; + + std::string inputFileName = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); + + //return default implementation + output += inputFileName; + return output; + } + + std::string BaseGenerator::getFileClassFilePath() + { + std::string output; + + //convert mReportedFilePath string to c++ + std::string path = mContext.reportedFilePath; +#ifdef _WIN32 + //escape backslash characters for c++ + static const std::string BACKSLASH = "\\"; + static const std::string BACKSLASH_ESCAPED = "\\\\"; + ra::strings::Replace(path, BACKSLASH, BACKSLASH_ESCAPED); +#endif + + //is there a reported path specified ? + const char * reported_path = mContext.reportedFilePath.c_str(); + if (reported_path != NULL && reported_path[0] != '\0') + { + output += path; + return output; + } + else + { + //if reported path is not specified ? + //report the same as getFileName() + output = getFileClassFileName(); + return output; + } + + //return default implementation + output += path; + return output; + } + bool BaseGenerator::createCppHeaderFile(const char * header_file_path) { FILE * header = fopen(header_file_path, "w"); @@ -322,8 +405,47 @@ namespace bin2cpp bool BaseGenerator::createCHeaderFile(const char* file_path) { - // not supported yet - return false; + FILE* header = fopen(file_path, "w"); + if ( !header ) + return false; + + //define macro guard matching the filename + std::string macroGuard = getCppIncludeGuardMacroName(file_path); + + std::string classMacroGuardPrefix = getClassMacroGuardPrefix(); + std::string fileHeader = getHeaderTemplate(); + + fprintf(header, "%s", fileHeader.c_str()); + fprintf(header, "#ifndef %s\n", macroGuard.c_str()); + fprintf(header, "#define %s\n", macroGuard.c_str()); + fprintf(header, "\n"); + fprintf(header, "#include \n"); + fprintf(header, "#include \n"); + fprintf(header, "\n"); + fprintf(header, "#ifndef %s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); + fprintf(header, "#define %s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); + fprintf(header, "typedef struct %s %s;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); + fprintf(header, "typedef bool(*bin2c_load_func)();\n"); + fprintf(header, "typedef void(*bin2c_free_func)();\n"); + fprintf(header, "typedef bool(*bin2c_save_func)(const char*);\n"); + fprintf(header, "typedef struct %s\n", mContext.baseClass.c_str()); + fprintf(header, "{\n"); + fprintf(header, " size_t size;\n"); + fprintf(header, " const char* file_name;\n"); + fprintf(header, " const char* file_path;\n"); + fprintf(header, " unsigned char* buffer;\n"); + fprintf(header, " bin2c_load_func load;\n"); + fprintf(header, " bin2c_free_func unload;\n"); + fprintf(header, " bin2c_save_func save;\n"); + fprintf(header, "} %s;\n", mContext.baseClass.c_str()); + fprintf(header, "#endif //%s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); + fprintf(header, "%s* %s();\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); + fprintf(header, "\n"); + fprintf(header, "#endif //%s\n", macroGuard.c_str()); + + fclose(header); + + return true; } bool BaseGenerator::createCSourceFile(const char* file_path) diff --git a/src/bin2cpp/BaseGenerator.h b/src/bin2cpp/BaseGenerator.h index cdeb216..d4944fe 100644 --- a/src/bin2cpp/BaseGenerator.h +++ b/src/bin2cpp/BaseGenerator.h @@ -62,6 +62,8 @@ namespace bin2cpp virtual std::string getClassMacroGuardPrefix(); virtual std::string getImplOfGetFileName(); virtual std::string getImplOfGetFilePath(); + virtual std::string getFileClassFileName(); + virtual std::string getFileClassFilePath(); //attributes Context mContext; diff --git a/src/bin2cpp/SegmentGenerator.cpp b/src/bin2cpp/SegmentGenerator.cpp index 8099bbd..ffa90f2 100755 --- a/src/bin2cpp/SegmentGenerator.cpp +++ b/src/bin2cpp/SegmentGenerator.cpp @@ -61,7 +61,7 @@ namespace bin2cpp std::string headerPath = getHeaderFilePath(cpp_file_path); std::string cppPath = cpp_file_path; - //create cpp file + //create cpp source file FILE * cpp = fopen(cppPath.c_str(), "w"); if (!cpp) { @@ -160,4 +160,161 @@ namespace bin2cpp return true; } + bool SegmentGenerator::createCSourceFile(const char* file_path) + { + //check if input file exists + FILE* input = fopen(mContext.inputFilePath.c_str(), "rb"); + if ( !input ) + return false; + + //Uppercase function identifier + std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); + + //Build header and cpp file path + std::string headerPath = getHeaderFilePath(file_path); + std::string sourcePath = file_path; + + //create c source file + FILE* fout = fopen(sourcePath.c_str(), "w"); + if ( !fout ) + { + fclose(input); + return false; + } + + //determine file properties + uint32_t fileSize = ra::filesystem::GetFileSize(input); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); + //long lastSegmentSize = fileSize%chunk_size; + //size_t numSegments = fileSize/chunk_size + (lastSegmentSize == 0 ? 0 : 1); + + //Build class name + std::string className = getClassName(); + + //Build function + std::string getterFunctionName = getGetterFunctionName(); + + //Build FileManager class template + std::string manager = mContext.managerHeaderFilename; + + //write c file heading + fprintf(fout, "%s", getHeaderTemplate().c_str()); + fprintf(fout, "#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n"); + fprintf(fout, "#define _CRT_SECURE_NO_WARNINGS\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, "#include \"%s\"\n", mContext.headerFilename.c_str()); + fprintf(fout, "#include // for malloc\n"); + fprintf(fout, "#include // for memset\n"); + fprintf(fout, "#include // for fopen\n"); + + fprintf(fout, "static %s %s_file = { 0 };\n", mContext.baseClass.c_str(), functionIdentifier.c_str()); + fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + + fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " return true;\n"); + fprintf(fout, "\n"); + fprintf(fout, " unsigned char* local_buffer = (unsigned char*)malloc(%s_file.size);\n", functionIdentifier.c_str()); + fprintf(fout, " if ( local_buffer == NULL )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, "\n"); + fprintf(fout, " unsigned char* next = local_buffer;\n"); + + //create buffer for each chunks from input buffer + unsigned char* buffer = new unsigned char[getContext().chunkSize]; + while ( !feof(input) ) + { + //read a chunk of the file + size_t readSize = fread(buffer, 1, getContext().chunkSize, input); + + //bool isLastChunk = !(readSize == chunk_size); + + if ( readSize == 0 ) + continue; //nothing to output if nothing was read + + //convert to cpp string + std::string cppEncoder; + switch ( getContext().cppEncoder ) + { + case CPP_ENCODER_HEX: + cppEncoder = ra::code::cpp::ToHexString(buffer, readSize); + break; + case CPP_ENCODER_OCT: + default: + cppEncoder = ra::code::cpp::ToOctString(buffer, readSize, false); + break; + }; + + //output + fprintf(fout, " memcpy(next, \"%s\", %s); next += %s; \n", cppEncoder.c_str(), ra::strings::ToString(readSize).c_str(), ra::strings::ToString(readSize).c_str()); + } + delete[] buffer; + buffer = NULL; + + fprintf(fout, "\n"); + fprintf(fout, " %s_file.buffer = local_buffer;\n", functionIdentifier.c_str()); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + + fprintf(fout, "\n"); + + fprintf(fout, "void %s_free()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " free(%s_file.buffer);\n", functionIdentifier.c_str()); + fprintf(fout, " %s_file.buffer = NULL;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "bool %s_save(const char* path)\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( !%s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " return false;\n"); + fprintf(fout, " FILE* f = fopen(path, \"wb\");\n"); + fprintf(fout, " if ( !f )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " size_t write_size = fwrite(%s_file.buffer, 1, %s_file.size, f);\n", functionIdentifier.c_str(), functionIdentifier.c_str()); + fprintf(fout, " fclose(f);\n"); + fprintf(fout, " if ( write_size != %s_file.size )\n", functionIdentifier.c_str()); + fprintf(fout, " return false;\n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "inline void %s_init()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " // remember we already initialized\n"); + fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str()); + fprintf(fout, " return;\n"); + fprintf(fout, " %s_initialized = true;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + fprintf(fout, " // initialize\n"); + fprintf(fout, " %s* file = &%s_file;\n", mContext.baseClass.c_str(), functionIdentifier.c_str()); + fprintf(fout, " file->size = %uULL;\n", fileSize); + fprintf(fout, " file->file_name = \"%s\";\n", getFileClassFileName().c_str()); + fprintf(fout, " file->file_path = \"%s\";\n", getFileClassFilePath().c_str()); + fprintf(fout, " file->buffer = NULL;\n"); + fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); + fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); + fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " %s_init();\n", functionIdentifier.c_str()); + fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + + if ( mContext.registerFiles ) + { + std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + fprintf(fout, "%s", fileManagerTemplate.c_str()); + } + + fclose(input); + fclose(fout); + + return true; + } + }; //bin2cpp \ No newline at end of file diff --git a/src/bin2cpp/SegmentGenerator.h b/src/bin2cpp/SegmentGenerator.h index 92757db..767eeaa 100644 --- a/src/bin2cpp/SegmentGenerator.h +++ b/src/bin2cpp/SegmentGenerator.h @@ -41,6 +41,7 @@ namespace bin2cpp virtual ~SegmentGenerator(); virtual const char * getName() const; virtual bool createCppSourceFile(const char * cpp_file_path); + virtual bool createCSourceFile(const char* file_path); }; }; //bin2cpp From bcfbe55ddd3be507de2d928485836956c7f6b72f Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Mon, 12 May 2025 19:14:49 -0400 Subject: [PATCH 08/25] Implemented C code generation support for ArrayGenerator, SegmentGenerator, StringGenerator and Win32ResourceGenerator. #53 --- src/bin2cpp/ArrayGenerator.cpp | 155 ++++++++++++++++++- src/bin2cpp/ArrayGenerator.h | 1 + src/bin2cpp/BaseGenerator.cpp | 2 +- src/bin2cpp/SegmentGenerator.cpp | 3 +- src/bin2cpp/StringGenerator.cpp | 168 +++++++++++++++++++- src/bin2cpp/StringGenerator.h | 1 + src/bin2cpp/Win32ResourceGenerator.cpp | 203 ++++++++++++++++++++++++- src/bin2cpp/Win32ResourceGenerator.h | 2 + src/bin2cpp/bin2cpp.samples.txt | 7 +- 9 files changed, 536 insertions(+), 6 deletions(-) diff --git a/src/bin2cpp/ArrayGenerator.cpp b/src/bin2cpp/ArrayGenerator.cpp index 0ed05f0..ca34592 100644 --- a/src/bin2cpp/ArrayGenerator.cpp +++ b/src/bin2cpp/ArrayGenerator.cpp @@ -131,7 +131,7 @@ namespace bin2cpp delete[] buffer; buffer = NULL; - //write cpp file footer + //write cpp source file footer fprintf(cpp, " return (const char *)buffer;\n"); fprintf(cpp, " }\n"); fprintf(cpp, "%s", getSaveMethodTemplate().c_str()); @@ -192,4 +192,157 @@ namespace bin2cpp return true; } + bool ArrayGenerator::createCSourceFile(const char* file_path) + { + //check if input file exists + FILE* input = fopen(mContext.inputFilePath.c_str(), "rb"); + if ( !input ) + return false; + + //Uppercase function identifier + std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); + + //Build header and cpp file path + std::string headerPath = getHeaderFilePath(file_path); + std::string sourcePath = file_path; + + //create c source file + FILE* fout = fopen(sourcePath.c_str(), "w"); + if ( !fout ) + { + fclose(input); + return false; + } + + //determine file properties + uint32_t fileSize = ra::filesystem::GetFileSize(input); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); + //long lastSegmentSize = fileSize%chunk_size; + //size_t numSegments = fileSize/chunk_size + (lastSegmentSize == 0 ? 0 : 1); + + //Build class name + std::string className = getClassName(); + + //Build function + std::string getterFunctionName = getGetterFunctionName(); + + //Build FileManager class template + std::string manager = mContext.managerHeaderFilename; + + //write c file heading + fprintf(fout, "%s", getHeaderTemplate().c_str()); + fprintf(fout, "#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n"); + fprintf(fout, "#define _CRT_SECURE_NO_WARNINGS\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, "#include \"%s\"\n", mContext.headerFilename.c_str()); + fprintf(fout, "#include // for malloc\n"); + fprintf(fout, "#include // for memset\n"); + fprintf(fout, "#include // for fopen\n"); + + fprintf(fout, "static %s %s_file = { 0 };\n", mContext.baseClass.c_str(), functionIdentifier.c_str()); + fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + + fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " return true;\n"); + fprintf(fout, " static const unsigned char static_buffer[] = {\n"); + + //create buffer for each chunks from input buffer + int numLinePrinted = 0; + unsigned char* buffer = new unsigned char[getContext().chunkSize]; + while ( !feof(input) ) + { + //read a chunk of the file + size_t readSize = fread(buffer, 1, getContext().chunkSize, input); + + bool isLastChunk = !(readSize == getContext().chunkSize); + + if ( readSize > 0 ) + { + if ( numLinePrinted > 0 ) + { + //end previous line + fprintf(fout, ",\n"); + } + + //output + fprintf(fout, " %s", ra::code::cpp::ToCppCharactersArray(buffer, readSize).c_str()); + numLinePrinted++; + } + + //end the array. all the file content is printed + if ( isLastChunk ) + { + fprintf(fout, "\n"); + fprintf(fout, " };\n"); + } + } + delete[] buffer; + buffer = NULL; + + //write c source file footer + fprintf(fout, "\n"); + fprintf(fout, " %s_file.buffer = static_buffer;\n", functionIdentifier.c_str()); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + + fprintf(fout, "\n"); + + fprintf(fout, "void %s_free()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " %s_file.buffer = NULL;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "bool %s_save(const char* path)\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( !%s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " return false;\n"); + fprintf(fout, " FILE* f = fopen(path, \"wb\");\n"); + fprintf(fout, " if ( !f )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " size_t write_size = fwrite(%s_file.buffer, 1, %s_file.size, f);\n", functionIdentifier.c_str(), functionIdentifier.c_str()); + fprintf(fout, " fclose(f);\n"); + fprintf(fout, " if ( write_size != %s_file.size )\n", functionIdentifier.c_str()); + fprintf(fout, " return false;\n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "inline void %s_init()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " // remember we already initialized\n"); + fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str()); + fprintf(fout, " return;\n"); + fprintf(fout, " %s_initialized = true;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + fprintf(fout, " // initialize\n"); + fprintf(fout, " %s* file = &%s_file;\n", mContext.baseClass.c_str(), functionIdentifier.c_str()); + fprintf(fout, " file->size = %uULL;\n", fileSize); + fprintf(fout, " file->file_name = \"%s\";\n", getFileClassFileName().c_str()); + fprintf(fout, " file->file_path = \"%s\";\n", getFileClassFilePath().c_str()); + fprintf(fout, " file->buffer = NULL;\n"); + fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); + fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); + fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " %s_init();\n", functionIdentifier.c_str()); + fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + + if ( mContext.registerFiles ) + { + std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + fprintf(fout, "%s", fileManagerTemplate.c_str()); + } + + fclose(input); + fclose(fout); + + return true; + } + }; //bin2cpp \ No newline at end of file diff --git a/src/bin2cpp/ArrayGenerator.h b/src/bin2cpp/ArrayGenerator.h index a0f15d5..46ec570 100644 --- a/src/bin2cpp/ArrayGenerator.h +++ b/src/bin2cpp/ArrayGenerator.h @@ -41,6 +41,7 @@ namespace bin2cpp virtual ~ArrayGenerator(); virtual const char * getName() const; virtual bool createCppSourceFile(const char * cpp_file_path); + virtual bool createCSourceFile(const char * cpp_file_path); virtual bool printFileContent(); }; diff --git a/src/bin2cpp/BaseGenerator.cpp b/src/bin2cpp/BaseGenerator.cpp index c98dfdd..b96f99d 100755 --- a/src/bin2cpp/BaseGenerator.cpp +++ b/src/bin2cpp/BaseGenerator.cpp @@ -433,7 +433,7 @@ namespace bin2cpp fprintf(header, " size_t size;\n"); fprintf(header, " const char* file_name;\n"); fprintf(header, " const char* file_path;\n"); - fprintf(header, " unsigned char* buffer;\n"); + fprintf(header, " const unsigned char* buffer;\n"); fprintf(header, " bin2c_load_func load;\n"); fprintf(header, " bin2c_free_func unload;\n"); fprintf(header, " bin2c_save_func save;\n"); diff --git a/src/bin2cpp/SegmentGenerator.cpp b/src/bin2cpp/SegmentGenerator.cpp index ffa90f2..d413b23 100755 --- a/src/bin2cpp/SegmentGenerator.cpp +++ b/src/bin2cpp/SegmentGenerator.cpp @@ -140,7 +140,7 @@ namespace bin2cpp delete[] buffer; buffer = NULL; - //write cpp file footer + //write cpp source file footer fprintf(cpp, " }\n"); fprintf(cpp, "%s", getSaveMethodTemplate().c_str()); fprintf(cpp, " private:\n"); @@ -253,6 +253,7 @@ namespace bin2cpp delete[] buffer; buffer = NULL; + //write c source file footer fprintf(fout, "\n"); fprintf(fout, " %s_file.buffer = local_buffer;\n", functionIdentifier.c_str()); fprintf(fout, " return true;\n"); diff --git a/src/bin2cpp/StringGenerator.cpp b/src/bin2cpp/StringGenerator.cpp index 77aaa0a..064d0a2 100755 --- a/src/bin2cpp/StringGenerator.cpp +++ b/src/bin2cpp/StringGenerator.cpp @@ -143,7 +143,7 @@ namespace bin2cpp delete[] buffer; buffer = NULL; - //write cpp file footer + //write cpp source file footer fprintf(cpp, " return buffer;\n"); fprintf(cpp, " }\n"); fprintf(cpp, "%s", getSaveMethodTemplate().c_str()); @@ -162,4 +162,170 @@ namespace bin2cpp return true; } + bool StringGenerator::createCSourceFile(const char* file_path) + { + //check if input file exists + FILE* input = fopen(mContext.inputFilePath.c_str(), "rb"); + if ( !input ) + return false; + + //Uppercase function identifier + std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); + + //Build header and cpp file path + std::string headerPath = getHeaderFilePath(file_path); + std::string sourcePath = file_path; + + //create c source file + FILE* fout = fopen(sourcePath.c_str(), "w"); + if ( !fout ) + { + fclose(input); + return false; + } + + //determine file properties + uint32_t fileSize = ra::filesystem::GetFileSize(input); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); + //long lastSegmentSize = fileSize%chunk_size; + //size_t numSegments = fileSize/chunk_size + (lastSegmentSize == 0 ? 0 : 1); + + //Build class name + std::string className = getClassName(); + + //Build function + std::string getterFunctionName = getGetterFunctionName(); + + //Build FileManager class template + std::string manager = mContext.managerHeaderFilename; + + //write c file heading + fprintf(fout, "%s", getHeaderTemplate().c_str()); + fprintf(fout, "#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n"); + fprintf(fout, "#define _CRT_SECURE_NO_WARNINGS\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, "#include \"%s\"\n", mContext.headerFilename.c_str()); + fprintf(fout, "#include // for malloc\n"); + fprintf(fout, "#include // for memset\n"); + fprintf(fout, "#include // for fopen\n"); + + fprintf(fout, "static %s %s_file = { 0 };\n", mContext.baseClass.c_str(), functionIdentifier.c_str()); + fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + + fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " return true;\n"); + fprintf(fout, "\n"); + fprintf(fout, " static const char * static_buffer = ""\n"); + + //create buffer for each chunks from input buffer + int numLinePrinted = 0; + unsigned char* buffer = new unsigned char[getContext().chunkSize]; + while ( !feof(input) ) + { + //read a chunk of the file + size_t readSize = fread(buffer, 1, getContext().chunkSize, input); + + bool isLastChunk = !(readSize == getContext().chunkSize); + + if ( readSize > 0 ) + { + if ( numLinePrinted > 0 ) + { + //end previous line + fprintf(fout, "\n"); + } + + //convert to cpp string + std::string cppEncoder; + switch ( getContext().cppEncoder ) + { + case CPP_ENCODER_HEX: + cppEncoder = ra::code::cpp::ToHexString(buffer, readSize); + break; + case CPP_ENCODER_OCT: + default: + cppEncoder = ra::code::cpp::ToOctString(buffer, readSize, false); + break; + }; + + //output + fprintf(fout, " \"%s\"", cppEncoder.c_str()); + numLinePrinted++; + } + + //end the string if last chunk printed + if ( isLastChunk ) + { + fprintf(fout, ";\n"); + } + } + delete[] buffer; + buffer = NULL; + + //write c source file footer + fprintf(fout, "\n"); + fprintf(fout, " %s_file.buffer = static_buffer;\n", functionIdentifier.c_str()); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + + fprintf(fout, "\n"); + + fprintf(fout, "void %s_free()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " %s_file.buffer = NULL;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "bool %s_save(const char* path)\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( !%s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " return false;\n"); + fprintf(fout, " FILE* f = fopen(path, \"wb\");\n"); + fprintf(fout, " if ( !f )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " size_t write_size = fwrite(%s_file.buffer, 1, %s_file.size, f);\n", functionIdentifier.c_str(), functionIdentifier.c_str()); + fprintf(fout, " fclose(f);\n"); + fprintf(fout, " if ( write_size != %s_file.size )\n", functionIdentifier.c_str()); + fprintf(fout, " return false;\n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "inline void %s_init()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " // remember we already initialized\n"); + fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str()); + fprintf(fout, " return;\n"); + fprintf(fout, " %s_initialized = true;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + fprintf(fout, " // initialize\n"); + fprintf(fout, " %s* file = &%s_file;\n", mContext.baseClass.c_str(), functionIdentifier.c_str()); + fprintf(fout, " file->size = %uULL;\n", fileSize); + fprintf(fout, " file->file_name = \"%s\";\n", getFileClassFileName().c_str()); + fprintf(fout, " file->file_path = \"%s\";\n", getFileClassFilePath().c_str()); + fprintf(fout, " file->buffer = NULL;\n"); + fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); + fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); + fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " %s_init();\n", functionIdentifier.c_str()); + fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + + if ( mContext.registerFiles ) + { + std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + fprintf(fout, "%s", fileManagerTemplate.c_str()); + } + + fclose(input); + fclose(fout); + + return true; + } + }; //bin2cpp \ No newline at end of file diff --git a/src/bin2cpp/StringGenerator.h b/src/bin2cpp/StringGenerator.h index 9d84551..f3dda2f 100644 --- a/src/bin2cpp/StringGenerator.h +++ b/src/bin2cpp/StringGenerator.h @@ -40,6 +40,7 @@ namespace bin2cpp virtual ~StringGenerator(); virtual const char * getName() const; virtual bool createCppSourceFile(const char * cpp_file_path); + virtual bool createCSourceFile(const char* file_path); }; }; //bin2cpp diff --git a/src/bin2cpp/Win32ResourceGenerator.cpp b/src/bin2cpp/Win32ResourceGenerator.cpp index 5db6091..5b2f71e 100755 --- a/src/bin2cpp/Win32ResourceGenerator.cpp +++ b/src/bin2cpp/Win32ResourceGenerator.cpp @@ -90,6 +90,10 @@ namespace bin2cpp //write cpp file heading fprintf(cpp, "%s", getHeaderTemplate().c_str()); fprintf(cpp, "#include \"%s\"\n", mContext.headerFilename.c_str() ); + fprintf(cpp, "#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n"); + fprintf(cpp, "#define _CRT_SECURE_NO_WARNINGS\n"); + fprintf(cpp, "#endif\n"); + fprintf(cpp, "\n"); fprintf(cpp, "#include \n"); fprintf(cpp, "#include \n"); fprintf(cpp, "#include //for ofstream\n"); @@ -187,11 +191,201 @@ namespace bin2cpp return true; } + bool Win32ResourceGenerator::createCSourceFile(const char* file_path) + { + bool resourceFileSuccess = createResourceFile(file_path); + if ( !resourceFileSuccess ) + return false; + + //check if input file exists + FILE* input = fopen(mContext.inputFilePath.c_str(), "rb"); + if ( !input ) + return false; + + //Uppercase function identifier + std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); + + //Build header and cpp file path + std::string headerPath = getHeaderFilePath(file_path); + std::string sourcePath = file_path; + + //create c source file + FILE* fout = fopen(sourcePath.c_str(), "w"); + if ( !fout ) + { + fclose(input); + return false; + } + + //determine file properties + uint32_t fileSize = ra::filesystem::GetFileSize(input); + std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str()); + //long lastSegmentSize = fileSize%chunk_size; + //size_t numSegments = fileSize/chunk_size + (lastSegmentSize == 0 ? 0 : 1); + + //Build class name + std::string className = getClassName(); + + //Build function + std::string getterFunctionName = getGetterFunctionName(); + + //Build FileManager class template + std::string manager = mContext.managerHeaderFilename; + + //write c file heading + fprintf(fout, "%s", getHeaderTemplate().c_str()); + fprintf(fout, "#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n"); + fprintf(fout, "#define _CRT_SECURE_NO_WARNINGS\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, "\n"); + fprintf(fout, "#include \"%s\"\n", mContext.headerFilename.c_str()); + fprintf(fout, "#include // for malloc\n"); + fprintf(fout, "#include // for memset\n"); + fprintf(fout, "#include // for fopen\n"); + fprintf(fout, "\n"); + fprintf(fout, "#ifndef WIN32_LEAN_AND_MEAN\n"); + fprintf(fout, "#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, "#include \n"); + fprintf(fout, "\n"); + fprintf(fout, "#include //for EnumProcessModules()\n"); + fprintf(fout, "#pragma comment( lib, \"psapi.lib\" )\n"); + fprintf(fout, "\n"); + fprintf(fout, "static %s %s_file = { 0 };\n", mContext.baseClass.c_str(), functionIdentifier.c_str()); + fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); + fprintf(fout, "typedef struct %s\n", getLocalInfoStructName().c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " HANDLE hProcess;\n"); + fprintf(fout, " HMODULE hModule;\n"); + fprintf(fout, " HRSRC hResourceInfoBlock;\n"); + fprintf(fout, " HGLOBAL hResHandle;\n"); + fprintf(fout, " DWORD dwBufferSize;\n"); + fprintf(fout, "} %s;\n", getLocalInfoStructName().c_str()); + fprintf(fout, "static %s %s_info = { 0 };\n", getLocalInfoStructName().c_str(), functionIdentifier.c_str()); + fprintf(fout, "\n"); + + fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " return true;\n"); + fprintf(fout, "\n"); + fprintf(fout, " %s* info = &%s_info;\n", getLocalInfoStructName().c_str(), functionIdentifier.c_str()); + + fprintf(fout, " //Get a handle to this process\n"); + fprintf(fout, " info->hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId() );\n"); + fprintf(fout, " if (info->hProcess)\n"); + fprintf(fout, " {\n"); + fprintf(fout, " //Find the main HMODULE of the process\n"); + fprintf(fout, " DWORD cbNeeded;\n"); + fprintf(fout, " if ( EnumProcessModules( info->hProcess, &info->hModule, sizeof(info->hModule), &cbNeeded) )\n"); + fprintf(fout, " {\n"); + fprintf(fout, " //Retrieve the resource\n"); + fprintf(fout, " info->hResourceInfoBlock = FindResource(info->hModule, L\"%s\", L\"CUSTOM\");\n", getRandomIdentifier(mContext.inputFilePath.c_str()).c_str()); + fprintf(fout, " if (info->hResourceInfoBlock)\n"); + fprintf(fout, " {\n"); + fprintf(fout, " info->hResHandle = LoadResource(info->hModule, info->hResourceInfoBlock);\n"); + fprintf(fout, " if (info->hResHandle)\n"); + fprintf(fout, " {\n"); + fprintf(fout, " %s_file.buffer = (const unsigned char *)LockResource(info->hResHandle);\n", functionIdentifier.c_str()); + fprintf(fout, " info->dwBufferSize = SizeofResource(info->hModule, info->hResourceInfoBlock);\n"); + fprintf(fout, " return true;\n"); + fprintf(fout, " }\n"); + fprintf(fout, " }\n"); + fprintf(fout, " }\n"); + fprintf(fout, " }\n"); + fprintf(fout, " \n"); + fprintf(fout, " return false;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + + fprintf(fout, "void %s_free()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( %s_file.buffer == NULL)\n", functionIdentifier.c_str()); + fprintf(fout, " return;\n"); + fprintf(fout, " %s* info = &%s_info;\n", getLocalInfoStructName().c_str(), functionIdentifier.c_str()); + fprintf(fout, " if (info->hResHandle)\n"); + fprintf(fout, " {\n"); + fprintf(fout, " FreeResource(info->hResHandle);\n"); + fprintf(fout, " info->hResHandle = NULL;\n"); + fprintf(fout, " %s_file.buffer = NULL;\n", functionIdentifier.c_str()); + fprintf(fout, " info->dwBufferSize = 0;\n"); + fprintf(fout, " }\n"); + fprintf(fout, " info->hResourceInfoBlock = NULL;\n"); + fprintf(fout, " info->hModule = NULL;\n"); + fprintf(fout, " if (info->hProcess)\n"); + fprintf(fout, " {\n"); + fprintf(fout, " CloseHandle(info->hProcess);\n"); + fprintf(fout, " info->hProcess = NULL;\n"); + fprintf(fout, " }\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + + fprintf(fout, "bool %s_save(const char* path)\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( !%s_file.buffer )\n", functionIdentifier.c_str()); + fprintf(fout, " return false;\n"); + fprintf(fout, " FILE* f = fopen(path, \"wb\");\n"); + fprintf(fout, " if ( !f )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " size_t write_size = fwrite(%s_file.buffer, 1, %s_file.size, f);\n", functionIdentifier.c_str(), functionIdentifier.c_str()); + fprintf(fout, " fclose(f);\n"); + fprintf(fout, " if ( write_size != %s_file.size )\n", functionIdentifier.c_str()); + fprintf(fout, " return false;\n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + + fprintf(fout, "inline void %s_init()\n", functionIdentifier.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " // remember we already initialized\n"); + fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str()); + fprintf(fout, " return;\n"); + fprintf(fout, " %s_initialized = true;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + fprintf(fout, " // initialize\n"); + fprintf(fout, " %s* file = &%s_file;\n", mContext.baseClass.c_str(), functionIdentifier.c_str()); + fprintf(fout, " file->size = %uULL;\n", fileSize); + fprintf(fout, " file->file_name = \"%s\";\n", getFileClassFileName().c_str()); + fprintf(fout, " file->file_path = \"%s\";\n", getFileClassFilePath().c_str()); + fprintf(fout, " file->buffer = NULL;\n"); + fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); + fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); + fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + + fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " %s_init();\n", functionIdentifier.c_str()); + fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); + fprintf(fout, "}\n"); + + if ( mContext.registerFiles ) + { + std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + fprintf(fout, "%s", fileManagerTemplate.c_str()); + } + + fclose(input); + fclose(fout); + + return true; + } + std::string Win32ResourceGenerator::getResourceFilePath(const char * cpp_file_path) { //Build header file path std::string resourcePath = cpp_file_path; - ra::strings::Replace(resourcePath, ".cpp", ".rc"); + switch ( mContext.code ) + { + default: + case CODE_GENERATION_CPP: + ra::strings::Replace(resourcePath, ".cpp", ".rc"); + break; + case CODE_GENERATION_C: + ra::strings::Replace(resourcePath, ".c", ".rc"); + break; + }; return resourcePath; } @@ -247,4 +441,11 @@ namespace bin2cpp return false; // not supported } + std::string Win32ResourceGenerator::getLocalInfoStructName() + { + std::string name = ra::strings::Lowercase(mContext.functionIdentifier); + name = ra::strings::Uppercase(name) + "_INFO"; + return name; + } + }; //bin2cpp \ No newline at end of file diff --git a/src/bin2cpp/Win32ResourceGenerator.h b/src/bin2cpp/Win32ResourceGenerator.h index 68b4a0d..a5e29ce 100644 --- a/src/bin2cpp/Win32ResourceGenerator.h +++ b/src/bin2cpp/Win32ResourceGenerator.h @@ -40,11 +40,13 @@ namespace bin2cpp virtual ~Win32ResourceGenerator(); virtual const char * getName() const; virtual bool createCppSourceFile(const char * cpp_file_path); + virtual bool createCSourceFile(const char* file_path); virtual bool printFileContent(); protected: virtual std::string getResourceFilePath(const char * cpp_file_path); virtual bool createResourceFile(const char * cpp_file_path); virtual std::string getRandomIdentifier(const char * cpp_file_path); + virtual std::string getLocalInfoStructName(); }; }; //bin2cpp diff --git a/src/bin2cpp/bin2cpp.samples.txt b/src/bin2cpp/bin2cpp.samples.txt index f6c68b7..bf626dd 100644 --- a/src/bin2cpp/bin2cpp.samples.txt +++ b/src/bin2cpp/bin2cpp.samples.txt @@ -1,4 +1,9 @@ ---file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c +# C code examples: +--file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=array +--file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=segment +--file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=string +--file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=win32 + --file=.\generated_files\testText1000\testText1000.bin --output=.\generated_files\testText1000 --headerfile=_testText1000.h --identifier=testText1000 --chunksize=450 --override --file=.\generated_files\testSequential1000\testSequential1000.bin --output=.\generated_files\testSequential1000 --headerfile=_testSequential1000.h --identifier=testSequential1000 --chunksize=180 --override --file=..\..\test\bin2cpp_unittest\generated_files\testIssue28\testIssue28.bin --output=..\..\test\bin2cpp_unittest\generated_files\testIssue28 --headerfile=_testIssue28.h --identifier=testIssue28 --managerfile=FileManager.h --override From 2f61bc5e0334f8626956835e8363f3c000524748 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Fri, 16 May 2025 18:45:22 -0400 Subject: [PATCH 09/25] Implemented register files support for C code generators. --- src/bin2cpp/ArrayGenerator.cpp | 20 ++- src/bin2cpp/BaseGenerator.cpp | 1 + src/bin2cpp/ManagerGenerator.cpp | 217 +++++++++++++++++++++++++ src/bin2cpp/ManagerGenerator.h | 2 + src/bin2cpp/SegmentGenerator.cpp | 26 ++- src/bin2cpp/StringGenerator.cpp | 14 ++ src/bin2cpp/Win32ResourceGenerator.cpp | 14 ++ src/bin2cpp/bin2cpp.samples.txt | 40 +++-- 8 files changed, 305 insertions(+), 29 deletions(-) diff --git a/src/bin2cpp/ArrayGenerator.cpp b/src/bin2cpp/ArrayGenerator.cpp index ca34592..49648b4 100644 --- a/src/bin2cpp/ArrayGenerator.cpp +++ b/src/bin2cpp/ArrayGenerator.cpp @@ -243,6 +243,12 @@ namespace bin2cpp fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); fprintf(fout, "\n"); + if ( mContext.registerFiles ) + { + fprintf(fout, "extern bool bin2c_filemanager_register_file(%s * file);\n", mContext.baseClass.c_str()); + fprintf(fout, "\n"); + } + fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); @@ -325,6 +331,14 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + + if ( mContext.registerFiles ) + { + fprintf(fout, " \n"); + fprintf(fout, " // register\n"); + fprintf(fout, " bin2c_filemanager_register_file(file);\n"); + } + fprintf(fout, "}\n"); fprintf(fout, "\n"); fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); @@ -333,12 +347,6 @@ namespace bin2cpp fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); fprintf(fout, "}\n"); - if ( mContext.registerFiles ) - { - std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); - fprintf(fout, "%s", fileManagerTemplate.c_str()); - } - fclose(input); fclose(fout); diff --git a/src/bin2cpp/BaseGenerator.cpp b/src/bin2cpp/BaseGenerator.cpp index b96f99d..58c2b34 100755 --- a/src/bin2cpp/BaseGenerator.cpp +++ b/src/bin2cpp/BaseGenerator.cpp @@ -438,6 +438,7 @@ namespace bin2cpp fprintf(header, " bin2c_free_func unload;\n"); fprintf(header, " bin2c_save_func save;\n"); fprintf(header, "} %s;\n", mContext.baseClass.c_str()); + fprintf(header, "typedef %s* %sPtr;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); fprintf(header, "#endif //%s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); fprintf(header, "%s* %s();\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); fprintf(header, "\n"); diff --git a/src/bin2cpp/ManagerGenerator.cpp b/src/bin2cpp/ManagerGenerator.cpp index 72a8126..36fff63 100644 --- a/src/bin2cpp/ManagerGenerator.cpp +++ b/src/bin2cpp/ManagerGenerator.cpp @@ -239,6 +239,223 @@ namespace bin2cpp return true; } + bool ManagerGenerator::createCHeaderFile(const char* file_path) + { + FILE* fout = fopen(file_path, "w"); + if ( !fout ) + return false; + + //define macro guard a macro matching the filename + std::string macroGuard; + macroGuard += getCppIncludeGuardMacroName(mContext.codeNamespace.c_str()); //prefix the custom namespace for the file manager + if ( !macroGuard.empty() ) + macroGuard += "_"; + macroGuard += getCppIncludeGuardMacroName(file_path); + + std::string classMacroGuardPrefix = getClassMacroGuardPrefix(); + std::string fileHeader = getHeaderTemplate(false); + + fprintf(fout, "%s", fileHeader.c_str()); + fprintf(fout, "#ifndef %s\n", macroGuard.c_str()); + fprintf(fout, "#define %s\n", macroGuard.c_str()); + fprintf(fout, "\n"); + fprintf(fout, "#include \n"); + fprintf(fout, "#include \n"); + fprintf(fout, "\n"); + fprintf(fout, "#ifndef %s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); + fprintf(fout, "#define %s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); + fprintf(fout, "typedef struct %s %s;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); + fprintf(fout, "typedef bool(*bin2c_load_func)();\n"); + fprintf(fout, "typedef void(*bin2c_free_func)();\n"); + fprintf(fout, "typedef bool(*bin2c_save_func)(const char*);\n"); + fprintf(fout, "typedef struct %s\n", mContext.baseClass.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " size_t size;\n"); + fprintf(fout, " const char* file_name;\n"); + fprintf(fout, " const char* file_path;\n"); + fprintf(fout, " const unsigned char* buffer;\n"); + fprintf(fout, " bin2c_load_func load;\n"); + fprintf(fout, " bin2c_free_func unload;\n"); + fprintf(fout, " bin2c_save_func save;\n"); + fprintf(fout, "} %s;\n", mContext.baseClass.c_str()); + fprintf(fout, "typedef %s* %sPtr;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); + fprintf(fout, "#endif //%s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); + fprintf(fout, "\n"); + fprintf(fout, "size_t bin2c_filemanager_get_file_count();\n"); + fprintf(fout, "bool bin2c_filemanager_register_file(%s* file);\n", mContext.baseClass.c_str()); + fprintf(fout, "const %s* bin2c_filemanager_get_file(size_t index);\n", mContext.baseClass.c_str()); + fprintf(fout, "bool bin2c_filemanager_save_files(const char* directory);\n"); + fprintf(fout, "\n"); + fprintf(fout, "#endif //%s\n", macroGuard.c_str()); + + fclose(fout); + + return true; + } + + bool ManagerGenerator::createCSourceFile(const char* file_path) + { + FILE* fout = fopen(file_path, "w"); + if ( !fout ) + return false; + + //Build header and cpp file path + std::string headerPath = getHeaderFilePath(file_path); + std::string sourcePath = file_path; + + std::string fileHeader = getHeaderTemplate(false); + + fprintf(fout, "%s", fileHeader.c_str()); + fprintf(fout, "#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n"); + fprintf(fout, "#define _CRT_SECURE_NO_WARNINGS\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, "\n"); + fprintf(fout, "#include \"%s\"\n", mContext.managerHeaderFilename.c_str()); + fprintf(fout, "#include // for malloc\n"); + fprintf(fout, "#include // for snprintf()\n"); + fprintf(fout, "#include // strlen\n"); + fprintf(fout, "#include // stat\n"); + fprintf(fout, "#include // errno, EEXIST\n"); + fprintf(fout, "#if defined(_WIN32)\n"); + fprintf(fout, "#include // _mkdir\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, "#if defined(_WIN32)\n"); + fprintf(fout, "#define portable_stat _stat\n"); + fprintf(fout, "#define portable_mkdir(path) _mkdir(path)\n"); + fprintf(fout, "#define PATH_SEPARATOR_CHAR '\\\\'\n"); + fprintf(fout, "#define PATH_SEPARATOR_STR \"\\\\\"\n"); + fprintf(fout, "#else\n"); + fprintf(fout, "#define portable_stat stat\n"); + fprintf(fout, "#define portable_mkdir(path) mkdir(path, 0755)\n"); + fprintf(fout, "#define PATH_SEPARATOR_CHAR '/'\n"); + fprintf(fout, "#define PATH_SEPARATOR_STR \"/\"\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, "\n"); + fprintf(fout, "#define BIN2C_MAX_PATH 32767\n"); + fprintf(fout, "\n"); + fprintf(fout, "static %s** registered_files = NULL;\n", mContext.baseClass.c_str()); + fprintf(fout, "static size_t registered_files_count = 0;\n"); + fprintf(fout, "\n"); + fprintf(fout, "size_t bin2c_filemanager_get_file_count()\n"); + fprintf(fout, "{\n"); + fprintf(fout, " return registered_files_count;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "bool bin2c_filemanager_register_file(%s* file)\n", mContext.baseClass.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " // allocate ram\n"); + fprintf(fout, " size_t new_ram_size = sizeof(%s**) * (registered_files_count + 1);\n", mContext.baseClass.c_str()); + fprintf(fout, " %s** tmp = NULL;\n", mContext.baseClass.c_str()); + fprintf(fout, " if ( registered_files == NULL )\n"); + fprintf(fout, " tmp = (%s**)malloc(new_ram_size);\n", mContext.baseClass.c_str()); + fprintf(fout, " else\n"); + fprintf(fout, " tmp = (%s**)realloc(registered_files, new_ram_size);\n", mContext.baseClass.c_str()); + fprintf(fout, " if ( tmp == NULL )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " \n"); + fprintf(fout, " registered_files = tmp;\n"); + fprintf(fout, " registered_files_count++;\n"); + fprintf(fout, " \n"); + fprintf(fout, " // insert\n"); + fprintf(fout, " registered_files[registered_files_count - 1] = file;\n"); + fprintf(fout, " \n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "const %s* bin2c_filemanager_get_file(size_t index)\n", mContext.baseClass.c_str()); + fprintf(fout, "{\n"); + fprintf(fout, " if ( index >= registered_files_count )\n"); + fprintf(fout, " return NULL;\n"); + fprintf(fout, " return registered_files[index];\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "static inline bool bin2c_filemanager_is_root_directory(const char* path)\n"); + fprintf(fout, "{\n"); + fprintf(fout, " if ( path == NULL && path[0] == '\0' )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, "#if defined(_WIN32)\n"); + fprintf(fout, " bool is_drive_letter = ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'));\n"); + fprintf(fout, " if ( (is_drive_letter && path[1] == ':' && path[2] == '\0') || // test for C:\n"); + fprintf(fout, " (is_drive_letter && path[1] == ':' && path[2] == PATH_SEPARATOR_CHAR && path[3] == '\0') ) // test for C:\\ \n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "#else\n"); + fprintf(fout, " if ( path[0] == PATH_SEPARATOR_CHAR )\n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "#endif\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "bool bin2c_filemanager_create_parent_directories(const char* file_path)\n"); + fprintf(fout, "{\n"); + fprintf(fout, " if ( file_path == NULL )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " char* accumulator = (char*)malloc(BIN2C_MAX_PATH);\n"); + fprintf(fout, " if ( accumulator == NULL )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " accumulator[0] = '\0';\n"); + fprintf(fout, " size_t length = strlen(file_path);\n"); + fprintf(fout, " for ( size_t i = 0; i < length; i++ )\n"); + fprintf(fout, " {\n"); + fprintf(fout, " if ( file_path[i] == PATH_SEPARATOR_CHAR && !(accumulator[0] == '\0') && !bin2c_filemanager_is_root_directory(accumulator) )\n"); + fprintf(fout, " {\n"); + fprintf(fout, " int ret = portable_mkdir(accumulator);\n"); + fprintf(fout, " if ( ret != 0 && errno != EEXIST )\n"); + fprintf(fout, " {\n"); + fprintf(fout, " free(accumulator);\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " }\n"); + fprintf(fout, " }\n"); + fprintf(fout, " \n"); + fprintf(fout, " // append\n"); + fprintf(fout, " char tmp[] = { file_path[i], '\0' };\n"); + fprintf(fout, " strcat(accumulator, tmp);\n"); + fprintf(fout, " }\n"); + fprintf(fout, " free(accumulator);\n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + fprintf(fout, "bool bin2c_filemanager_save_files(const char * directory)\n"); + fprintf(fout, "{\n"); + fprintf(fout, " if (directory == NULL)\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " char* path = (char*)malloc(BIN2C_MAX_PATH);\n"); + fprintf(fout, " if ( path == NULL )\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " path[0] = '\0';\n"); + fprintf(fout, " for(size_t i=0; i< registered_files_count; i++)\n"); + fprintf(fout, " {\n"); + fprintf(fout, " const Bin2cFile* f = bin2c_filemanager_get_file(i);\n"); + fprintf(fout, " if ( !f )\n"); + fprintf(fout, " {\n"); + fprintf(fout, " free(path);\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " }\n"); + fprintf(fout, " \n"); + fprintf(fout, " char path[32767] = { 0 };\n"); + fprintf(fout, " snprintf(path, sizeof(path), \"%%s%%c%%s\", directory, PATH_SEPARATOR_CHAR, f->file_path);\n"); + fprintf(fout, " \n"); + fprintf(fout, " if (!bin2c_filemanager_create_parent_directories(path))\n"); + fprintf(fout, " {\n"); + fprintf(fout, " free(path);\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " }\n"); + fprintf(fout, " bool saved = f->save(path);\n"); + fprintf(fout, " if (!saved)\n"); + fprintf(fout, " {\n"); + fprintf(fout, " free(path);\n"); + fprintf(fout, " return false;\n"); + fprintf(fout, " }\n"); + fprintf(fout, " }\n"); + fprintf(fout, " free(path);\n"); + fprintf(fout, " return true;\n"); + fprintf(fout, "}\n"); + fprintf(fout, "\n"); + + fclose(fout); + + return true; + } + bool ManagerGenerator::printFileContent() { return false; diff --git a/src/bin2cpp/ManagerGenerator.h b/src/bin2cpp/ManagerGenerator.h index 101e412..a6d7981 100644 --- a/src/bin2cpp/ManagerGenerator.h +++ b/src/bin2cpp/ManagerGenerator.h @@ -41,6 +41,8 @@ namespace bin2cpp virtual const char * getName() const; virtual bool createCppHeaderFile(const char* header_file_path); virtual bool createCppSourceFile(const char * cpp_file_path); + virtual bool createCHeaderFile(const char* file_path); + virtual bool createCSourceFile(const char* file_path); virtual bool printFileContent(); }; diff --git a/src/bin2cpp/SegmentGenerator.cpp b/src/bin2cpp/SegmentGenerator.cpp index d413b23..575133d 100755 --- a/src/bin2cpp/SegmentGenerator.cpp +++ b/src/bin2cpp/SegmentGenerator.cpp @@ -211,6 +211,12 @@ namespace bin2cpp fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); fprintf(fout, "\n"); + if ( mContext.registerFiles ) + { + fprintf(fout, "extern bool bin2c_filemanager_register_file(%s * file);\n", mContext.baseClass.c_str()); + fprintf(fout, "\n"); + } + fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); @@ -264,7 +270,7 @@ namespace bin2cpp fprintf(fout, "void %s_free()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); - fprintf(fout, " free(%s_file.buffer);\n", functionIdentifier.c_str()); + fprintf(fout, " free((unsigned char*)%s_file.buffer);\n", functionIdentifier.c_str()); fprintf(fout, " %s_file.buffer = NULL;\n", functionIdentifier.c_str()); fprintf(fout, "}\n"); fprintf(fout, "\n"); @@ -298,6 +304,14 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + + if ( mContext.registerFiles ) + { + fprintf(fout, " \n"); + fprintf(fout, " // register\n"); + fprintf(fout, " bin2c_filemanager_register_file(file);\n"); + } + fprintf(fout, "}\n"); fprintf(fout, "\n"); fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); @@ -306,11 +320,11 @@ namespace bin2cpp fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); fprintf(fout, "}\n"); - if ( mContext.registerFiles ) - { - std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); - fprintf(fout, "%s", fileManagerTemplate.c_str()); - } + //if ( mContext.registerFiles ) + //{ + // std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + // fprintf(fout, "%s", fileManagerTemplate.c_str()); + //} fclose(input); fclose(fout); diff --git a/src/bin2cpp/StringGenerator.cpp b/src/bin2cpp/StringGenerator.cpp index 064d0a2..a7e5589 100755 --- a/src/bin2cpp/StringGenerator.cpp +++ b/src/bin2cpp/StringGenerator.cpp @@ -213,6 +213,12 @@ namespace bin2cpp fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); fprintf(fout, "\n"); + if ( mContext.registerFiles ) + { + fprintf(fout, "extern bool bin2c_filemanager_register_file(%s * file);\n", mContext.baseClass.c_str()); + fprintf(fout, "\n"); + } + fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); @@ -308,6 +314,14 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + + if ( mContext.registerFiles ) + { + fprintf(fout, " \n"); + fprintf(fout, " // register\n"); + fprintf(fout, " bin2c_filemanager_register_file(file);\n"); + } + fprintf(fout, "}\n"); fprintf(fout, "\n"); fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); diff --git a/src/bin2cpp/Win32ResourceGenerator.cpp b/src/bin2cpp/Win32ResourceGenerator.cpp index 5b2f71e..26165c6 100755 --- a/src/bin2cpp/Win32ResourceGenerator.cpp +++ b/src/bin2cpp/Win32ResourceGenerator.cpp @@ -264,6 +264,12 @@ namespace bin2cpp fprintf(fout, "static %s %s_info = { 0 };\n", getLocalInfoStructName().c_str(), functionIdentifier.c_str()); fprintf(fout, "\n"); + if ( mContext.registerFiles ) + { + fprintf(fout, "extern bool bin2c_filemanager_register_file(%s * file);\n", mContext.baseClass.c_str()); + fprintf(fout, "\n"); + } + fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str()); @@ -351,6 +357,14 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + + if ( mContext.registerFiles ) + { + fprintf(fout, " \n"); + fprintf(fout, " // register\n"); + fprintf(fout, " bin2c_filemanager_register_file(file);\n"); + } + fprintf(fout, "}\n"); fprintf(fout, "\n"); diff --git a/src/bin2cpp/bin2cpp.samples.txt b/src/bin2cpp/bin2cpp.samples.txt index bf626dd..7343172 100644 --- a/src/bin2cpp/bin2cpp.samples.txt +++ b/src/bin2cpp/bin2cpp.samples.txt @@ -4,6 +4,29 @@ --file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=string --file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=win32 +--file=..\..\test\bin2cpp_unittest\generated_files\testRandom1\testRandom1.bin" --output=..\..\test\bin2cpp_unittest\generated_files\testRandom1 --headerfile=_testRandom1_C.h --registerfile + +--file=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C\testFileManager.1.bin --output=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C --headerfile=_testFileManager.1.h --identifier=testFileManager1_c --managerfile=filemanager.h --override --code=c +--file=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C\testFileManager.2.bin --output=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C --headerfile=_testFileManager.2.h --identifier=testFileManager2_c --registerfile --override --code=c + +--dir=..\..\..\samples\demo_website\www --output=..\..\temp --code=c +--dir=..\..\..\samples\demo_website\www --output=..\..\temp --code=c --managerfile=www-file-manager.h + + + +# CPP code examples: +--dir=..\..\..\samples\demo_website\www --output=..\..\temp --managerfile=PagesFileManager.h --namespace=myblog --keepdirs +--dir=..\..\..\samples\demo_website\www --output=..\..\temp --dirincludefilter="*\static\*.css:*.jpg" +--dir=..\..\..\samples\demo_website\www --output=..\..\temp --dirincludefilter="*\static\*.css:*.jpg" --direxcludefilter="*\light-mode.css" +--dir=..\..\..\samples\demo_website\www --output=..\..\temp --direxcludefilter="*.html" + +--file=..\..\test\bin2cpp_unittest\generated_files\testText1000\testText1000.bin --output=..\..\temp --override +--noheader --dir=..\..\test\bin2cpp_unittest\generated_files\testIssue56a\input_files --output=..\..\test\bin2cpp_unittest\generated_files\testIssue56a\compiled_sources --chunksize=200 --managerfile=FileManager56a.h --registerfile --namespace=issue56a --override +--plainoutput --chunksize=9999 --file=..\..\test\bin2cpp_unittest\generated_files\testSequential1000\testSequential1000.bin + + + +# old code examples: --file=.\generated_files\testText1000\testText1000.bin --output=.\generated_files\testText1000 --headerfile=_testText1000.h --identifier=testText1000 --chunksize=450 --override --file=.\generated_files\testSequential1000\testSequential1000.bin --output=.\generated_files\testSequential1000 --headerfile=_testSequential1000.h --identifier=testSequential1000 --chunksize=180 --override --file=..\..\test\bin2cpp_unittest\generated_files\testIssue28\testIssue28.bin --output=..\..\test\bin2cpp_unittest\generated_files\testIssue28 --headerfile=_testIssue28.h --identifier=testIssue28 --managerfile=FileManager.h --override @@ -20,25 +43,8 @@ --dir=..\..\test\bin2cpp_unittest\generated_files\testIssue56b\input_files\www --output=..\..\test\bin2cpp_unittest\generated_files\testIssue56b\generated_sources --namespace=issue56b --override --dir=..\..\test\bin2cpp_unittest\generated_files\testKeepDirectories\input_files\www --output=..\..\test\bin2cpp_unittest\generated_files\testKeepDirectories\generated_sources --override --keepdirs ---dir=..\..\..\samples\demo_website\www --output=..\..\temp --managerfile=PagesFileManager.h --namespace=myblog --keepdirs ---dir=..\..\..\samples\demo_website\www --output=..\..\temp --dirincludefilter="*\static\*.css:*.jpg" ---dir=..\..\..\samples\demo_website\www --output=..\..\temp --dirincludefilter="*\static\*.css:*.jpg" --direxcludefilter="*\light-mode.css" ---dir=..\..\..\samples\demo_website\www --output=..\..\temp --direxcludefilter="*.html" - -Bug: ---dir=..\..\..\samples\demo_website\www --output=..\..\temp --dirincludefilter="*.old" ---file=..\..\..\samples\demo_website\www\index.html.old --output=..\..\temp - - --file=D:\Temp\bin2cpp\issue51\input_files\IMG_0001.jpg --output=D:\Temp\bin2cpp\issue51\generated_sources --headerfile="IMG_0001.h" --identifier=testIssue51 --namespace=testIssue51 --managerfile=FileManager51.h --override --reportedfilepath=foo\bar\IMG_0001.h --dir=D:\Temp\bin2cpp\testIssue56b\input_files\www --output=D:\Temp\bin2cpp\testIssue56b\generated_sources --namespace=testIssue51 --managerfile=FileManager51.h --override --file=..\..\test\bin2cpp_unittest\generated_files\testSequential1000\testSequential1000.bin --plainoutput --chunksize=50 --managerfile=MyManager.h --output=generated_files --override - ---file=..\..\test\bin2cpp_unittest\generated_files\testText1000\testText1000.bin --output=. --override - ---noheader --dir=..\..\test\bin2cpp_unittest\generated_files\testIssue56a\input_files --output=..\..\test\bin2cpp_unittest\generated_files\testIssue56a\compiled_sources --chunksize=200 --managerfile=FileManager56a.h --registerfile --namespace=issue56a --override - - ---plainoutput --chunksize=9999 --file=..\..\test\bin2cpp_unittest\generated_files\testSequential1000\testSequential1000.bin From 1c0b7772b33f7b3456335164c08ae493b42297db Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sat, 17 May 2025 08:31:14 -0400 Subject: [PATCH 10/25] Updaed samples file for more examples. --- src/bin2cpp/bin2cpp.samples.txt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/bin2cpp/bin2cpp.samples.txt b/src/bin2cpp/bin2cpp.samples.txt index 7343172..e020ac3 100644 --- a/src/bin2cpp/bin2cpp.samples.txt +++ b/src/bin2cpp/bin2cpp.samples.txt @@ -1,17 +1,25 @@ # C code examples: + +Test all generators --file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=array --file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=segment --file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=string --file=..\..\test\bin2cpp_unittest\generated_files\testHtml100000\testHtml100000.bin --output=..\..\test\bin2cpp_unittest\generated_files\testHtml100000 --headerfile=_testHtml100000_C.h --override --code=c --generator=win32 ---file=..\..\test\bin2cpp_unittest\generated_files\testRandom1\testRandom1.bin" --output=..\..\test\bin2cpp_unittest\generated_files\testRandom1 --headerfile=_testRandom1_C.h --registerfile - +Test for: + * Segment C generator + * filemanager + * registerfile --file=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C\testFileManager.1.bin --output=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C --headerfile=_testFileManager.1.h --identifier=testFileManager1_c --managerfile=filemanager.h --override --code=c --file=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C\testFileManager.2.bin --output=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C --headerfile=_testFileManager.2.h --identifier=testFileManager2_c --registerfile --override --code=c +Test directories: --dir=..\..\..\samples\demo_website\www --output=..\..\temp --code=c --dir=..\..\..\samples\demo_website\www --output=..\..\temp --code=c --managerfile=www-file-manager.h +Test for namespace: +--file=..\..\test\bin2cpp_unittest\generated_files\testNamespace_C\testNamespace_C.bin --output=..\..\test\bin2cpp_unittest\generated_files\testNamespace_C --headerfile=testNamespace_C.h --identifier=testNamespace_C --managerfile=filemanager.h --override --code=c --namespace=foobar + # CPP code examples: From f223179d703e847899dbb377f75ea26dc42616bb Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sat, 17 May 2025 08:34:31 -0400 Subject: [PATCH 11/25] Implemented `--registerfile` command support for C generated code. --- src/bin2cpp/ArrayGenerator.cpp | 18 ++++++------- src/bin2cpp/BaseGenerator.cpp | 37 +++++++++++++++++++++++++- src/bin2cpp/BaseGenerator.h | 4 ++- src/bin2cpp/ManagerGenerator.cpp | 11 ++++++++ src/bin2cpp/SegmentGenerator.cpp | 22 +++++---------- src/bin2cpp/StringGenerator.cpp | 16 ++++------- src/bin2cpp/Win32ResourceGenerator.cpp | 16 ++++------- 7 files changed, 75 insertions(+), 49 deletions(-) diff --git a/src/bin2cpp/ArrayGenerator.cpp b/src/bin2cpp/ArrayGenerator.cpp index 49648b4..cdd5ff5 100644 --- a/src/bin2cpp/ArrayGenerator.cpp +++ b/src/bin2cpp/ArrayGenerator.cpp @@ -139,7 +139,7 @@ namespace bin2cpp fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str()); if (mContext.registerFiles) { - std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + std::string fileManagerTemplate = getCppFileManagerRegistrationImplementationTemplate(); fprintf(cpp, "%s", fileManagerTemplate.c_str()); } fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str()); @@ -199,7 +199,7 @@ namespace bin2cpp if ( !input ) return false; - //Uppercase function identifier + //Lowercase function identifier std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); //Build header and cpp file path @@ -243,11 +243,8 @@ namespace bin2cpp fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); fprintf(fout, "\n"); - if ( mContext.registerFiles ) - { - fprintf(fout, "extern bool bin2c_filemanager_register_file(%s * file);\n", mContext.baseClass.c_str()); - fprintf(fout, "\n"); - } + // File registration predeclaration code + fprintf(fout, "%s", getCFileManagerRegistrationPredeclarationTemplate().c_str()); fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); @@ -331,14 +328,12 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); - if ( mContext.registerFiles ) { fprintf(fout, " \n"); - fprintf(fout, " // register\n"); + fprintf(fout, " // register when loaded if static initialisation does not work\n"); fprintf(fout, " bin2c_filemanager_register_file(file);\n"); } - fprintf(fout, "}\n"); fprintf(fout, "\n"); fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); @@ -347,6 +342,9 @@ namespace bin2cpp fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); fprintf(fout, "}\n"); + // File registration implementation code + fprintf(fout, "%s", getCFileManagerRegistrationImplementationTemplate().c_str()); + fclose(input); fclose(fout); diff --git a/src/bin2cpp/BaseGenerator.cpp b/src/bin2cpp/BaseGenerator.cpp index 58c2b34..7b96007 100755 --- a/src/bin2cpp/BaseGenerator.cpp +++ b/src/bin2cpp/BaseGenerator.cpp @@ -166,7 +166,7 @@ namespace bin2cpp return output; } - std::string BaseGenerator::getFileManagerRegistrationTemplate() + std::string BaseGenerator::getCppFileManagerRegistrationImplementationTemplate() { if (!mContext.registerFiles) return std::string(); @@ -181,6 +181,41 @@ namespace bin2cpp return output; } + std::string BaseGenerator::getCFileManagerRegistrationPredeclarationTemplate() + { + if ( !mContext.registerFiles ) + return std::string(); + + std::string output; + output << "extern bool bin2c_filemanager_register_file(" << mContext.baseClass << " * file); \n"; + output << "\n"; + return output; + } + + std::string BaseGenerator::getCFileManagerRegistrationImplementationTemplate() + { + if ( !mContext.registerFiles ) + return std::string(); + + //Lowercase function identifier + std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); + + std::string output; + output << "#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) // GCC 4.0+ required, Clang supports it by default\n"; + output << "__attribute__((constructor))\n"; + output << "#endif\n"; + output << "void bin2c_register_file_static_init_" << functionIdentifier << "(void)\n"; + output << "{\n"; + output << " " << mContext.baseClass << "* this_file = bin2c_get_file_" << functionIdentifier << "();\n"; + output << " bin2c_filemanager_register_file(this_file);\n"; + output << "}\n"; + output << "#if _MSC_VER >= 1920 // Visual Studio 2019 or later\n"; + output << "#pragma section(\".CRT$XCU\", read)\n"; + output << "__declspec(allocate(\".CRT$XCU\")) void (*init_ptr_" << functionIdentifier << ")(void) = bin2c_register_file_static_init_" << functionIdentifier << ";\n"; + output << "#endif\n"; + return output; + } + std::string BaseGenerator::getClassName() { std::string functionIdentifier = ra::strings::CapitalizeFirstCharacter(mContext.functionIdentifier); diff --git a/src/bin2cpp/BaseGenerator.h b/src/bin2cpp/BaseGenerator.h index d4944fe..31473df 100644 --- a/src/bin2cpp/BaseGenerator.h +++ b/src/bin2cpp/BaseGenerator.h @@ -57,7 +57,9 @@ namespace bin2cpp virtual std::string getHeaderTemplate(); virtual std::string getHeaderTemplate(bool include_source_file); virtual std::string getSaveMethodTemplate(); - virtual std::string getFileManagerRegistrationTemplate(); + virtual std::string getCppFileManagerRegistrationImplementationTemplate(); + virtual std::string getCFileManagerRegistrationPredeclarationTemplate(); + virtual std::string getCFileManagerRegistrationImplementationTemplate(); virtual std::string getClassName(); virtual std::string getClassMacroGuardPrefix(); virtual std::string getImplOfGetFileName(); diff --git a/src/bin2cpp/ManagerGenerator.cpp b/src/bin2cpp/ManagerGenerator.cpp index 36fff63..8f10313 100644 --- a/src/bin2cpp/ManagerGenerator.cpp +++ b/src/bin2cpp/ManagerGenerator.cpp @@ -343,6 +343,17 @@ namespace bin2cpp fprintf(fout, "\n"); fprintf(fout, "bool bin2c_filemanager_register_file(%s* file)\n", mContext.baseClass.c_str()); fprintf(fout, "{\n"); + fprintf(fout, " // check if already registered\n"); + fprintf(fout, " if ( registered_files_count && registered_files )\n"); + fprintf(fout, " {\n"); + fprintf(fout, " for ( size_t i = 0; i < registered_files_count; i++ )\n"); + fprintf(fout, " {\n"); + fprintf(fout, " const %s* existing_file = registered_files[i];\n", mContext.baseClass.c_str()); + fprintf(fout, " if ( existing_file == file )\n"); + fprintf(fout, " return true; // nothing to do\n"); + fprintf(fout, " }\n"); + fprintf(fout, " }\n"); + fprintf(fout, " \n"); fprintf(fout, " // allocate ram\n"); fprintf(fout, " size_t new_ram_size = sizeof(%s**) * (registered_files_count + 1);\n", mContext.baseClass.c_str()); fprintf(fout, " %s** tmp = NULL;\n", mContext.baseClass.c_str()); diff --git a/src/bin2cpp/SegmentGenerator.cpp b/src/bin2cpp/SegmentGenerator.cpp index 575133d..4122f85 100755 --- a/src/bin2cpp/SegmentGenerator.cpp +++ b/src/bin2cpp/SegmentGenerator.cpp @@ -149,7 +149,7 @@ namespace bin2cpp fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str()); if (mContext.registerFiles) { - std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + std::string fileManagerTemplate = getCppFileManagerRegistrationImplementationTemplate(); fprintf(cpp, "%s", fileManagerTemplate.c_str()); } fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str()); @@ -167,7 +167,7 @@ namespace bin2cpp if ( !input ) return false; - //Uppercase function identifier + //Lowercase function identifier std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); //Build header and cpp file path @@ -211,11 +211,8 @@ namespace bin2cpp fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); fprintf(fout, "\n"); - if ( mContext.registerFiles ) - { - fprintf(fout, "extern bool bin2c_filemanager_register_file(%s * file);\n", mContext.baseClass.c_str()); - fprintf(fout, "\n"); - } + // File registration predeclaration code + fprintf(fout, "%s", getCFileManagerRegistrationPredeclarationTemplate().c_str()); fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); @@ -304,14 +301,12 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); - if ( mContext.registerFiles ) { fprintf(fout, " \n"); - fprintf(fout, " // register\n"); + fprintf(fout, " // register when loaded if static initialisation does not work\n"); fprintf(fout, " bin2c_filemanager_register_file(file);\n"); } - fprintf(fout, "}\n"); fprintf(fout, "\n"); fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); @@ -320,11 +315,8 @@ namespace bin2cpp fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); fprintf(fout, "}\n"); - //if ( mContext.registerFiles ) - //{ - // std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); - // fprintf(fout, "%s", fileManagerTemplate.c_str()); - //} + // File registration implementation code + fprintf(fout, "%s", getCFileManagerRegistrationImplementationTemplate().c_str()); fclose(input); fclose(fout); diff --git a/src/bin2cpp/StringGenerator.cpp b/src/bin2cpp/StringGenerator.cpp index a7e5589..a7ba051 100755 --- a/src/bin2cpp/StringGenerator.cpp +++ b/src/bin2cpp/StringGenerator.cpp @@ -151,7 +151,7 @@ namespace bin2cpp fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str()); if (mContext.registerFiles) { - std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + std::string fileManagerTemplate = getCppFileManagerRegistrationImplementationTemplate(); fprintf(cpp, "%s", fileManagerTemplate.c_str()); } fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str()); @@ -213,11 +213,8 @@ namespace bin2cpp fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str()); fprintf(fout, "\n"); - if ( mContext.registerFiles ) - { - fprintf(fout, "extern bool bin2c_filemanager_register_file(%s * file);\n", mContext.baseClass.c_str()); - fprintf(fout, "\n"); - } + // File registration predeclaration code + fprintf(fout, "%s", getCFileManagerRegistrationPredeclarationTemplate().c_str()); fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); @@ -330,11 +327,8 @@ namespace bin2cpp fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); fprintf(fout, "}\n"); - if ( mContext.registerFiles ) - { - std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); - fprintf(fout, "%s", fileManagerTemplate.c_str()); - } + // File registration implementation code + fprintf(fout, "%s", getCFileManagerRegistrationImplementationTemplate().c_str()); fclose(input); fclose(fout); diff --git a/src/bin2cpp/Win32ResourceGenerator.cpp b/src/bin2cpp/Win32ResourceGenerator.cpp index 26165c6..bf6ba80 100755 --- a/src/bin2cpp/Win32ResourceGenerator.cpp +++ b/src/bin2cpp/Win32ResourceGenerator.cpp @@ -180,7 +180,7 @@ namespace bin2cpp fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str()); if (mContext.registerFiles) { - std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); + std::string fileManagerTemplate = getCppFileManagerRegistrationImplementationTemplate(); fprintf(cpp, "%s", fileManagerTemplate.c_str()); } fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str()); @@ -264,11 +264,8 @@ namespace bin2cpp fprintf(fout, "static %s %s_info = { 0 };\n", getLocalInfoStructName().c_str(), functionIdentifier.c_str()); fprintf(fout, "\n"); - if ( mContext.registerFiles ) - { - fprintf(fout, "extern bool bin2c_filemanager_register_file(%s * file);\n", mContext.baseClass.c_str()); - fprintf(fout, "\n"); - } + // File registration predeclaration code + fprintf(fout, "%s", getCFileManagerRegistrationPredeclarationTemplate().c_str()); fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); @@ -374,11 +371,8 @@ namespace bin2cpp fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str()); fprintf(fout, "}\n"); - if ( mContext.registerFiles ) - { - std::string fileManagerTemplate = getFileManagerRegistrationTemplate(); - fprintf(fout, "%s", fileManagerTemplate.c_str()); - } + // File registration implementation code + fprintf(fout, "%s", getCFileManagerRegistrationImplementationTemplate().c_str()); fclose(input); fclose(fout); From 3ee8d5744fc938e25d743969f2ffb462fd330144 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sat, 17 May 2025 08:43:42 -0400 Subject: [PATCH 12/25] Fixes C code generation error with `\0` code. --- src/bin2cpp/ManagerGenerator.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bin2cpp/ManagerGenerator.cpp b/src/bin2cpp/ManagerGenerator.cpp index 8f10313..a18d922 100644 --- a/src/bin2cpp/ManagerGenerator.cpp +++ b/src/bin2cpp/ManagerGenerator.cpp @@ -382,12 +382,12 @@ namespace bin2cpp fprintf(fout, "\n"); fprintf(fout, "static inline bool bin2c_filemanager_is_root_directory(const char* path)\n"); fprintf(fout, "{\n"); - fprintf(fout, " if ( path == NULL && path[0] == '\0' )\n"); + fprintf(fout, " if ( path == NULL && path[0] == '\\0' )\n"); fprintf(fout, " return false;\n"); fprintf(fout, "#if defined(_WIN32)\n"); fprintf(fout, " bool is_drive_letter = ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'));\n"); - fprintf(fout, " if ( (is_drive_letter && path[1] == ':' && path[2] == '\0') || // test for C:\n"); - fprintf(fout, " (is_drive_letter && path[1] == ':' && path[2] == PATH_SEPARATOR_CHAR && path[3] == '\0') ) // test for C:\\ \n"); + fprintf(fout, " if ( (is_drive_letter && path[1] == ':' && path[2] == '\\0') || // test for C:\n"); + fprintf(fout, " (is_drive_letter && path[1] == ':' && path[2] == PATH_SEPARATOR_CHAR && path[3] == '\\0') ) // test for C:\\ \n"); fprintf(fout, " return true;\n"); fprintf(fout, "#else\n"); fprintf(fout, " if ( path[0] == PATH_SEPARATOR_CHAR )\n"); @@ -403,11 +403,11 @@ namespace bin2cpp fprintf(fout, " char* accumulator = (char*)malloc(BIN2C_MAX_PATH);\n"); fprintf(fout, " if ( accumulator == NULL )\n"); fprintf(fout, " return false;\n"); - fprintf(fout, " accumulator[0] = '\0';\n"); + fprintf(fout, " accumulator[0] = '\\0';\n"); fprintf(fout, " size_t length = strlen(file_path);\n"); fprintf(fout, " for ( size_t i = 0; i < length; i++ )\n"); fprintf(fout, " {\n"); - fprintf(fout, " if ( file_path[i] == PATH_SEPARATOR_CHAR && !(accumulator[0] == '\0') && !bin2c_filemanager_is_root_directory(accumulator) )\n"); + fprintf(fout, " if ( file_path[i] == PATH_SEPARATOR_CHAR && !(accumulator[0] == '\\0') && !bin2c_filemanager_is_root_directory(accumulator) )\n"); fprintf(fout, " {\n"); fprintf(fout, " int ret = portable_mkdir(accumulator);\n"); fprintf(fout, " if ( ret != 0 && errno != EEXIST )\n"); @@ -418,7 +418,7 @@ namespace bin2cpp fprintf(fout, " }\n"); fprintf(fout, " \n"); fprintf(fout, " // append\n"); - fprintf(fout, " char tmp[] = { file_path[i], '\0' };\n"); + fprintf(fout, " char tmp[] = { file_path[i], '\\0' };\n"); fprintf(fout, " strcat(accumulator, tmp);\n"); fprintf(fout, " }\n"); fprintf(fout, " free(accumulator);\n"); @@ -432,7 +432,7 @@ namespace bin2cpp fprintf(fout, " char* path = (char*)malloc(BIN2C_MAX_PATH);\n"); fprintf(fout, " if ( path == NULL )\n"); fprintf(fout, " return false;\n"); - fprintf(fout, " path[0] = '\0';\n"); + fprintf(fout, " path[0] = '\\0';\n"); fprintf(fout, " for(size_t i=0; i< registered_files_count; i++)\n"); fprintf(fout, " {\n"); fprintf(fout, " const Bin2cFile* f = bin2c_filemanager_get_file(i);\n"); From a37e1e93a88364a02b407e1c30969b204357f6be Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sat, 17 May 2025 08:54:10 -0400 Subject: [PATCH 13/25] Fixed hardcoded `Bin2cFile` string for `--baseclass` command for C generated code. --- src/bin2cpp/ManagerGenerator.cpp | 2 +- src/bin2cpp/bin2cpp.samples.txt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bin2cpp/ManagerGenerator.cpp b/src/bin2cpp/ManagerGenerator.cpp index a18d922..e5dc539 100644 --- a/src/bin2cpp/ManagerGenerator.cpp +++ b/src/bin2cpp/ManagerGenerator.cpp @@ -435,7 +435,7 @@ namespace bin2cpp fprintf(fout, " path[0] = '\\0';\n"); fprintf(fout, " for(size_t i=0; i< registered_files_count; i++)\n"); fprintf(fout, " {\n"); - fprintf(fout, " const Bin2cFile* f = bin2c_filemanager_get_file(i);\n"); + fprintf(fout, " const %s* f = bin2c_filemanager_get_file(i);\n", mContext.baseClass.c_str()); fprintf(fout, " if ( !f )\n"); fprintf(fout, " {\n"); fprintf(fout, " free(path);\n"); diff --git a/src/bin2cpp/bin2cpp.samples.txt b/src/bin2cpp/bin2cpp.samples.txt index e020ac3..9909bed 100644 --- a/src/bin2cpp/bin2cpp.samples.txt +++ b/src/bin2cpp/bin2cpp.samples.txt @@ -19,7 +19,9 @@ Test directories: Test for namespace: --file=..\..\test\bin2cpp_unittest\generated_files\testNamespace_C\testNamespace_C.bin --output=..\..\test\bin2cpp_unittest\generated_files\testNamespace_C --headerfile=testNamespace_C.h --identifier=testNamespace_C --managerfile=filemanager.h --override --code=c --namespace=foobar - + +Test for baseclass: +--file=..\..\test\bin2cpp_unittest\generated_files\testBaseClass_C\testBaseClass_C.bin --output=..\..\test\bin2cpp_unittest\generated_files\testBaseClass_C --headerfile=testBaseClass_C.h --identifier=testBaseClass_C --managerfile=filemanager.h --override --code=c --baseclass=Resource # CPP code examples: From 54717971f8ac71a7a011480468aac100ff4d4cbf Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sat, 17 May 2025 12:00:51 -0400 Subject: [PATCH 14/25] * Implemented `--namespace` command support for C generated code. --- src/bin2cpp/ArrayGenerator.cpp | 2 +- src/bin2cpp/BaseGenerator.cpp | 25 +++++++++-------- src/bin2cpp/ManagerGenerator.cpp | 38 +++++++++++++------------- src/bin2cpp/SegmentGenerator.cpp | 2 +- src/bin2cpp/StringGenerator.cpp | 2 +- src/bin2cpp/Win32ResourceGenerator.cpp | 2 +- src/bin2cpp/main.cpp | 2 ++ 7 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/bin2cpp/ArrayGenerator.cpp b/src/bin2cpp/ArrayGenerator.cpp index cdd5ff5..43d5fba 100644 --- a/src/bin2cpp/ArrayGenerator.cpp +++ b/src/bin2cpp/ArrayGenerator.cpp @@ -332,7 +332,7 @@ namespace bin2cpp { fprintf(fout, " \n"); fprintf(fout, " // register when loaded if static initialisation does not work\n"); - fprintf(fout, " bin2c_filemanager_register_file(file);\n"); + fprintf(fout, " %s_filemanager_register_file(file);\n", mContext.codeNamespace.c_str()); } fprintf(fout, "}\n"); fprintf(fout, "\n"); diff --git a/src/bin2cpp/BaseGenerator.cpp b/src/bin2cpp/BaseGenerator.cpp index 7b96007..9ae693b 100755 --- a/src/bin2cpp/BaseGenerator.cpp +++ b/src/bin2cpp/BaseGenerator.cpp @@ -81,7 +81,8 @@ namespace bin2cpp //Uppercase function identifier std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier); - getter.append("bin2c_get_file_"); + getter.append(mContext.codeNamespace); + getter.append("_get_file_"); getter.append(functionIdentifier); } break; @@ -187,7 +188,7 @@ namespace bin2cpp return std::string(); std::string output; - output << "extern bool bin2c_filemanager_register_file(" << mContext.baseClass << " * file); \n"; + output << "extern bool " << mContext.codeNamespace << "_filemanager_register_file(" << mContext.baseClass << " * file); \n"; output << "\n"; return output; } @@ -204,14 +205,14 @@ namespace bin2cpp output << "#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) // GCC 4.0+ required, Clang supports it by default\n"; output << "__attribute__((constructor))\n"; output << "#endif\n"; - output << "void bin2c_register_file_static_init_" << functionIdentifier << "(void)\n"; + output << "void " << mContext.codeNamespace << "_register_file_static_init_" << functionIdentifier << "(void)\n"; output << "{\n"; - output << " " << mContext.baseClass << "* this_file = bin2c_get_file_" << functionIdentifier << "();\n"; - output << " bin2c_filemanager_register_file(this_file);\n"; + output << " " << mContext.baseClass << "* this_file = " << mContext.codeNamespace << "_get_file_" << functionIdentifier << "();\n"; + output << " " << mContext.codeNamespace << "_filemanager_register_file(this_file);\n"; output << "}\n"; output << "#if _MSC_VER >= 1920 // Visual Studio 2019 or later\n"; output << "#pragma section(\".CRT$XCU\", read)\n"; - output << "__declspec(allocate(\".CRT$XCU\")) void (*init_ptr_" << functionIdentifier << ")(void) = bin2c_register_file_static_init_" << functionIdentifier << ";\n"; + output << "__declspec(allocate(\".CRT$XCU\")) void (*init_ptr_" << functionIdentifier << ")(void) = " << mContext.codeNamespace << "_register_file_static_init_" << functionIdentifier << ";\n"; output << "#endif\n"; return output; } @@ -460,18 +461,18 @@ namespace bin2cpp fprintf(header, "#ifndef %s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); fprintf(header, "#define %s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); fprintf(header, "typedef struct %s %s;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); - fprintf(header, "typedef bool(*bin2c_load_func)();\n"); - fprintf(header, "typedef void(*bin2c_free_func)();\n"); - fprintf(header, "typedef bool(*bin2c_save_func)(const char*);\n"); + fprintf(header, "typedef bool(*%s_load_func)();\n", mContext.codeNamespace.c_str()); + fprintf(header, "typedef void(*%s_free_func)();\n", mContext.codeNamespace.c_str()); + fprintf(header, "typedef bool(*%s_save_func)(const char*);\n", mContext.codeNamespace.c_str()); fprintf(header, "typedef struct %s\n", mContext.baseClass.c_str()); fprintf(header, "{\n"); fprintf(header, " size_t size;\n"); fprintf(header, " const char* file_name;\n"); fprintf(header, " const char* file_path;\n"); fprintf(header, " const unsigned char* buffer;\n"); - fprintf(header, " bin2c_load_func load;\n"); - fprintf(header, " bin2c_free_func unload;\n"); - fprintf(header, " bin2c_save_func save;\n"); + fprintf(header, " %s_load_func load;\n", mContext.codeNamespace.c_str()); + fprintf(header, " %s_free_func unload;\n", mContext.codeNamespace.c_str()); + fprintf(header, " %s_save_func save;\n", mContext.codeNamespace.c_str()); fprintf(header, "} %s;\n", mContext.baseClass.c_str()); fprintf(header, "typedef %s* %sPtr;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); fprintf(header, "#endif //%s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); diff --git a/src/bin2cpp/ManagerGenerator.cpp b/src/bin2cpp/ManagerGenerator.cpp index e5dc539..5ca8853 100644 --- a/src/bin2cpp/ManagerGenerator.cpp +++ b/src/bin2cpp/ManagerGenerator.cpp @@ -265,26 +265,26 @@ namespace bin2cpp fprintf(fout, "#ifndef %s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); fprintf(fout, "#define %s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); fprintf(fout, "typedef struct %s %s;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); - fprintf(fout, "typedef bool(*bin2c_load_func)();\n"); - fprintf(fout, "typedef void(*bin2c_free_func)();\n"); - fprintf(fout, "typedef bool(*bin2c_save_func)(const char*);\n"); + fprintf(fout, "typedef bool(*%s_load_func)();\n", mContext.codeNamespace.c_str()); + fprintf(fout, "typedef void(*%s_free_func)();\n", mContext.codeNamespace.c_str()); + fprintf(fout, "typedef bool(*%s_save_func)(const char*);\n", mContext.codeNamespace.c_str()); fprintf(fout, "typedef struct %s\n", mContext.baseClass.c_str()); fprintf(fout, "{\n"); fprintf(fout, " size_t size;\n"); fprintf(fout, " const char* file_name;\n"); fprintf(fout, " const char* file_path;\n"); fprintf(fout, " const unsigned char* buffer;\n"); - fprintf(fout, " bin2c_load_func load;\n"); - fprintf(fout, " bin2c_free_func unload;\n"); - fprintf(fout, " bin2c_save_func save;\n"); + fprintf(fout, " %s_load_func load;\n", mContext.codeNamespace.c_str()); + fprintf(fout, " %s_free_func unload;\n", mContext.codeNamespace.c_str()); + fprintf(fout, " %s_save_func save;\n", mContext.codeNamespace.c_str()); fprintf(fout, "} %s;\n", mContext.baseClass.c_str()); fprintf(fout, "typedef %s* %sPtr;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); fprintf(fout, "#endif //%s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); fprintf(fout, "\n"); - fprintf(fout, "size_t bin2c_filemanager_get_file_count();\n"); - fprintf(fout, "bool bin2c_filemanager_register_file(%s* file);\n", mContext.baseClass.c_str()); - fprintf(fout, "const %s* bin2c_filemanager_get_file(size_t index);\n", mContext.baseClass.c_str()); - fprintf(fout, "bool bin2c_filemanager_save_files(const char* directory);\n"); + fprintf(fout, "size_t %s_filemanager_get_file_count();\n", mContext.codeNamespace.c_str()); + fprintf(fout, "bool %s_filemanager_register_file(%s* file);\n", mContext.codeNamespace.c_str(), mContext.baseClass.c_str()); + fprintf(fout, "const %s* %s_filemanager_get_file(size_t index);\n", mContext.baseClass.c_str(), mContext.codeNamespace.c_str()); + fprintf(fout, "bool %s_filemanager_save_files(const char* directory);\n", mContext.codeNamespace.c_str()); fprintf(fout, "\n"); fprintf(fout, "#endif //%s\n", macroGuard.c_str()); @@ -336,12 +336,12 @@ namespace bin2cpp fprintf(fout, "static %s** registered_files = NULL;\n", mContext.baseClass.c_str()); fprintf(fout, "static size_t registered_files_count = 0;\n"); fprintf(fout, "\n"); - fprintf(fout, "size_t bin2c_filemanager_get_file_count()\n"); + fprintf(fout, "size_t %s_filemanager_get_file_count()\n", mContext.codeNamespace.c_str()); fprintf(fout, "{\n"); fprintf(fout, " return registered_files_count;\n"); fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "bool bin2c_filemanager_register_file(%s* file)\n", mContext.baseClass.c_str()); + fprintf(fout, "bool %s_filemanager_register_file(%s* file)\n", mContext.codeNamespace.c_str(), mContext.baseClass.c_str()); fprintf(fout, "{\n"); fprintf(fout, " // check if already registered\n"); fprintf(fout, " if ( registered_files_count && registered_files )\n"); @@ -373,14 +373,14 @@ namespace bin2cpp fprintf(fout, " return true;\n"); fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "const %s* bin2c_filemanager_get_file(size_t index)\n", mContext.baseClass.c_str()); + fprintf(fout, "const %s* %s_filemanager_get_file(size_t index)\n", mContext.baseClass.c_str(), mContext.codeNamespace.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if ( index >= registered_files_count )\n"); fprintf(fout, " return NULL;\n"); fprintf(fout, " return registered_files[index];\n"); fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "static inline bool bin2c_filemanager_is_root_directory(const char* path)\n"); + fprintf(fout, "static inline bool %s_filemanager_is_root_directory(const char* path)\n", mContext.codeNamespace.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if ( path == NULL && path[0] == '\\0' )\n"); fprintf(fout, " return false;\n"); @@ -396,7 +396,7 @@ namespace bin2cpp fprintf(fout, " return false;\n"); fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "bool bin2c_filemanager_create_parent_directories(const char* file_path)\n"); + fprintf(fout, "bool %s_filemanager_create_parent_directories(const char* file_path)\n", mContext.codeNamespace.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if ( file_path == NULL )\n"); fprintf(fout, " return false;\n"); @@ -407,7 +407,7 @@ namespace bin2cpp fprintf(fout, " size_t length = strlen(file_path);\n"); fprintf(fout, " for ( size_t i = 0; i < length; i++ )\n"); fprintf(fout, " {\n"); - fprintf(fout, " if ( file_path[i] == PATH_SEPARATOR_CHAR && !(accumulator[0] == '\\0') && !bin2c_filemanager_is_root_directory(accumulator) )\n"); + fprintf(fout, " if ( file_path[i] == PATH_SEPARATOR_CHAR && !(accumulator[0] == '\\0') && !%s_filemanager_is_root_directory(accumulator) )\n", mContext.codeNamespace.c_str()); fprintf(fout, " {\n"); fprintf(fout, " int ret = portable_mkdir(accumulator);\n"); fprintf(fout, " if ( ret != 0 && errno != EEXIST )\n"); @@ -425,7 +425,7 @@ namespace bin2cpp fprintf(fout, " return true;\n"); fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "bool bin2c_filemanager_save_files(const char * directory)\n"); + fprintf(fout, "bool %s_filemanager_save_files(const char * directory)\n", mContext.codeNamespace.c_str()); fprintf(fout, "{\n"); fprintf(fout, " if (directory == NULL)\n"); fprintf(fout, " return false;\n"); @@ -435,7 +435,7 @@ namespace bin2cpp fprintf(fout, " path[0] = '\\0';\n"); fprintf(fout, " for(size_t i=0; i< registered_files_count; i++)\n"); fprintf(fout, " {\n"); - fprintf(fout, " const %s* f = bin2c_filemanager_get_file(i);\n", mContext.baseClass.c_str()); + fprintf(fout, " const %s* f = %s_filemanager_get_file(i);\n", mContext.baseClass.c_str(), mContext.codeNamespace.c_str()); fprintf(fout, " if ( !f )\n"); fprintf(fout, " {\n"); fprintf(fout, " free(path);\n"); @@ -445,7 +445,7 @@ namespace bin2cpp fprintf(fout, " char path[32767] = { 0 };\n"); fprintf(fout, " snprintf(path, sizeof(path), \"%%s%%c%%s\", directory, PATH_SEPARATOR_CHAR, f->file_path);\n"); fprintf(fout, " \n"); - fprintf(fout, " if (!bin2c_filemanager_create_parent_directories(path))\n"); + fprintf(fout, " if (!%s_filemanager_create_parent_directories(path))\n", mContext.codeNamespace.c_str()); fprintf(fout, " {\n"); fprintf(fout, " free(path);\n"); fprintf(fout, " return false;\n"); diff --git a/src/bin2cpp/SegmentGenerator.cpp b/src/bin2cpp/SegmentGenerator.cpp index 4122f85..35359b9 100755 --- a/src/bin2cpp/SegmentGenerator.cpp +++ b/src/bin2cpp/SegmentGenerator.cpp @@ -305,7 +305,7 @@ namespace bin2cpp { fprintf(fout, " \n"); fprintf(fout, " // register when loaded if static initialisation does not work\n"); - fprintf(fout, " bin2c_filemanager_register_file(file);\n"); + fprintf(fout, " %s_filemanager_register_file(file);\n", mContext.codeNamespace.c_str()); } fprintf(fout, "}\n"); fprintf(fout, "\n"); diff --git a/src/bin2cpp/StringGenerator.cpp b/src/bin2cpp/StringGenerator.cpp index a7ba051..7e433c1 100755 --- a/src/bin2cpp/StringGenerator.cpp +++ b/src/bin2cpp/StringGenerator.cpp @@ -316,7 +316,7 @@ namespace bin2cpp { fprintf(fout, " \n"); fprintf(fout, " // register\n"); - fprintf(fout, " bin2c_filemanager_register_file(file);\n"); + fprintf(fout, " %s_filemanager_register_file(file);\n", mContext.codeNamespace.c_str()); } fprintf(fout, "}\n"); diff --git a/src/bin2cpp/Win32ResourceGenerator.cpp b/src/bin2cpp/Win32ResourceGenerator.cpp index bf6ba80..45d288c 100755 --- a/src/bin2cpp/Win32ResourceGenerator.cpp +++ b/src/bin2cpp/Win32ResourceGenerator.cpp @@ -359,7 +359,7 @@ namespace bin2cpp { fprintf(fout, " \n"); fprintf(fout, " // register\n"); - fprintf(fout, " bin2c_filemanager_register_file(file);\n"); + fprintf(fout, " %s_filemanager_register_file(file);\n", mContext.codeNamespace.c_str()); } fprintf(fout, "}\n"); diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index f287b4f..336f71d 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -191,7 +191,9 @@ void printUsage() " --encoding= Name of the binary to string literal encoding to use. Possible values are 'oct' and 'hex'. [default: oct]\n" " --chunksize= Size in bytes of each string segments (bytes per LoC). [default: 200]\n" " --baseclass= The name of the interface for embedded files. [default: File]\n" + " For C generated code, this parameter is for naming the File structure. [default: Bin2cFile]\n" " --namespace= The namespace of the generated source code. [default: bin2cpp]\n" + " For C generated code, this parameter is for setting the prefix of all function names. [default: bin2c]\n" " --reportedfilepath= The relative reported path of the File. Path returned when calling method getFilePath() of the File class. ie: images" SEPARATOR "DCIM" SEPARATOR "IMG_0001.jpg.\n" " Automatically calculated when --dir mode is used.\n" " --managerfile= File name or relative path of the generated C++ header file for the FileManager class. ie: FileManager.h\n" From 21fe6d8b94d2f9dee405f5683e203b056393ae7e Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 18 May 2025 09:24:28 -0400 Subject: [PATCH 15/25] Fixed a bug with Win32ResourceGenerator where the code was using `FindResource()` which detect unicode support and calls `FindResourceA()` or `FindResourceW()` depending of the settings. Modified the code to always use ANSI functions since the names of the identifiers are always English based characters. --- src/bin2cpp/Win32ResourceGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin2cpp/Win32ResourceGenerator.cpp b/src/bin2cpp/Win32ResourceGenerator.cpp index 45d288c..ac516ef 100755 --- a/src/bin2cpp/Win32ResourceGenerator.cpp +++ b/src/bin2cpp/Win32ResourceGenerator.cpp @@ -138,7 +138,7 @@ namespace bin2cpp fprintf(cpp, " if ( EnumProcessModules( hProcess, &hModule, sizeof(hModule), &cbNeeded) )\n"); fprintf(cpp, " {\n"); fprintf(cpp, " //Retrieve the resource\n"); - fprintf(cpp, " hResourceInfoBlock = FindResource(hModule, \"%s\", \"CUSTOM\");\n", getRandomIdentifier(mContext.inputFilePath.c_str()).c_str()); + fprintf(cpp, " hResourceInfoBlock = FindResourceA(hModule, \"%s\", \"CUSTOM\");\n", getRandomIdentifier(mContext.inputFilePath.c_str()).c_str()); fprintf(cpp, " if (hResourceInfoBlock)\n"); fprintf(cpp, " {\n"); fprintf(cpp, " hResHandle = LoadResource(hModule, hResourceInfoBlock);\n"); @@ -283,7 +283,7 @@ namespace bin2cpp fprintf(fout, " if ( EnumProcessModules( info->hProcess, &info->hModule, sizeof(info->hModule), &cbNeeded) )\n"); fprintf(fout, " {\n"); fprintf(fout, " //Retrieve the resource\n"); - fprintf(fout, " info->hResourceInfoBlock = FindResource(info->hModule, L\"%s\", L\"CUSTOM\");\n", getRandomIdentifier(mContext.inputFilePath.c_str()).c_str()); + fprintf(fout, " info->hResourceInfoBlock = FindResourceA(info->hModule, \"%s\", \"CUSTOM\");\n", getRandomIdentifier(mContext.inputFilePath.c_str()).c_str()); fprintf(fout, " if (info->hResourceInfoBlock)\n"); fprintf(fout, " {\n"); fprintf(fout, " info->hResHandle = LoadResource(info->hModule, info->hResourceInfoBlock);\n"); From be7e39435e9b4953facced72212296cb730be13a Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 18 May 2025 09:25:58 -0400 Subject: [PATCH 16/25] Fixed a bug with commands `--managerfile=filemanager.h --code=c` where the generated file manager files were using `.cpp` file extension instead of the expected `.c` file extension. --- src/bin2cpp/bin2cpp.samples.txt | 4 ++-- src/bin2cpp/main.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/bin2cpp/bin2cpp.samples.txt b/src/bin2cpp/bin2cpp.samples.txt index 9909bed..1f9d63f 100644 --- a/src/bin2cpp/bin2cpp.samples.txt +++ b/src/bin2cpp/bin2cpp.samples.txt @@ -10,8 +10,8 @@ Test for: * Segment C generator * filemanager * registerfile ---file=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C\testFileManager.1.bin --output=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C --headerfile=_testFileManager.1.h --identifier=testFileManager1_c --managerfile=filemanager.h --override --code=c ---file=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C\testFileManager.2.bin --output=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C --headerfile=_testFileManager.2.h --identifier=testFileManager2_c --registerfile --override --code=c +--file=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C\testFileManager_C.1.bin --output=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C --headerfile=_testFileManager_C.1.h --identifier=testFileManager1_c --managerfile=filemanager.h --override --code=c +--file=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C\testFileManager_C.2.bin --output=..\..\test\bin2cpp_unittest\generated_files\testFileManager_C --headerfile=_testFileManager_C.2.h --identifier=testFileManager2_c --registerfile --override --code=c Test directories: --dir=..\..\..\samples\demo_website\www --output=..\..\temp --code=c diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index 336f71d..1ea7abc 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -823,12 +823,14 @@ APP_ERROR_CODES processManagerFiles(const Context & c) info << "..."; ra::logging::Log(ra::logging::LOG_INFO, info.c_str()); + const std::string& sourceFileExtension = "." + getDefaultCodeSourceFileExtension(c.code); + //prepare output files path std::string cppFilename = c.managerHeaderFilename; - ra::strings::Replace(cppFilename, ".hpp", ".cpp"); - ra::strings::Replace(cppFilename, ".h", ".cpp"); + ra::strings::Replace(cppFilename, ".hpp", sourceFileExtension); + ra::strings::Replace(cppFilename, ".h", sourceFileExtension); std::string outputHeaderPath = c.outputDirPath + ra::filesystem::GetPathSeparatorStr() + c.managerHeaderFilename; - std::string outputCppPath = c.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cppFilename; + std::string outputSourcePath = c.outputDirPath + ra::filesystem::GetPathSeparatorStr() + cppFilename; ManagerGenerator generator; @@ -840,7 +842,7 @@ APP_ERROR_CODES processManagerFiles(const Context & c) if (!headerResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; - bool cppResult = generateOutputFile(c, outputCppPath, &generator); + bool cppResult = generateOutputFile(c, outputSourcePath, &generator); if (!cppResult) return APP_ERROR_UNABLETOCREATEOUTPUTFILES; From ca77dd8f6ef4d3d3b6badcf978d81acd8a20fcf5 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 18 May 2025 09:52:36 -0400 Subject: [PATCH 17/25] Modified scripts `generate_test_files.bat.in` and `generate_test_files.sh.in` to generate files in C and added them to project bin2cpp_unittest to check that generated C code is compilable. --- src/bin2cpp/BaseGenerator.cpp | 2 +- test/bin2cpp_unittest/CMakeLists.txt | 26 +++++ test/bin2cpp_unittest/TestExtraction.cpp | 102 ++++++++++++++++++ .../generate_test_files.bat.in | 51 +++++++++ .../generate_test_files.sh.in | 46 +++++++- 5 files changed, 225 insertions(+), 2 deletions(-) diff --git a/src/bin2cpp/BaseGenerator.cpp b/src/bin2cpp/BaseGenerator.cpp index 9ae693b..980fefa 100755 --- a/src/bin2cpp/BaseGenerator.cpp +++ b/src/bin2cpp/BaseGenerator.cpp @@ -476,7 +476,7 @@ namespace bin2cpp fprintf(header, "} %s;\n", mContext.baseClass.c_str()); fprintf(header, "typedef %s* %sPtr;\n", mContext.baseClass.c_str(), mContext.baseClass.c_str()); fprintf(header, "#endif //%s_EMBEDDEDFILE_STRUCT\n", classMacroGuardPrefix.c_str()); - fprintf(header, "%s* %s();\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); + fprintf(header, "%s* %s(void);\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str()); fprintf(header, "\n"); fprintf(header, "#endif //%s\n", macroGuard.c_str()); diff --git a/test/bin2cpp_unittest/CMakeLists.txt b/test/bin2cpp_unittest/CMakeLists.txt index 3e6760c..badf315 100644 --- a/test/bin2cpp_unittest/CMakeLists.txt +++ b/test/bin2cpp_unittest/CMakeLists.txt @@ -7,15 +7,21 @@ include_directories(${GENERATED_TEST_FILES_DIR}) # for TestExtraction.cpp # These are required because each generated cpp file is including its header file # without using the parent directory. include_directories(${GENERATED_TEST_FILES_DIR}/testBaseClass) +include_directories(${GENERATED_TEST_FILES_DIR}/testBaseClass_C) include_directories(${GENERATED_TEST_FILES_DIR}/testDir01/sources) include_directories(${GENERATED_TEST_FILES_DIR}/testEncodingHex) include_directories(${GENERATED_TEST_FILES_DIR}/testEncodingOct) include_directories(${GENERATED_TEST_FILES_DIR}/testFileManager) +include_directories(${GENERATED_TEST_FILES_DIR}/testFileManager_C) include_directories(${GENERATED_TEST_FILES_DIR}/testGeneratorArray10000) +include_directories(${GENERATED_TEST_FILES_DIR}/testGeneratorArray10000_C) include_directories(${GENERATED_TEST_FILES_DIR}/testGeneratorSegment10000) +include_directories(${GENERATED_TEST_FILES_DIR}/testGeneratorSegment10000_C) include_directories(${GENERATED_TEST_FILES_DIR}/testGeneratorString10000) +include_directories(${GENERATED_TEST_FILES_DIR}/testGeneratorString10000_C) if (WIN32) include_directories(${GENERATED_TEST_FILES_DIR}/testGeneratorWin32) + include_directories(${GENERATED_TEST_FILES_DIR}/testGeneratorWin32_C) endif() include_directories(${GENERATED_TEST_FILES_DIR}/testHtml100000) include_directories(${GENERATED_TEST_FILES_DIR}/testIssue12) @@ -28,6 +34,7 @@ include_directories(${GENERATED_TEST_FILES_DIR}/testIssue56b/generated_sources) include_directories(${GENERATED_TEST_FILES_DIR}/testIssue56c/generated_sources) include_directories(${GENERATED_TEST_FILES_DIR}/testKeepDirectories) include_directories(${GENERATED_TEST_FILES_DIR}/testNamespace) +include_directories(${GENERATED_TEST_FILES_DIR}/testNamespace_C) include_directories(${GENERATED_TEST_FILES_DIR}/testRandom1) include_directories(${GENERATED_TEST_FILES_DIR}/testRandom2) include_directories(${GENERATED_TEST_FILES_DIR}/testRandom3) @@ -48,6 +55,8 @@ include_directories(${GENERATED_TEST_FILES_DIR}/testText100000) set(GENERATED_TEST_FILES ${GENERATED_TEST_FILES_DIR}/testBaseClass/_testBaseClass.h ${GENERATED_TEST_FILES_DIR}/testBaseClass/_testBaseClass.cpp + ${GENERATED_TEST_FILES_DIR}/testBaseClass_C/_testBaseClass_C.h + ${GENERATED_TEST_FILES_DIR}/testBaseClass_C/_testBaseClass_C.c ${GENERATED_TEST_FILES_DIR}/testEncodingHex/_testEncodingHex.h ${GENERATED_TEST_FILES_DIR}/testEncodingHex/_testEncodingHex.cpp ${GENERATED_TEST_FILES_DIR}/testEncodingOct/_testEncodingOct.h @@ -58,6 +67,12 @@ set(GENERATED_TEST_FILES ${GENERATED_TEST_FILES_DIR}/testGeneratorSegment10000/_testGeneratorSegment10000.cpp ${GENERATED_TEST_FILES_DIR}/testGeneratorString10000/_testGeneratorString10000.h ${GENERATED_TEST_FILES_DIR}/testGeneratorString10000/_testGeneratorString10000.cpp + ${GENERATED_TEST_FILES_DIR}/testGeneratorArray10000_C/_testGeneratorArray10000_C.h + ${GENERATED_TEST_FILES_DIR}/testGeneratorArray10000_C/_testGeneratorArray10000_C.c + ${GENERATED_TEST_FILES_DIR}/testGeneratorSegment10000_C/_testGeneratorSegment10000_C.h + ${GENERATED_TEST_FILES_DIR}/testGeneratorSegment10000_C/_testGeneratorSegment10000_C.c + ${GENERATED_TEST_FILES_DIR}/testGeneratorString10000_C/_testGeneratorString10000_C.h + ${GENERATED_TEST_FILES_DIR}/testGeneratorString10000_C/_testGeneratorString10000_C.c ${GENERATED_TEST_FILES_DIR}/testHtml100000/_testHtml100000.h ${GENERATED_TEST_FILES_DIR}/testHtml100000/_testHtml100000.cpp ${GENERATED_TEST_FILES_DIR}/testIssue12/_testIssue12.h @@ -110,6 +125,8 @@ set(GENERATED_TEST_FILES ${GENERATED_TEST_FILES_DIR}/testIssue56c/generated_sources/index_5.h ${GENERATED_TEST_FILES_DIR}/testNamespace/_testNamespace.h ${GENERATED_TEST_FILES_DIR}/testNamespace/_testNamespace.cpp + ${GENERATED_TEST_FILES_DIR}/testNamespace_C/_testNamespace_C.h + ${GENERATED_TEST_FILES_DIR}/testNamespace_C/_testNamespace_C.c ${GENERATED_TEST_FILES_DIR}/testRandom1/_testRandom1.h ${GENERATED_TEST_FILES_DIR}/testRandom1/_testRandom1.cpp ${GENERATED_TEST_FILES_DIR}/testRandom2/_testRandom2.h @@ -142,6 +159,12 @@ set(GENERATED_TEST_FILES ${GENERATED_TEST_FILES_DIR}/testFileManager/_testFileManager.2.cpp ${GENERATED_TEST_FILES_DIR}/testFileManager/FileManager.h ${GENERATED_TEST_FILES_DIR}/testFileManager/FileManager.cpp + ${GENERATED_TEST_FILES_DIR}/testFileManager_C/_testFileManager_C.1.h + ${GENERATED_TEST_FILES_DIR}/testFileManager_C/_testFileManager_C.1.c + ${GENERATED_TEST_FILES_DIR}/testFileManager_C/_testFileManager_C.2.h + ${GENERATED_TEST_FILES_DIR}/testFileManager_C/_testFileManager_C.2.c + ${GENERATED_TEST_FILES_DIR}/testFileManager_C/FileManager.h + ${GENERATED_TEST_FILES_DIR}/testFileManager_C/FileManager.c ${GENERATED_TEST_FILES_DIR}/testDir01/sources/_img0001.h ${GENERATED_TEST_FILES_DIR}/testDir01/sources/_img0002.h ${GENERATED_TEST_FILES_DIR}/testDir01/sources/_img0003.h @@ -177,6 +200,9 @@ if (WIN32) ${GENERATED_TEST_FILES_DIR}/testGeneratorWin32/_testGeneratorWin32.h ${GENERATED_TEST_FILES_DIR}/testGeneratorWin32/_testGeneratorWin32.cpp ${GENERATED_TEST_FILES_DIR}/testGeneratorWin32/_testGeneratorWin32.rc + ${GENERATED_TEST_FILES_DIR}/testGeneratorWin32_C/_testGeneratorWin32_C.h + ${GENERATED_TEST_FILES_DIR}/testGeneratorWin32_C/_testGeneratorWin32_C.c + ${GENERATED_TEST_FILES_DIR}/testGeneratorWin32_C/_testGeneratorWin32_C.rc ) endif() diff --git a/test/bin2cpp_unittest/TestExtraction.cpp b/test/bin2cpp_unittest/TestExtraction.cpp index c35d71b..dbde3b8 100755 --- a/test/bin2cpp_unittest/TestExtraction.cpp +++ b/test/bin2cpp_unittest/TestExtraction.cpp @@ -69,6 +69,18 @@ #undef BIN2CPP_EMBEDDEDFILE_CLASS #include "testBaseClass/_testBaseClass.h" +extern "C" +{ + #include "testGeneratorArray10000_C/_testGeneratorArray10000_C.h" + #include "testGeneratorSegment10000_C/_testGeneratorSegment10000_C.h" + #include "testGeneratorString10000_C/_testGeneratorString10000_C.h" + #ifdef _WIN32 + #include "testGeneratorWin32_C/_testGeneratorWin32_C.h" + #endif + #include "testNamespace_C/_testNamespace_C.h" + #include "testBaseClass_C/_testBaseClass_C.h" +} + extern const std::string & gGeneratedFilesDir; namespace TestExtractionUtils @@ -330,6 +342,21 @@ TEST_F(TestExtraction, testGeneratorArray10000) ASSERT_TRUE(equal) << reason.c_str(); } +TEST_F(TestExtraction, testGeneratorArray10000_C) +{ + static const std::string expectedFilePath = getExpectedFilePath(); + static const std::string outputFilePath = getActualFilePath(); + + Bin2cFile* file = bin2c_get_file_testgeneratorarray10000_c(); + bool extractSuccess = file->save(outputFilePath.c_str()); + ASSERT_TRUE(extractSuccess); + + //assert binary content is the same + std::string reason; + bool equal = ra::testing::IsFileEquals(expectedFilePath.c_str(), outputFilePath.c_str(), reason); + ASSERT_TRUE(equal) << reason.c_str(); +} + TEST_F(TestExtraction, testGeneratorSegment10000) { static const std::string expectedFilePath = getExpectedFilePath(); @@ -345,6 +372,21 @@ TEST_F(TestExtraction, testGeneratorSegment10000) ASSERT_TRUE(equal) << reason.c_str(); } +TEST_F(TestExtraction, testGeneratorSegment10000_C) +{ + static const std::string expectedFilePath = getExpectedFilePath(); + static const std::string outputFilePath = getActualFilePath(); + + const Bin2cFile* file = bin2c_get_file_testgeneratorsegment10000_c(); + bool extractSuccess = file->save(outputFilePath.c_str()); + ASSERT_TRUE(extractSuccess); + + //assert binary content is the same + std::string reason; + bool equal = ra::testing::IsFileEquals(expectedFilePath.c_str(), outputFilePath.c_str(), reason); + ASSERT_TRUE(equal) << reason.c_str(); +} + TEST_F(TestExtraction, testGeneratorString10000) { static const std::string expectedFilePath = getExpectedFilePath(); @@ -360,6 +402,21 @@ TEST_F(TestExtraction, testGeneratorString10000) ASSERT_TRUE(equal) << reason.c_str(); } +TEST_F(TestExtraction, testGeneratorString10000_C) +{ + static const std::string expectedFilePath = getExpectedFilePath(); + static const std::string outputFilePath = getActualFilePath(); + + const Bin2cFile* file = bin2c_get_file_testgeneratorstring10000_c(); + bool extractSuccess = file->save(outputFilePath.c_str()); + ASSERT_TRUE(extractSuccess); + + //assert binary content is the same + std::string reason; + bool equal = ra::testing::IsFileEquals(expectedFilePath.c_str(), outputFilePath.c_str(), reason); + ASSERT_TRUE(equal) << reason.c_str(); +} + #ifdef _WIN32 TEST_F(TestExtraction, testGeneratorWin32) { @@ -375,6 +432,21 @@ TEST_F(TestExtraction, testGeneratorWin32) bool equal = ra::testing::IsFileEquals(expectedFilePath.c_str(), outputFilePath.c_str(), reason); ASSERT_TRUE(equal) << reason.c_str(); } + +TEST_F(TestExtraction, testGeneratorWin32_C) +{ + static const std::string expectedFilePath = getExpectedFilePath(); + static const std::string outputFilePath = getActualFilePath(); + + const Bin2cFile* file = bin2c_get_file_testgeneratorwin32_c(); + bool extractSuccess = file->save(outputFilePath.c_str()); + ASSERT_TRUE(extractSuccess); + + //assert binary content is the same + std::string reason; + bool equal = ra::testing::IsFileEquals(expectedFilePath.c_str(), outputFilePath.c_str(), reason); + ASSERT_TRUE(equal) << reason.c_str(); +} #endif TEST_F(TestExtraction, testEncodingOct) @@ -422,6 +494,21 @@ TEST_F(TestExtraction, testNamespace) ASSERT_TRUE(equal) << reason.c_str(); } +TEST_F(TestExtraction, testNamespace_C) +{ + static const std::string expectedFilePath = getExpectedFilePath(); + static const std::string outputFilePath = getActualFilePath(); + + const Bin2cFile2* file = foobar_get_file_testnamespace_c(); + bool extractSuccess = file->save(outputFilePath.c_str()); + ASSERT_TRUE(extractSuccess); + + //assert binary content is the same + std::string reason; + bool equal = ra::testing::IsFileEquals(expectedFilePath.c_str(), outputFilePath.c_str(), reason); + ASSERT_TRUE(equal) << reason.c_str(); +} + TEST_F(TestExtraction, testBaseClass) { static const std::string expectedFilePath = getExpectedFilePath(); @@ -437,6 +524,21 @@ TEST_F(TestExtraction, testBaseClass) ASSERT_TRUE(equal) << reason.c_str(); } +TEST_F(TestExtraction, testBaseClass_C) +{ + static const std::string expectedFilePath = getExpectedFilePath(); + static const std::string outputFilePath = getActualFilePath(); + + const Resource* file = tbc_get_file_testbaseclass_c(); + bool extractSuccess = file->save(outputFilePath.c_str()); + ASSERT_TRUE(extractSuccess); + + //assert binary content is the same + std::string reason; + bool equal = ra::testing::IsFileEquals(expectedFilePath.c_str(), outputFilePath.c_str(), reason); + ASSERT_TRUE(equal) << reason.c_str(); +} + TEST_F(TestExtraction, testIssue12) { static const std::string expectedFilePath = getExpectedFilePath(); diff --git a/test/bin2cpp_unittest/generate_test_files.bat.in b/test/bin2cpp_unittest/generate_test_files.bat.in index d30366f..13708da 100644 --- a/test/bin2cpp_unittest/generate_test_files.bat.in +++ b/test/bin2cpp_unittest/generate_test_files.bat.in @@ -121,6 +121,13 @@ mkdir %OUTDIR% 1>NUL 2>NUL @BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=array --override if %errorlevel% neq 0 exit /b %errorlevel% +set TEST_NAME=testGeneratorArray10000_C +set OUTDIR=.\generated_files\%TEST_NAME% +mkdir %OUTDIR% 1>NUL 2>NUL +@TESTFILEGENERATOR_TARGET_FILE@ --file=%OUTDIR%\%TEST_NAME%.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=array --override --code=c +if %errorlevel% neq 0 exit /b %errorlevel% + set TEST_NAME=testGeneratorString10000 set OUTDIR=.\generated_files\%TEST_NAME% mkdir %OUTDIR% 1>NUL 2>NUL @@ -128,6 +135,13 @@ mkdir %OUTDIR% 1>NUL 2>NUL @BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=string --override if %errorlevel% neq 0 exit /b %errorlevel% +set TEST_NAME=testGeneratorString10000_C +set OUTDIR=.\generated_files\%TEST_NAME% +mkdir %OUTDIR% 1>NUL 2>NUL +@TESTFILEGENERATOR_TARGET_FILE@ --file=%OUTDIR%\%TEST_NAME%.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=string --override --code=c +if %errorlevel% neq 0 exit /b %errorlevel% + set TEST_NAME=testGeneratorSegment10000 set OUTDIR=.\generated_files\%TEST_NAME% mkdir %OUTDIR% 1>NUL 2>NUL @@ -135,6 +149,13 @@ mkdir %OUTDIR% 1>NUL 2>NUL @BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=segment --override if %errorlevel% neq 0 exit /b %errorlevel% +set TEST_NAME=testGeneratorSegment10000_C +set OUTDIR=.\generated_files\%TEST_NAME% +mkdir %OUTDIR% 1>NUL 2>NUL +@TESTFILEGENERATOR_TARGET_FILE@ --file=%OUTDIR%\%TEST_NAME%.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=segment --override --code=c +if %errorlevel% neq 0 exit /b %errorlevel% + set TEST_NAME=testGeneratorWin32 set OUTDIR=.\generated_files\%TEST_NAME% mkdir %OUTDIR% 1>NUL 2>NUL @@ -142,6 +163,13 @@ mkdir %OUTDIR% 1>NUL 2>NUL @BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=win32 --override if %errorlevel% neq 0 exit /b %errorlevel% +set TEST_NAME=testGeneratorWin32_C +set OUTDIR=.\generated_files\%TEST_NAME% +mkdir %OUTDIR% 1>NUL 2>NUL +@TESTFILEGENERATOR_TARGET_FILE@ --file=%OUTDIR%\%TEST_NAME%.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=win32 --override --code=c +if %errorlevel% neq 0 exit /b %errorlevel% + set TEST_NAME=testNamespace set OUTDIR=.\generated_files\%TEST_NAME% mkdir %OUTDIR% 1>NUL 2>NUL @@ -149,6 +177,13 @@ mkdir %OUTDIR% 1>NUL 2>NUL @BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=segment --override --namespace=foobar if %errorlevel% neq 0 exit /b %errorlevel% +set TEST_NAME=testNamespace_C +set OUTDIR=.\generated_files\%TEST_NAME% +mkdir %OUTDIR% 1>NUL 2>NUL +@TESTFILEGENERATOR_TARGET_FILE@ --file=%OUTDIR%\%TEST_NAME%.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=segment --override --baseclass=Bin2cFile2 --namespace=foobar --code=c +if %errorlevel% neq 0 exit /b %errorlevel% + set TEST_NAME=testBaseClass set OUTDIR=.\generated_files\%TEST_NAME% mkdir %OUTDIR% 1>NUL 2>NUL @@ -156,6 +191,13 @@ mkdir %OUTDIR% 1>NUL 2>NUL @BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=segment --override --baseclass=Resource if %errorlevel% neq 0 exit /b %errorlevel% +set TEST_NAME=testBaseClass_C +set OUTDIR=.\generated_files\%TEST_NAME% +mkdir %OUTDIR% 1>NUL 2>NUL +@TESTFILEGENERATOR_TARGET_FILE@ --file=%OUTDIR%\%TEST_NAME%.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.h --identifier=%TEST_NAME% --chunksize=450 --generator=segment --override --baseclass=Resource --namespace=tbc --code=c +if %errorlevel% neq 0 exit /b %errorlevel% + set TEST_NAME=testEncodingOct set OUTDIR=.\generated_files\%TEST_NAME% mkdir %OUTDIR% 1>NUL 2>NUL @@ -201,6 +243,15 @@ mkdir %OUTDIR% 1>NUL 2>NUL @BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.2.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.2.h --identifier=%TEST_NAME%2 --registerfile --override if %errorlevel% neq 0 exit /b %errorlevel% +set TEST_NAME=testFileManager_C +set OUTDIR=.\generated_files\%TEST_NAME% +mkdir %OUTDIR% 1>NUL 2>NUL +@TESTFILEGENERATOR_TARGET_FILE@ --file=%OUTDIR%\%TEST_NAME%.1.bin --size=1000 --fill=random --seed=1 +@TESTFILEGENERATOR_TARGET_FILE@ --file=%OUTDIR%\%TEST_NAME%.2.bin --size=1000 --fill=random --seed=2 +@BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.1.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.1.h --identifier=%TEST_NAME%1 --managerfile=filemanager.h --override --code=c +@BIN2CPP_TARGET_FILE@ --noheader --file=%OUTDIR%\%TEST_NAME%.2.bin --output=%OUTDIR% --headerfile=_%TEST_NAME%.2.h --identifier=%TEST_NAME%2 --registerfile --override --code=c +if %errorlevel% neq 0 exit /b %errorlevel% + set TEST_NAME=testDir01 set OUTDIR=.\generated_files\%TEST_NAME% mkdir %OUTDIR% 1>NUL 2>NUL diff --git a/test/bin2cpp_unittest/generate_test_files.sh.in b/test/bin2cpp_unittest/generate_test_files.sh.in index 30f8f16..9f767bd 100755 --- a/test/bin2cpp_unittest/generate_test_files.sh.in +++ b/test/bin2cpp_unittest/generate_test_files.sh.in @@ -105,29 +105,59 @@ mkdir -p ${OUTDIR} @TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential @BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=array --override +export TEST_NAME=testGeneratorArray10000_C +export OUTDIR=./generated_files/$TEST_NAME +mkdir -p ${OUTDIR} +@TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=array --override --code=c + export TEST_NAME=testGeneratorString10000 export OUTDIR=./generated_files/$TEST_NAME mkdir -p ${OUTDIR} @TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential @BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=string --override +export TEST_NAME=testGeneratorString10000_C +export OUTDIR=./generated_files/$TEST_NAME +mkdir -p ${OUTDIR} +@TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=string --override --code=c + export TEST_NAME=testGeneratorSegment10000 export OUTDIR=./generated_files/$TEST_NAME mkdir -p ${OUTDIR} @TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential @BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override +export TEST_NAME=testGeneratorSegment10000_C +export OUTDIR=./generated_files/$TEST_NAME +mkdir -p ${OUTDIR} +@TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override --code=c + export TEST_NAME=testGeneratorWin32 export OUTDIR=./generated_files/$TEST_NAME mkdir -p ${OUTDIR} @TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential @BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=win32 --override +export TEST_NAME=testGeneratorWin32_C +export OUTDIR=./generated_files/$TEST_NAME +mkdir -p ${OUTDIR} +@TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=win32 --override --code=c + export TEST_NAME=testNamespace export OUTDIR=./generated_files/$TEST_NAME mkdir -p ${OUTDIR} @TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential -@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override --namespace=foobar +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override --baseclass=Bin2cFile2 --namespace=foobar + +export TEST_NAME=testNamespace_C +export OUTDIR=./generated_files/$TEST_NAME +mkdir -p ${OUTDIR} +@TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override --baseclass=Bin2cFile2 --namespace=foobar --code=c export TEST_NAME=testBaseClass export OUTDIR=./generated_files/$TEST_NAME @@ -135,6 +165,12 @@ mkdir -p ${OUTDIR} @TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential @BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override --baseclass=Resource +export TEST_NAME=testBaseClass_C +export OUTDIR=./generated_files/$TEST_NAME +mkdir -p ${OUTDIR} +@TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override --baseclass=Resource --namespace=tbc --code=c + export TEST_NAME=testEncodingOct export OUTDIR=./generated_files/$TEST_NAME mkdir -p ${OUTDIR} @@ -174,6 +210,14 @@ mkdir -p ${OUTDIR} @BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.1.bin --output=$OUTDIR --headerfile=_$TEST_NAME.1.h --identifier=testFileManager1 --managerfile=FileManager.h --override @BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.2.bin --output=$OUTDIR --headerfile=_$TEST_NAME.2.h --identifier=testFileManager2 --registerfile --override +export TEST_NAME=testFileManager_C +export OUTDIR=./generated_files/$TEST_NAME +mkdir -p ${OUTDIR} +@TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.1.bin --size=1000 --fill=random --seed=1 +@TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.2.bin --size=1000 --fill=random --seed=2 +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.1.bin --output=$OUTDIR --headerfile=_$TEST_NAME.1.h --identifier=testFileManager1 --managerfile=filemanager.h --override --code=c +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.2.bin --output=$OUTDIR --headerfile=_$TEST_NAME.2.h --identifier=testFileManager2 --registerfile --override --code=c + export TEST_NAME=testDir01 export OUTDIR=./generated_files/$TEST_NAME mkdir -p ${OUTDIR} From fa217683c62327d82fedc07b95287feadd0b8adf Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 18 May 2025 11:47:16 -0400 Subject: [PATCH 18/25] Modified C code generators to force the files to load in memory at initialization to mimic the behavior of c++ generated code. --- src/bin2cpp/ArrayGenerator.cpp | 3 +++ src/bin2cpp/SegmentGenerator.cpp | 3 +++ src/bin2cpp/StringGenerator.cpp | 3 +++ src/bin2cpp/Win32ResourceGenerator.cpp | 3 +++ 4 files changed, 12 insertions(+) diff --git a/src/bin2cpp/ArrayGenerator.cpp b/src/bin2cpp/ArrayGenerator.cpp index 43d5fba..cd37198 100644 --- a/src/bin2cpp/ArrayGenerator.cpp +++ b/src/bin2cpp/ArrayGenerator.cpp @@ -328,6 +328,9 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + fprintf(fout, " // load file by default on init as in c++ implementation"); + fprintf(fout, " file->load();\n"); if ( mContext.registerFiles ) { fprintf(fout, " \n"); diff --git a/src/bin2cpp/SegmentGenerator.cpp b/src/bin2cpp/SegmentGenerator.cpp index 35359b9..341216b 100755 --- a/src/bin2cpp/SegmentGenerator.cpp +++ b/src/bin2cpp/SegmentGenerator.cpp @@ -301,6 +301,9 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + fprintf(fout, " // load file by default on init as in c++ implementation"); + fprintf(fout, " file->load();\n"); if ( mContext.registerFiles ) { fprintf(fout, " \n"); diff --git a/src/bin2cpp/StringGenerator.cpp b/src/bin2cpp/StringGenerator.cpp index 7e433c1..e85eda8 100755 --- a/src/bin2cpp/StringGenerator.cpp +++ b/src/bin2cpp/StringGenerator.cpp @@ -311,6 +311,9 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + fprintf(fout, " // load file by default on init as in c++ implementation"); + fprintf(fout, " file->load();\n"); if ( mContext.registerFiles ) { diff --git a/src/bin2cpp/Win32ResourceGenerator.cpp b/src/bin2cpp/Win32ResourceGenerator.cpp index ac516ef..fcb8f05 100755 --- a/src/bin2cpp/Win32ResourceGenerator.cpp +++ b/src/bin2cpp/Win32ResourceGenerator.cpp @@ -354,6 +354,9 @@ namespace bin2cpp fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str()); fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str()); fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str()); + fprintf(fout, "\n"); + fprintf(fout, " // load file by default on init as in c++ implementation"); + fprintf(fout, " file->load();\n"); if ( mContext.registerFiles ) { From 7c40328ceca1149fd4bf92ba9be0840e42509e28 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 18 May 2025 13:17:56 -0400 Subject: [PATCH 19/25] Fixed warning `/home/runner/work/bin2cpp/bin2cpp/src/bin2cpp/main.cpp:226:22: warning: trigraph ??' ignored, use -trigraphs to enable [-Wtrigraphs]` on Linux and macOS. --- src/bin2cpp/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index 1ea7abc..1c9f272 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -223,11 +223,10 @@ void printUsage() " [a-zA-Z0-9] Matches any single letter (uppercase or lowercase) or digit.\n" "\n" " For example:\n" - " 'ker*##.???' would match files that starts with 'ker', and ends with 2 digits, a dot and then 3 characters." + " 'ker*##.\?\?\?' would match files that starts with 'ker', and ends with 2 digits, a dot and then 3 characters.\n" " --dir-include-filter=\"*.jpg:*.png\" would include all files whose file extension is 'jpg' or 'png'.\n" " --dir-exclude-filter=\"*.bak\" would exclude all backup files.\n" - " --dir-include-filter=\"*.log\" --dir-exclude-filter=\"debug.log\" would include all log files but not the one named 'debug.log'." - "\n"; + " --dir-include-filter=\"*.log\" --dir-exclude-filter=\"debug.log\" would include all log files but not the one named 'debug.log'.\n"; printf("%s", usage); } From 4dc8a8a585c96ef0edde986da346707582c3af86 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Sun, 18 May 2025 13:22:42 -0400 Subject: [PATCH 20/25] =?UTF-8?q?Fixed=20compilation=20error=20`/home/runn?= =?UTF-8?q?er/work/bin2cpp/bin2cpp/src/bin2cpp/main.cpp:243:33:=20error:?= =?UTF-8?q?=20cannot=20bind=20non-const=20lvalue=20reference=20of=20type?= =?UTF-8?q?=20=E2=80=98bin2cpp::INameProvider&=E2=80=99=20to=20an=20rvalue?= =?UTF-8?q?=20of=20type=20=E2=80=98bin2cpp::INameProvider=E2=80=99`=20on?= =?UTF-8?q?=20Linux=20and=20macOS.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin2cpp/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bin2cpp/main.cpp b/src/bin2cpp/main.cpp index 1c9f272..d5763f0 100755 --- a/src/bin2cpp/main.cpp +++ b/src/bin2cpp/main.cpp @@ -239,7 +239,8 @@ int main(int argc, char* argv[]) args.version = false; Context c; - INameProvider& nameProvider = LegacyNameProvider(); + LegacyNameProvider legacyNameProvider; + INameProvider& nameProvider = legacyNameProvider; std::string dummy; //help From 1be839d0d170414e94de8bebca37543d828d2f69 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Mon, 19 May 2025 11:34:26 -0400 Subject: [PATCH 21/25] Fixed a file generation bug where bin2cpp_unittest would start compiling before the the end of the generation script. This would create compilation failures since some required files were not generated yet. --- test/bin2cpp_unittest/CMakeLists.txt | 56 +++++++++++++++++++++------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/test/bin2cpp_unittest/CMakeLists.txt b/test/bin2cpp_unittest/CMakeLists.txt index badf315..43035a8 100644 --- a/test/bin2cpp_unittest/CMakeLists.txt +++ b/test/bin2cpp_unittest/CMakeLists.txt @@ -208,9 +208,26 @@ endif() set(TEMPLATE_SCRIPT_FILE ${BIN2CPP_UNITTEST_SOURCE_DIR}/generate_test_files.${SCRIPT_FILE_EXTENSION}.in) -# https://stackoverflow.com/questions/18427877/add-custom-build-step-in-cmake +# Define a dummy file to act as a stamp for file generation completion +set(GENERATION_STAMP ${GENERATED_TEST_FILES_DIR}/generated_files.stamp) + +# The script generates multiple files from a single command, but if I try to list all of them as OUTPUT of the add_custom_command it won't work. +# CMake assumes each output is independently produced, so it starts compiling as soon as any one is generated, not necessarily all. +# +# CMake tracks outputs individually, so even if I have `OUTPUT ${GENERATED_TEST_FILES}`, it sees each output as possibly ready at different times. +# When one appears on disk (even partially), it may trigger compilation of bin2cpp_unittest, before the script finishes generating all files. +# +# To work around this behavior, is using a stamp file which is created after the generation script has run which indicates to CMake we are ready to compile bin2cpp_unittest. +# Required steps: +# Only the stamp file is listed as OUTPUT. This prevents CMake from checking each generated file independently. +# The actual source files are listed as BYPRODUCTS, so CMake knows they will appear but doesn't rely on their timestamps individually. +# add_dependencies() ensures the executable only starts compiling after the stamp file is created, i.e., after the script finishes. +# +# To force CMake to regenerate the files, delete the stamp file. +# if (WIN32) - add_custom_command( OUTPUT ${GENERATED_TEST_FILES} + add_custom_command( OUTPUT ${GENERATION_STAMP} + BYPRODUCTS ${GENERATED_TEST_FILES} # Execute prebuild copy COMMAND ${CMAKE_COMMAND} -DBIN2CPP_TARGET_FILE=$ @@ -223,10 +240,17 @@ if (WIN32) # Execute generator script COMMAND echo Calling 'generate_test_files.bat' script... COMMAND cd /d ${CMAKE_CURRENT_BINARY_DIR} && call generate_test_files.bat + + # Tell CMake that we generated the last file of the series + COMMAND ${CMAKE_COMMAND} -E touch ${GENERATION_STAMP} + + COMMENT "Generating test files" + VERBATIM ) else() # Linux build - add_custom_command( OUTPUT ${GENERATED_TEST_FILES} + add_custom_command( OUTPUT ${GENERATION_STAMP} + BYPRODUCTS ${GENERATED_TEST_FILES} # Execute prebuild copy COMMAND ${CMAKE_COMMAND} -DBIN2CPP_TARGET_FILE=$ @@ -235,21 +259,23 @@ else() -DBIN2CPP_UNITTEST_PROJECT_DIR=${CMAKE_CURRENT_BINARY_DIR} -DBIN2CPP_UNITTEST_OUTPUT_DIR=${CMAKE_BINARY_DIR}/bin -P ${CMAKE_CURRENT_SOURCE_DIR}/generate_test_files.cmake - + # Execute generator script COMMAND echo Calling 'generate_test_files.sh' script... COMMAND cd ${CMAKE_CURRENT_BINARY_DIR} && ./generate_test_files.sh + + # Tell CMake that we generated the last file of the series + COMMAND ${CMAKE_COMMAND} -E touch ${GENERATION_STAMP} + + COMMENT "Generating test files" + VERBATIM ) endif() -# target build_test_files is always built -add_custom_target(build_test_files ALL - COMMAND echo "Building unit test files..." - - # If the files exists, then commands related to these files won't be executed - # DONOT let other target depends on the same OUTPUT as current target, - # or it may be bad when doing parallel make - DEPENDS ${GENERATED_TEST_FILES} +# Create a custom target that depends on the generated files +add_custom_target(generate_test_files + DEPENDS ${GENERATION_STAMP} + COMMENT "Ensuring file generation stamp exist" ) # Show all generated files in a common folder @@ -261,6 +287,9 @@ source_group("External Files" FILES ${CMAKE_SOURCE_DIR}/src/bin2cpp/wildcard.h ) +# Ensure source files are properly recognized as generated +set_source_files_properties(${GENERATED_TEST_FILES} PROPERTIES GENERATED TRUE) + add_executable(bin2cpp_unittest ${BIN2CPP_VERSION_HEADER} ${BIN2CPP_CONFIG_HEADER} @@ -288,7 +317,8 @@ add_executable(bin2cpp_unittest add_dependencies(bin2cpp_unittest bin2cpp) add_dependencies(bin2cpp_unittest testfilegenerator) -add_dependencies(bin2cpp_unittest build_test_files) +add_dependencies(bin2cpp_unittest generate_test_files) + # Unit test projects requires to link with pthread if also linking with gtest if(NOT WIN32) From c40c91c4b4d4b94c6db544dbedc07f4d2e9b6058 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Mon, 19 May 2025 23:02:29 +0000 Subject: [PATCH 22/25] Fixed warnings such as . --- src/bin2cpp/ArrayGenerator.cpp | 2 +- src/bin2cpp/SegmentGenerator.cpp | 2 +- src/bin2cpp/StringGenerator.cpp | 2 +- src/bin2cpp/Win32ResourceGenerator.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bin2cpp/ArrayGenerator.cpp b/src/bin2cpp/ArrayGenerator.cpp index cd37198..b43bfa2 100644 --- a/src/bin2cpp/ArrayGenerator.cpp +++ b/src/bin2cpp/ArrayGenerator.cpp @@ -312,7 +312,7 @@ namespace bin2cpp fprintf(fout, " return true;\n"); fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "inline void %s_init()\n", functionIdentifier.c_str()); + fprintf(fout, "static inline void %s_init()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " // remember we already initialized\n"); fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str()); diff --git a/src/bin2cpp/SegmentGenerator.cpp b/src/bin2cpp/SegmentGenerator.cpp index 341216b..071365d 100755 --- a/src/bin2cpp/SegmentGenerator.cpp +++ b/src/bin2cpp/SegmentGenerator.cpp @@ -285,7 +285,7 @@ namespace bin2cpp fprintf(fout, " return true;\n"); fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "inline void %s_init()\n", functionIdentifier.c_str()); + fprintf(fout, "static inline void %s_init()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " // remember we already initialized\n"); fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str()); diff --git a/src/bin2cpp/StringGenerator.cpp b/src/bin2cpp/StringGenerator.cpp index e85eda8..b3fe3af 100755 --- a/src/bin2cpp/StringGenerator.cpp +++ b/src/bin2cpp/StringGenerator.cpp @@ -295,7 +295,7 @@ namespace bin2cpp fprintf(fout, " return true;\n"); fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "inline void %s_init()\n", functionIdentifier.c_str()); + fprintf(fout, "static inline void %s_init()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " // remember we already initialized\n"); fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str()); diff --git a/src/bin2cpp/Win32ResourceGenerator.cpp b/src/bin2cpp/Win32ResourceGenerator.cpp index fcb8f05..574a8f5 100755 --- a/src/bin2cpp/Win32ResourceGenerator.cpp +++ b/src/bin2cpp/Win32ResourceGenerator.cpp @@ -338,7 +338,7 @@ namespace bin2cpp fprintf(fout, "}\n"); fprintf(fout, "\n"); - fprintf(fout, "inline void %s_init()\n", functionIdentifier.c_str()); + fprintf(fout, "static inline void %s_init()\n", functionIdentifier.c_str()); fprintf(fout, "{\n"); fprintf(fout, " // remember we already initialized\n"); fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str()); From dbc01d8e0cde8c1f62758d7d4f780a661a83fd13 Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Tue, 20 May 2025 02:05:49 +0000 Subject: [PATCH 23/25] Fixed compilation issues on Linux and macOS. --- src/bin2cpp/ManagerGenerator.cpp | 1 - test/bin2cpp_unittest/CMakeLists.txt | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bin2cpp/ManagerGenerator.cpp b/src/bin2cpp/ManagerGenerator.cpp index 5ca8853..fa38a8f 100644 --- a/src/bin2cpp/ManagerGenerator.cpp +++ b/src/bin2cpp/ManagerGenerator.cpp @@ -442,7 +442,6 @@ namespace bin2cpp fprintf(fout, " return false;\n"); fprintf(fout, " }\n"); fprintf(fout, " \n"); - fprintf(fout, " char path[32767] = { 0 };\n"); fprintf(fout, " snprintf(path, sizeof(path), \"%%s%%c%%s\", directory, PATH_SEPARATOR_CHAR, f->file_path);\n"); fprintf(fout, " \n"); fprintf(fout, " if (!%s_filemanager_create_parent_directories(path))\n", mContext.codeNamespace.c_str()); diff --git a/test/bin2cpp_unittest/CMakeLists.txt b/test/bin2cpp_unittest/CMakeLists.txt index 43035a8..ac6c4ba 100644 --- a/test/bin2cpp_unittest/CMakeLists.txt +++ b/test/bin2cpp_unittest/CMakeLists.txt @@ -163,8 +163,8 @@ set(GENERATED_TEST_FILES ${GENERATED_TEST_FILES_DIR}/testFileManager_C/_testFileManager_C.1.c ${GENERATED_TEST_FILES_DIR}/testFileManager_C/_testFileManager_C.2.h ${GENERATED_TEST_FILES_DIR}/testFileManager_C/_testFileManager_C.2.c - ${GENERATED_TEST_FILES_DIR}/testFileManager_C/FileManager.h - ${GENERATED_TEST_FILES_DIR}/testFileManager_C/FileManager.c + ${GENERATED_TEST_FILES_DIR}/testFileManager_C/filemanager.h + ${GENERATED_TEST_FILES_DIR}/testFileManager_C/filemanager.c ${GENERATED_TEST_FILES_DIR}/testDir01/sources/_img0001.h ${GENERATED_TEST_FILES_DIR}/testDir01/sources/_img0002.h ${GENERATED_TEST_FILES_DIR}/testDir01/sources/_img0003.h From 6dc1c4da8782120b4bd855d600a03d8c16a1300d Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Tue, 20 May 2025 02:26:34 +0000 Subject: [PATCH 24/25] Fixed a compilation bug on Linux where `generate_test_files.bat.in` and `generate_test_files.sh.in` were not synchronized. --- test/bin2cpp_unittest/generate_test_files.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bin2cpp_unittest/generate_test_files.sh.in b/test/bin2cpp_unittest/generate_test_files.sh.in index 9f767bd..f808d55 100755 --- a/test/bin2cpp_unittest/generate_test_files.sh.in +++ b/test/bin2cpp_unittest/generate_test_files.sh.in @@ -151,7 +151,7 @@ export TEST_NAME=testNamespace export OUTDIR=./generated_files/$TEST_NAME mkdir -p ${OUTDIR} @TESTFILEGENERATOR_TARGET_FILE@ --file=$OUTDIR/$TEST_NAME.bin --size=10000 --fill=sequential -@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override --baseclass=Bin2cFile2 --namespace=foobar +@BIN2CPP_TARGET_FILE@ --noheader --file=$OUTDIR/$TEST_NAME.bin --output=$OUTDIR --headerfile=_$TEST_NAME.h --identifier=$TEST_NAME --chunksize=450 --generator=segment --override --namespace=foobar export TEST_NAME=testNamespace_C export OUTDIR=./generated_files/$TEST_NAME From 9e91c17ec8c0a71551df42af2ed76f063aa4f5da Mon Sep 17 00:00:00 2001 From: Antoine Beauchamp Date: Tue, 20 May 2025 21:25:25 -0400 Subject: [PATCH 25/25] * Fixed issue #53: Generate only C code. --- CHANGES | 2 ++ README.md | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index a48c8ca..892bec6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ Changes for 3.1.0: +* New feature: Support for generating C code. * Fixed issue #29: Create arguments to filter files found with '--dir' argument. +* Fixed issue #53: Generate only C code. * Fixed issue #63: Context class redesign. Move arguments handling into a Context class. * Fixed issue #64: Remove build artifacts of samples from installation packages. * Fixed issue #72: Move the code FileManager class generation code into its own IGenerator implementation. diff --git a/README.md b/README.md index d714cb0..8b44bb0 100644 --- a/README.md +++ b/README.md @@ -88,12 +88,12 @@ The following section shows how to use bin2cpp with code examples: ``` bin2cpp --file= --output= [--headerfile=] [--identifier=] [--generator=] [--encoding=] [--chunksize=] [--namespace=] - [--baseclass=] [--managerfile=] [--registerfile] - [--reportedfilepath=] [--override] [--noheader] [--quiet] + [--baseclass=] [--managerfile=] [--registerfile] [--code] + [--reportedfilepath=] [--plainoutput] [--override] [--noheader] [--quiet] bin2cpp --dir= --output= [--keepdirs] [--generator=] [--encoding=] [--chunksize=] [--namespace=] - [--baseclass=] [--managerfile=] [--registerfile] - [--dirincludefilter=] [--direxcludefilter=] + [--baseclass=] [--managerfile=] [--registerfile] [--code] + [--dirincludefilter=] [--direxcludefilter=] [--override] [--noheader] [--quiet] bin2cpp --help bin2cpp --version @@ -111,8 +111,8 @@ bin2cpp --version | --generator=<name> | Name of the generator to use. Possible values are 'segment', 'string', 'array' and 'win32'.
[default: segment] | | --encoding=<name> | Name of the binary to string literal encoding to use. Possible values are 'oct' and 'hex'.
[default: oct] | | --chunksize=<value> | Size in bytes of each string segments (bytes per LoC).
[default: 200] | -| --baseclass=<name> | The name of the interface for embedded files.
[default: File] | -| --namespace=<name> | The namespace of the generated source code.
[default: bin2cpp] | +| --baseclass=<name> | The name of the interface for embedded files. [default: File]
For C generated code, this parameter is for naming the File structure. [default: Bin2cFile] | +| --namespace=<name> | The namespace of the generated source code. [default: bin2cpp]
For C generated code, this parameter is for setting the prefix of all function names. [default: bin2c] | | --reportedfilepath=<path> | The relative reported path of the File. Path returned when calling method getFilePath() of the File class. Automatically calculated when --dir mode is used.
ie: images/DCIM/IMG_0001.jpg | | --managerfile=<path> | File name or relative path of the generated C++ header file for the FileManager class.
ie: FileManager.h. | | --registerfile | Register the generated file to the FileManager class. This flags is automatically set when parameter 'managerfile' is specified. | @@ -120,6 +120,7 @@ bin2cpp --version | --direxcludefilter=<value>| Set a negative filter on the input directory to skip files matching the filter. Wildcard characters are accepted. Separate each filter with the character ':'. Valid only when --dir is used. See wildcard characters definition below. The exclude filter has precedence over the include filter. | | --keepdirs | Keep the directory structure. Forces the output files to have the same directory structure as the input files. Valid only when --dir is used. | | --plainoutput | Print the encoded string in plain format to stdout. Useful for scripts and integration with third party application. | +| --code | Define the programming language output for code generation. Supported values are `c`, `cpp` or `c++`. | | --override | Tells bin2cpp to overwrite the destination files. | | --noheader | Do not print program header to standard output. | | --quiet | Do not log any message to standard output. |