first commit
This commit is contained in:
commit
81df594082
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
resource_embedder
|
||||||
|
*.o
|
||||||
|
*.exe
|
||||||
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Resource Embedder
|
||||||
|
Program that transforms files to array definitions in C.
|
||||||
|
|
||||||
|
## building
|
||||||
|
```shell
|
||||||
|
./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## usage
|
||||||
|
```shell
|
||||||
|
./resource_embedder -o src/embedded_resources.h -d res -i res/file1 -i res/file2 -i res/file3
|
||||||
|
```
|
||||||
|
This command generates array definitions of files from `res/` in `src/embedded_resources.h`. EmbeddedFile.path properties wouldn't contain directory `res/`.
|
||||||
|
|
||||||
|
Complete list of command line options could be shown using `-h flag`
|
||||||
7
build.sh
Normal file
7
build.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#/bin/sh
|
||||||
|
set -e
|
||||||
|
echo 'compiling resource_embedder...'
|
||||||
|
set -x
|
||||||
|
cc -Wall -Wextra -O2 resource_embedder.c -o resource_embedder
|
||||||
|
set +x
|
||||||
|
echo 'done'
|
||||||
262
resource_embedder.c
Normal file
262
resource_embedder.c
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// the program writes generated text to stdout
|
||||||
|
// other messages must be sent to stderr
|
||||||
|
#define printf USE_FPRINTF!!!
|
||||||
|
|
||||||
|
#define exit_with_error(FORMAT, ARGS...) ({ \
|
||||||
|
fprintf(stderr, "\e[91m\nerror: "FORMAT"\n", ## ARGS); \
|
||||||
|
exit(4); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define argis(STR) streq(arg, STR) || \
|
||||||
|
streq(arg, "-"STR) || \
|
||||||
|
streq(arg, "--"STR)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// STR FUNCTIONS //
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool streq(const char* key0,const char* key1){
|
||||||
|
if(!key0) return key1 ? false : true;
|
||||||
|
if(!key1) return false;
|
||||||
|
while(*key0&&*key1)
|
||||||
|
if(*key0++ != *key1++)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* basedir_exclude(const char* path, const char* basename){
|
||||||
|
int len=strlen(path);
|
||||||
|
int base_len=strlen(basename);
|
||||||
|
int i=0;
|
||||||
|
if(len>0 && base_len>0){
|
||||||
|
if(basename[base_len-1]=='/' || basename[base_len-1]=='\\')
|
||||||
|
base_len--; // remove trailing path separator
|
||||||
|
if(len>base_len){
|
||||||
|
while(i<base_len){
|
||||||
|
if(path[i]!=basename[i])
|
||||||
|
break;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if(i<base_len || basename[i]!='/' || basename[i]!='\\')
|
||||||
|
i=0;
|
||||||
|
else i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int rzlt_len=len-i;
|
||||||
|
char* rzlt=malloc(rzlt_len+1);
|
||||||
|
memcpy(rzlt, path+i, rzlt_len);
|
||||||
|
return rzlt;
|
||||||
|
}
|
||||||
|
|
||||||
|
///@returns ptr to string of <count> spaces
|
||||||
|
char* mult_space(int count){
|
||||||
|
char* _mult_space_buf=malloc(count+1);
|
||||||
|
_mult_space_buf[count]=0;
|
||||||
|
memset(_mult_space_buf, ' ', count);
|
||||||
|
return _mult_space_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_line(bool print_lines, bool start_new_line){
|
||||||
|
if(!print_lines)
|
||||||
|
return;
|
||||||
|
fflush(stdout);
|
||||||
|
if(start_new_line)
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "------------------------------------------------------------\n");
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// WRITE CODE //
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool _first_file_processed=false;
|
||||||
|
unsigned int _input_files_n=0;
|
||||||
|
|
||||||
|
void process_file(const char* input_file_path,
|
||||||
|
const char* embedded_file_path,
|
||||||
|
FILE* out_file,
|
||||||
|
const char* out_file_path)
|
||||||
|
{
|
||||||
|
bool print_lines=streq(out_file_path, "this_file");
|
||||||
|
|
||||||
|
if(!_first_file_processed){
|
||||||
|
print_line(print_lines, false);
|
||||||
|
|
||||||
|
int onml=strlen(out_file_path);
|
||||||
|
if(onml>43) onml=0;
|
||||||
|
char* _sp1=mult_space(43-onml);
|
||||||
|
fprintf(out_file,
|
||||||
|
// "////////////////////////////////////////////////////////////\n"
|
||||||
|
// "// //\n"
|
||||||
|
// "//%s%s%s//\n"
|
||||||
|
// "// //\n"
|
||||||
|
"////////////////////////////////////////////////////////////\n"
|
||||||
|
"// This file has been generated by resource_embedder //\n"
|
||||||
|
"// src: https://github.com/Timerix22/resource_embedder //\n"
|
||||||
|
"////////////////////////////////////////////////////////////\n"
|
||||||
|
"// USAGE: //\n"
|
||||||
|
"// Put inside any .c file //\n"
|
||||||
|
"// #define EMBEDDED_RESOURCE_POSTFIX your_postfix //\n"
|
||||||
|
"// #include \"%s\"%s//\n"
|
||||||
|
"// //\n"
|
||||||
|
"// Then you can access embedded files through //\n"
|
||||||
|
"// EmbeddedResourceFile_table_your_postfix. You can put //\n"
|
||||||
|
"// table content into a hashtable or get it by index. //\n"
|
||||||
|
"////////////////////////////////////////////////////////////\n"
|
||||||
|
"\n",
|
||||||
|
// mult_space(28-onml/2), outname, mult_space(28-onml/2+onml%2),
|
||||||
|
out_file_path, _sp1);
|
||||||
|
free(_sp1);
|
||||||
|
fprintf(out_file,
|
||||||
|
"typedef unsigned char _byte;\n"
|
||||||
|
"\n"
|
||||||
|
"typedef struct {\n"
|
||||||
|
" char* path;\n"
|
||||||
|
" _byte* data;\n"
|
||||||
|
" unsigned long long size;\n"
|
||||||
|
"} EmbeddedResourceFile;\n"
|
||||||
|
"\n"
|
||||||
|
"#ifndef _EmbeddedResourceFile_table\n"
|
||||||
|
"#ifdef EMBEDDED_RESOURCE_POSTFIX\n"
|
||||||
|
" #define _EmbeddedResourceFile_table \\\n"
|
||||||
|
" EmbeddedResourceFile_table##EMBEDDED_RESOURCE_POSTFIX\n"
|
||||||
|
" #define _EmbeddedResourceFile_table_count \\\n"
|
||||||
|
" EmbeddedResourceFile_table##EMBEDDED_RESOURCE_POSTFIX##_count\n"
|
||||||
|
"#else\n"
|
||||||
|
" #define _EmbeddedResourceFile_table \\\n"
|
||||||
|
" EmbeddedResourceFile_table\n"
|
||||||
|
" #define _EmbeddedResourceFile_table_count \\\n"
|
||||||
|
" EmbeddedResourceFile_table_count\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#endif\n"
|
||||||
|
"extern EmbeddedResourceFile _EmbeddedResourceFile_table[];\n"
|
||||||
|
"extern unsigned int _EmbeddedResourceFile_table_count;"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"EmbeddedResourceFile _EmbeddedResourceFile_table[]={\n");
|
||||||
|
print_line(print_lines, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "reading file %s\n", input_file_path);
|
||||||
|
print_line(print_lines, false);
|
||||||
|
|
||||||
|
|
||||||
|
FILE* input_file=fopen(input_file_path, "rb");
|
||||||
|
if(input_file==NULL)
|
||||||
|
exit_with_error("can't open file %s", input_file_path);
|
||||||
|
|
||||||
|
if(_first_file_processed)
|
||||||
|
fprintf(out_file, ",\n");
|
||||||
|
// writing input file code header
|
||||||
|
fprintf(out_file,
|
||||||
|
" {\n"
|
||||||
|
" .path=(char*)\"%s\",\n"
|
||||||
|
" .data=(_byte[]){",
|
||||||
|
embedded_file_path);
|
||||||
|
|
||||||
|
// writing input file content
|
||||||
|
int byte=0;
|
||||||
|
unsigned long long size=0;
|
||||||
|
while( (byte=fgetc(input_file)) != EOF ){
|
||||||
|
if(size!=0)
|
||||||
|
fprintf(out_file, ",");
|
||||||
|
if(size%16==0)
|
||||||
|
fprintf(out_file, "\n ");
|
||||||
|
fprintf(out_file, "0x%X", byte);
|
||||||
|
size+=1;
|
||||||
|
}
|
||||||
|
fprintf(out_file,
|
||||||
|
"\n },\n"
|
||||||
|
" .size=%llu\n"
|
||||||
|
" }",
|
||||||
|
size);
|
||||||
|
fflush(out_file);
|
||||||
|
|
||||||
|
print_line(print_lines,true);
|
||||||
|
if(ferror(input_file)){
|
||||||
|
perror("unexpected end of stream: ");
|
||||||
|
exit_with_error("input read error");
|
||||||
|
}
|
||||||
|
fclose(input_file);
|
||||||
|
|
||||||
|
fprintf(stderr, "read %llu bytes\n", size);
|
||||||
|
|
||||||
|
_first_file_processed=true;
|
||||||
|
_input_files_n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// MAIN //
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int main(const int argc, const char * const* argv){
|
||||||
|
FILE* out_file=NULL;
|
||||||
|
const char* out_file_path=NULL;
|
||||||
|
const char* basedir="";
|
||||||
|
|
||||||
|
for(int i=1; i<argc; i++){
|
||||||
|
const char* arg=argv[i];
|
||||||
|
print_line(true, false);
|
||||||
|
fprintf(stderr, "arg: %s\n", arg);
|
||||||
|
|
||||||
|
if(argis("h") || argis("help")){
|
||||||
|
fprintf(stderr, "Usage:\n"
|
||||||
|
" resource_embedder [options] [file_options] -i input_file [[file_options] -i input_file]...\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -o output file path (default=stdout)\n"
|
||||||
|
"File options:\n"
|
||||||
|
" -d base dir path that will be removed from compiled strings\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(argis("o")){
|
||||||
|
const char* file_path=argv[++i];
|
||||||
|
if(out_file!=NULL)
|
||||||
|
exit_with_error("can't set out_file to %s, because it is already set to %s",
|
||||||
|
file_path, out_file_path);
|
||||||
|
out_file_path=file_path;
|
||||||
|
out_file=fopen(out_file_path, "wb");
|
||||||
|
if(out_file==NULL)
|
||||||
|
exit_with_error("can't open file %s", out_file_path);
|
||||||
|
fprintf(stderr, "output file has been set to %s\n", out_file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(argis("i")){
|
||||||
|
const char* input_file_path=argv[++i];
|
||||||
|
if(out_file==NULL){
|
||||||
|
out_file=stdout;
|
||||||
|
out_file_path="this_file";
|
||||||
|
}
|
||||||
|
char* embedded_path=basedir_exclude(input_file_path, basedir);
|
||||||
|
fprintf(stderr, "input file path: %s\n", arg);
|
||||||
|
fprintf(stderr, "embedded path: %s\n", embedded_path);
|
||||||
|
process_file(input_file_path, embedded_path, out_file, out_file_path);
|
||||||
|
free(embedded_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
else exit_with_error("unknown argument: %s", arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(out_file_path!=NULL){
|
||||||
|
bool out_file_set=!streq(out_file_path, "this_file");
|
||||||
|
if(!out_file_set)
|
||||||
|
print_line(true, false);
|
||||||
|
fprintf(out_file,
|
||||||
|
"\n};\n\n"
|
||||||
|
"unsigned int _EmbeddedResourceFile_table_count=%u;\n",
|
||||||
|
_input_files_n);
|
||||||
|
if(!out_file_set)
|
||||||
|
fclose(out_file);
|
||||||
|
print_line(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user