Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d8e1a6e
Renamed function generateFile() to generateOutputFile().
end2endzone May 8, 2025
a8a5fa2
Moved bin2cpp::Dictionary definition to types.h.
end2endzone May 8, 2025
8d89e58
Created interface `INameProvider`. Moved functions `getDefaultFunctio…
end2endzone May 11, 2025
fc9feda
Created CodeGenerationEnum enum and supporting function `parseCode()`…
end2endzone May 11, 2025
22dbb60
Implemented `--code` argument support to specify the programming lang…
end2endzone May 11, 2025
b2c1416
Modified IGenerator interface to add support for generating C source …
end2endzone May 11, 2025
2253490
Created a valid implementation of IGenerator::createCHeaderFile() in …
end2endzone May 11, 2025
bcfbe55
Implemented C code generation support for ArrayGenerator, SegmentGene…
end2endzone May 12, 2025
2f61bc5
Implemented register files support for C code generators.
end2endzone May 16, 2025
1c0b777
Updaed samples file for more examples.
end2endzone May 17, 2025
f223179
Implemented `--registerfile` command support for C generated code.
end2endzone May 17, 2025
3ee8d57
Fixes C code generation error with `\0` code.
end2endzone May 17, 2025
a37e1e9
Fixed hardcoded `Bin2cFile` string for `--baseclass` command for C ge…
end2endzone May 17, 2025
5471797
* Implemented `--namespace` command support for C generated code.
end2endzone May 17, 2025
21fe6d8
Fixed a bug with Win32ResourceGenerator where the code was using `Fin…
end2endzone May 18, 2025
be7e394
Fixed a bug with commands `--managerfile=filemanager.h --code=c` wher…
end2endzone May 18, 2025
ca77dd8
Modified scripts `generate_test_files.bat.in` and `generate_test_file…
end2endzone May 18, 2025
fa21768
Modified C code generators to force the files to load in memory at in…
end2endzone May 18, 2025
7c40328
Fixed warning `/home/runner/work/bin2cpp/bin2cpp/src/bin2cpp/main.cpp…
end2endzone May 18, 2025
4dc8a8a
Fixed compilation error `/home/runner/work/bin2cpp/bin2cpp/src/bin2cp…
end2endzone May 18, 2025
1be839d
Fixed a file generation bug where bin2cpp_unittest would start compil…
end2endzone May 19, 2025
c40c91c
Fixed warnings such as .
end2endzone May 19, 2025
dbc01d8
Fixed compilation issues on Linux and macOS.
end2endzone May 20, 2025
6dc1c4d
Fixed a compilation bug on Linux where `generate_test_files.bat.in` a…
end2endzone May 20, 2025
9e91c17
* Fixed issue #53: Generate only C code.
end2endzone May 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ The following section shows how to use bin2cpp with code examples:
```
bin2cpp --file=<path> --output=<path> [--headerfile=<name>] [--identifier=<name>]
[--generator=<name>] [--encoding=<name>] [--chunksize=<value>] [--namespace=<value>]
[--baseclass=<name>] [--managerfile=<name>] [--registerfile]
[--reportedfilepath=<value>] [--override] [--noheader] [--quiet]
[--baseclass=<name>] [--managerfile=<name>] [--registerfile] [--code]
[--reportedfilepath=<value>] [--plainoutput] [--override] [--noheader] [--quiet]
bin2cpp --dir=<path> --output=<path> [--keepdirs]
[--generator=<name>] [--encoding=<name>] [--chunksize=<value>] [--namespace=<value>]
[--baseclass=<name>] [--managerfile=<name>] [--registerfile]
[--dirincludefilter=<value>] [--direxcludefilter=<value>]
[--baseclass=<name>] [--managerfile=<name>] [--registerfile] [--code]
[--dirincludefilter=<value>] [--direxcludefilter=<value>]
[--override] [--noheader] [--quiet]
bin2cpp --help
bin2cpp --version
Expand All @@ -111,15 +111,16 @@ bin2cpp --version
| --generator=&lt;name&gt; | Name of the generator to use. Possible values are 'segment', 'string', 'array' and 'win32'.<br>[default: segment] |
| --encoding=&lt;name&gt; | Name of the binary to string literal encoding to use. Possible values are 'oct' and 'hex'.<br>[default: oct] |
| --chunksize=&lt;value&gt; | Size in bytes of each string segments (bytes per LoC).<br>[default: 200] |
| --baseclass=&lt;name&gt; | The name of the interface for embedded files.<br>[default: File] |
| --namespace=&lt;name&gt; | The namespace of the generated source code.<br>[default: bin2cpp] |
| --baseclass=&lt;name&gt; | The name of the interface for embedded files. [default: File]<br>For C generated code, this parameter is for naming the File structure. [default: Bin2cFile] |
| --namespace=&lt;name&gt; | The namespace of the generated source code. [default: bin2cpp]<br>For C generated code, this parameter is for setting the prefix of all function names. [default: bin2c] |
| --reportedfilepath=&lt;path&gt; | The relative reported path of the File. Path returned when calling method getFilePath() of the File class. Automatically calculated when --dir mode is used.<br>ie: images/DCIM/IMG_0001.jpg |
| --managerfile=&lt;path&gt; | File name or relative path of the generated C++ header file for the FileManager class.<br>ie: FileManager.h. |
| --registerfile | Register the generated file to the FileManager class. This flags is automatically set when parameter 'managerfile' is specified. |
| --dirincludefilter=&lt;value&gt;| Set a positive filter on the input directory to only select 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. |
| --direxcludefilter=&lt;value&gt;| 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. |
Expand Down
166 changes: 164 additions & 2 deletions src/bin2cpp/ArrayGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@ 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());
fprintf(cpp, " };\n");
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());
Expand Down Expand Up @@ -192,4 +192,166 @@ 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;

//Lowercase 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 <stdlib.h> // for malloc\n");
fprintf(fout, "#include <string.h> // for memset\n");
fprintf(fout, "#include <stdio.h> // 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");

// File registration predeclaration code
fprintf(fout, "%s", getCFileManagerRegistrationPredeclarationTemplate().c_str());

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, "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());
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, " // load file by default on init as in c++ implementation");
fprintf(fout, " file->load();\n");
if ( mContext.registerFiles )
{
fprintf(fout, " \n");
fprintf(fout, " // register when loaded if static initialisation does not work\n");
fprintf(fout, " %s_filemanager_register_file(file);\n", mContext.codeNamespace.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");

// File registration implementation code
fprintf(fout, "%s", getCFileManagerRegistrationImplementationTemplate().c_str());

fclose(input);
fclose(fout);

return true;
}

}; //bin2cpp
1 change: 1 addition & 0 deletions src/bin2cpp/ArrayGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
};

Expand Down
Loading