Skip to content

Commit 3a5f0d2

Browse files
authored
Merge pull request #79 from end2endzone/feature-issue53
Fixes #53 - Generate only C code.
2 parents 6ab0917 + 9e91c17 commit 3a5f0d2

32 files changed

+1881
-128
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Changes for 3.1.0:
22

3+
* New feature: Support for generating C code.
34
* Fixed issue #29: Create arguments to filter files found with '--dir' argument.
5+
* Fixed issue #53: Generate only C code.
46
* Fixed issue #63: Context class redesign. Move arguments handling into a Context class.
57
* Fixed issue #64: Remove build artifacts of samples from installation packages.
68
* Fixed issue #72: Move the code FileManager class generation code into its own IGenerator implementation.

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,12 @@ The following section shows how to use bin2cpp with code examples:
8888
```
8989
bin2cpp --file=<path> --output=<path> [--headerfile=<name>] [--identifier=<name>]
9090
[--generator=<name>] [--encoding=<name>] [--chunksize=<value>] [--namespace=<value>]
91-
[--baseclass=<name>] [--managerfile=<name>] [--registerfile]
92-
[--reportedfilepath=<value>] [--override] [--noheader] [--quiet]
91+
[--baseclass=<name>] [--managerfile=<name>] [--registerfile] [--code]
92+
[--reportedfilepath=<value>] [--plainoutput] [--override] [--noheader] [--quiet]
9393
bin2cpp --dir=<path> --output=<path> [--keepdirs]
9494
[--generator=<name>] [--encoding=<name>] [--chunksize=<value>] [--namespace=<value>]
95-
[--baseclass=<name>] [--managerfile=<name>] [--registerfile]
96-
[--dirincludefilter=<value>] [--direxcludefilter=<value>]
95+
[--baseclass=<name>] [--managerfile=<name>] [--registerfile] [--code]
96+
[--dirincludefilter=<value>] [--direxcludefilter=<value>]
9797
[--override] [--noheader] [--quiet]
9898
bin2cpp --help
9999
bin2cpp --version
@@ -111,15 +111,16 @@ bin2cpp --version
111111
| --generator=&lt;name&gt; | Name of the generator to use. Possible values are 'segment', 'string', 'array' and 'win32'.<br>[default: segment] |
112112
| --encoding=&lt;name&gt; | Name of the binary to string literal encoding to use. Possible values are 'oct' and 'hex'.<br>[default: oct] |
113113
| --chunksize=&lt;value&gt; | Size in bytes of each string segments (bytes per LoC).<br>[default: 200] |
114-
| --baseclass=&lt;name&gt; | The name of the interface for embedded files.<br>[default: File] |
115-
| --namespace=&lt;name&gt; | The namespace of the generated source code.<br>[default: bin2cpp] |
114+
| --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] |
115+
| --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] |
116116
| --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 |
117117
| --managerfile=&lt;path&gt; | File name or relative path of the generated C++ header file for the FileManager class.<br>ie: FileManager.h. |
118118
| --registerfile | Register the generated file to the FileManager class. This flags is automatically set when parameter 'managerfile' is specified. |
119119
| --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. |
120120
| --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. |
121121
| --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. |
122122
| --plainoutput | Print the encoded string in plain format to stdout. Useful for scripts and integration with third party application. |
123+
| --code | Define the programming language output for code generation. Supported values are `c`, `cpp` or `c++`. |
123124
| --override | Tells bin2cpp to overwrite the destination files. |
124125
| --noheader | Do not print program header to standard output. |
125126
| --quiet | Do not log any message to standard output. |

src/bin2cpp/ArrayGenerator.cpp

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,15 @@ namespace bin2cpp
131131
delete[] buffer;
132132
buffer = NULL;
133133

134-
//write cpp file footer
134+
//write cpp source file footer
135135
fprintf(cpp, " return (const char *)buffer;\n");
136136
fprintf(cpp, " }\n");
137137
fprintf(cpp, "%s", getSaveMethodTemplate().c_str());
138138
fprintf(cpp, " };\n");
139139
fprintf(cpp, " const %s & %s() { static %s _instance; return _instance; }\n", getContext().baseClass.c_str(), getterFunctionName.c_str(), className.c_str());
140140
if (mContext.registerFiles)
141141
{
142-
std::string fileManagerTemplate = getFileManagerRegistrationTemplate();
142+
std::string fileManagerTemplate = getCppFileManagerRegistrationImplementationTemplate();
143143
fprintf(cpp, "%s", fileManagerTemplate.c_str());
144144
}
145145
fprintf(cpp, "}; //%s\n", getContext().codeNamespace.c_str());
@@ -192,4 +192,166 @@ namespace bin2cpp
192192
return true;
193193
}
194194

195+
bool ArrayGenerator::createCSourceFile(const char* file_path)
196+
{
197+
//check if input file exists
198+
FILE* input = fopen(mContext.inputFilePath.c_str(), "rb");
199+
if ( !input )
200+
return false;
201+
202+
//Lowercase function identifier
203+
std::string functionIdentifier = ra::strings::Lowercase(mContext.functionIdentifier);
204+
205+
//Build header and cpp file path
206+
std::string headerPath = getHeaderFilePath(file_path);
207+
std::string sourcePath = file_path;
208+
209+
//create c source file
210+
FILE* fout = fopen(sourcePath.c_str(), "w");
211+
if ( !fout )
212+
{
213+
fclose(input);
214+
return false;
215+
}
216+
217+
//determine file properties
218+
uint32_t fileSize = ra::filesystem::GetFileSize(input);
219+
std::string filename = ra::filesystem::GetFilename(mContext.inputFilePath.c_str());
220+
//long lastSegmentSize = fileSize%chunk_size;
221+
//size_t numSegments = fileSize/chunk_size + (lastSegmentSize == 0 ? 0 : 1);
222+
223+
//Build class name
224+
std::string className = getClassName();
225+
226+
//Build function
227+
std::string getterFunctionName = getGetterFunctionName();
228+
229+
//Build FileManager class template
230+
std::string manager = mContext.managerHeaderFilename;
231+
232+
//write c file heading
233+
fprintf(fout, "%s", getHeaderTemplate().c_str());
234+
fprintf(fout, "#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)\n");
235+
fprintf(fout, "#define _CRT_SECURE_NO_WARNINGS\n");
236+
fprintf(fout, "#endif\n");
237+
fprintf(fout, "#include \"%s\"\n", mContext.headerFilename.c_str());
238+
fprintf(fout, "#include <stdlib.h> // for malloc\n");
239+
fprintf(fout, "#include <string.h> // for memset\n");
240+
fprintf(fout, "#include <stdio.h> // for fopen\n");
241+
242+
fprintf(fout, "static %s %s_file = { 0 };\n", mContext.baseClass.c_str(), functionIdentifier.c_str());
243+
fprintf(fout, "static bool %s_initialized = false;\n", functionIdentifier.c_str());
244+
fprintf(fout, "\n");
245+
246+
// File registration predeclaration code
247+
fprintf(fout, "%s", getCFileManagerRegistrationPredeclarationTemplate().c_str());
248+
249+
fprintf(fout, "bool %s_load()\n", functionIdentifier.c_str());
250+
fprintf(fout, "{\n");
251+
fprintf(fout, " if ( %s_file.buffer )\n", functionIdentifier.c_str());
252+
fprintf(fout, " return true;\n");
253+
fprintf(fout, " static const unsigned char static_buffer[] = {\n");
254+
255+
//create buffer for each chunks from input buffer
256+
int numLinePrinted = 0;
257+
unsigned char* buffer = new unsigned char[getContext().chunkSize];
258+
while ( !feof(input) )
259+
{
260+
//read a chunk of the file
261+
size_t readSize = fread(buffer, 1, getContext().chunkSize, input);
262+
263+
bool isLastChunk = !(readSize == getContext().chunkSize);
264+
265+
if ( readSize > 0 )
266+
{
267+
if ( numLinePrinted > 0 )
268+
{
269+
//end previous line
270+
fprintf(fout, ",\n");
271+
}
272+
273+
//output
274+
fprintf(fout, " %s", ra::code::cpp::ToCppCharactersArray(buffer, readSize).c_str());
275+
numLinePrinted++;
276+
}
277+
278+
//end the array. all the file content is printed
279+
if ( isLastChunk )
280+
{
281+
fprintf(fout, "\n");
282+
fprintf(fout, " };\n");
283+
}
284+
}
285+
delete[] buffer;
286+
buffer = NULL;
287+
288+
//write c source file footer
289+
fprintf(fout, "\n");
290+
fprintf(fout, " %s_file.buffer = static_buffer;\n", functionIdentifier.c_str());
291+
fprintf(fout, " return true;\n");
292+
fprintf(fout, "}\n");
293+
294+
fprintf(fout, "\n");
295+
296+
fprintf(fout, "void %s_free()\n", functionIdentifier.c_str());
297+
fprintf(fout, "{\n");
298+
fprintf(fout, " %s_file.buffer = NULL;\n", functionIdentifier.c_str());
299+
fprintf(fout, "}\n");
300+
fprintf(fout, "\n");
301+
fprintf(fout, "bool %s_save(const char* path)\n", functionIdentifier.c_str());
302+
fprintf(fout, "{\n");
303+
fprintf(fout, " if ( !%s_file.buffer )\n", functionIdentifier.c_str());
304+
fprintf(fout, " return false;\n");
305+
fprintf(fout, " FILE* f = fopen(path, \"wb\");\n");
306+
fprintf(fout, " if ( !f )\n");
307+
fprintf(fout, " return false;\n");
308+
fprintf(fout, " size_t write_size = fwrite(%s_file.buffer, 1, %s_file.size, f);\n", functionIdentifier.c_str(), functionIdentifier.c_str());
309+
fprintf(fout, " fclose(f);\n");
310+
fprintf(fout, " if ( write_size != %s_file.size )\n", functionIdentifier.c_str());
311+
fprintf(fout, " return false;\n");
312+
fprintf(fout, " return true;\n");
313+
fprintf(fout, "}\n");
314+
fprintf(fout, "\n");
315+
fprintf(fout, "static inline void %s_init()\n", functionIdentifier.c_str());
316+
fprintf(fout, "{\n");
317+
fprintf(fout, " // remember we already initialized\n");
318+
fprintf(fout, " if ( %s_initialized )\n", functionIdentifier.c_str());
319+
fprintf(fout, " return;\n");
320+
fprintf(fout, " %s_initialized = true;\n", functionIdentifier.c_str());
321+
fprintf(fout, "\n");
322+
fprintf(fout, " // initialize\n");
323+
fprintf(fout, " %s* file = &%s_file;\n", mContext.baseClass.c_str(), functionIdentifier.c_str());
324+
fprintf(fout, " file->size = %uULL;\n", fileSize);
325+
fprintf(fout, " file->file_name = \"%s\";\n", getFileClassFileName().c_str());
326+
fprintf(fout, " file->file_path = \"%s\";\n", getFileClassFilePath().c_str());
327+
fprintf(fout, " file->buffer = NULL;\n");
328+
fprintf(fout, " file->load = %s_load;\n", functionIdentifier.c_str());
329+
fprintf(fout, " file->unload = %s_free;\n", functionIdentifier.c_str());
330+
fprintf(fout, " file->save = %s_save;\n", functionIdentifier.c_str());
331+
fprintf(fout, "\n");
332+
fprintf(fout, " // load file by default on init as in c++ implementation");
333+
fprintf(fout, " file->load();\n");
334+
if ( mContext.registerFiles )
335+
{
336+
fprintf(fout, " \n");
337+
fprintf(fout, " // register when loaded if static initialisation does not work\n");
338+
fprintf(fout, " %s_filemanager_register_file(file);\n", mContext.codeNamespace.c_str());
339+
}
340+
fprintf(fout, "}\n");
341+
fprintf(fout, "\n");
342+
fprintf(fout, "%s* %s(void)\n", mContext.baseClass.c_str(), getGetterFunctionName().c_str());
343+
fprintf(fout, "{\n");
344+
fprintf(fout, " %s_init();\n", functionIdentifier.c_str());
345+
fprintf(fout, " return &%s_file;\n", functionIdentifier.c_str());
346+
fprintf(fout, "}\n");
347+
348+
// File registration implementation code
349+
fprintf(fout, "%s", getCFileManagerRegistrationImplementationTemplate().c_str());
350+
351+
fclose(input);
352+
fclose(fout);
353+
354+
return true;
355+
}
356+
195357
}; //bin2cpp

src/bin2cpp/ArrayGenerator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ namespace bin2cpp
4141
virtual ~ArrayGenerator();
4242
virtual const char * getName() const;
4343
virtual bool createCppSourceFile(const char * cpp_file_path);
44+
virtual bool createCSourceFile(const char * cpp_file_path);
4445
virtual bool printFileContent();
4546
};
4647

0 commit comments

Comments
 (0)