├── .project ├── README.md ├── filetoarray.c └── filetoarray.exe /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | FileToArray 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > to obtain executable < 2 | gcc -o filetoarray filetoarray.c 3 | 4 | > to create filearray < 5 | filetoarray -o web_index.h index.html.gz 6 | 7 | > to print help message < 8 | filetoarray -h 9 | 10 | I advise to use my Online version at 11 | 12 | ### FILE TO (CPP) GZIP BYTE ARRAY 13 | [https://www.mischianti.org/online-converter-file-to-cpp-gzip-byte-array-3/](https://www.mischianti.org/online-converter-file-to-cpp-gzip-byte-array-3/) 14 | 15 | ### HEX ARRAY TO FILE 16 | [https://www.mischianti.org/online-converter-hex-array-to-file/](https://www.mischianti.org/online-converter-hex-array-to-file/) 17 | 18 | -------------------------------------------------------------------------------- /filetoarray.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define EMPTY "" 13 | 14 | #define MAX_NAME_LENGTH 2048 15 | 16 | #define DEFAULT_IO_BUFFER_SIZE 8192 17 | 18 | #define BYTES_PER_LINE 16 19 | #define DEFAULT_LINE_INDENT 4 20 | #define DEFAULT_ELEMENT_INDENT 1 21 | #define DEFAULT_OUTPUT_FILENAME "./array.h" 22 | 23 | #define VERSION "1.0" 24 | #define VERSION_INFO "filetoarray version " VERSION " (build date: " __DATE__ " " __TIME__ ")\n" 25 | 26 | #define HEADER_COMMENT "/*\n" \ 27 | " * File: %s, size: %lu bytes.\n" \ 28 | " *\n" \ 29 | " * This code was generated by filetoarray tool (https://github.com/xreef/FileToArray).\n" \ 30 | " * Try filetoarray online: https://www.mischianti.org/online-converter-file-to-cpp-gzip-byte-array-3/.\n" \ 31 | " */\n\n" 32 | 33 | #define ARRAY_SIZE_DEFINITION "#define %s_LEN %lu\n" 34 | #define ARRAY_DECLARATION "%sconst unsigned char %s[%lu]%s" 35 | #define ARRAY_LAST_MODIFIED_DEFINITION "#define %s_LAST_MODIFIED \"%s\"\n" 36 | 37 | #define INLCUDE_HEADER_FILE "#include \"%s\"\n" 38 | #define PROGMEM_IMPORT "#if defined ESP8266\n" \ 39 | "#include \n" \ 40 | "#endif\n\n" 41 | #define INCLUDE_GUARD "#ifndef %s\n" \ 42 | "#define %s\n\n" 43 | #define INCLUDE_GUARD_END "#endif /* %s */\n" 44 | 45 | #define USAGE "Usage: filetoarray [options] file...\n" 46 | #define HELP \ 47 | USAGE \ 48 | "Options:\n" \ 49 | " -g Specify a custom include guard.\n" \ 50 | " -h Display this information.\n" \ 51 | " -i Set indentation width.\n" \ 52 | " -l Specify the number of array elements per line.\n" \ 53 | " -o Place the output into . \n" \ 54 | " -p Use PROGMEM modifier.\n" \ 55 | " -v Display version information.\n" 56 | 57 | enum type 58 | { 59 | TYPE_DECLARATION = 1, 60 | TYPE_DEFINITION = 2 61 | }; 62 | 63 | struct config_s 64 | { 65 | enum 66 | { 67 | MODE_PROCESS, 68 | MODE_VERSION, 69 | MODE_HELP 70 | } mode; 71 | char *input_filename; 72 | char *output_filename; 73 | size_t indent; 74 | size_t bytes_per_line; 75 | bool progmem; 76 | char *include_guard; 77 | } config_s_default = {MODE_PROCESS, NULL, DEFAULT_OUTPUT_FILENAME, DEFAULT_LINE_INDENT, BYTES_PER_LINE, false, NULL}; 78 | 79 | typedef struct config_s config; 80 | 81 | const char *program_name; 82 | 83 | void print_error_message(const char *error_message, ...) 84 | { 85 | fprintf(stderr, "%s: ", program_name); 86 | va_list argps; 87 | va_start(argps, error_message); 88 | vfprintf(stderr, error_message, argps); 89 | va_end(argps); 90 | } 91 | 92 | char *get_basename(const char *path) 93 | { 94 | char *base = NULL; 95 | for (char *cursor = (char *)path; *cursor != 0; cursor++) 96 | { 97 | if (*cursor == '/' || *cursor == '\\') 98 | { 99 | base = cursor; 100 | } 101 | } 102 | return base ? base + 1 : (char *)path; 103 | } 104 | 105 | long calculate_file_size(FILE *file) 106 | { 107 | long current_position = ftell(file); 108 | fseek(file, 0, SEEK_END); 109 | long size = ftell(file); 110 | fseek(file, current_position, SEEK_SET); 111 | return size; 112 | } 113 | 114 | char *get_varname_from(const char *filename, char *variable_name, size_t length) 115 | { 116 | char *cursor = variable_name; 117 | for (char *name = get_basename(filename); *name != 0 && length > 0; cursor++, name++, length--) 118 | { 119 | *cursor = *name == '.' ? '_' : toupper(*name); 120 | } 121 | *cursor = 0; 122 | return variable_name; 123 | } 124 | 125 | char *transform_to_lowercase(char *string) 126 | { 127 | for (int i = 0; string[i]; i++) 128 | { 129 | string[i] = tolower(string[i]); 130 | } 131 | return string; 132 | } 133 | 134 | char *get_include_guard(char *dest, const config *configuration) 135 | { 136 | if (configuration->include_guard) 137 | { 138 | return strcpy(dest, configuration->include_guard); 139 | } 140 | return get_varname_from(configuration->output_filename, dest, MAX_NAME_LENGTH); 141 | } 142 | 143 | void print_last_modified(FILE *output, const char *variable_name) 144 | { 145 | time_t now = time(NULL); 146 | struct tm *current_time = gmtime(&now); 147 | char last_modified[30]; 148 | strftime(last_modified, sizeof(last_modified), "%a, %d %b %Y %H:%M:%S GMT", current_time); 149 | fprintf(output, ARRAY_LAST_MODIFIED_DEFINITION "\n", variable_name, last_modified); 150 | } 151 | 152 | void print_content(FILE *input, FILE *output, const config *configuration) 153 | { 154 | const size_t bytes_per_line = configuration->bytes_per_line ? configuration->bytes_per_line : SIZE_MAX; 155 | char buffer[DEFAULT_IO_BUFFER_SIZE]; 156 | size_t bytes_read = 0, total_bytes = 0; 157 | while (bytes_read = fread(buffer, 1, sizeof(buffer), input)) 158 | { 159 | for (long i = 0; i < bytes_read; i++, total_bytes++) 160 | { 161 | bool new_line = (total_bytes % bytes_per_line) == 0; 162 | int indent = new_line ? configuration->indent : DEFAULT_ELEMENT_INDENT; 163 | char *line_feed = (new_line && total_bytes) ? "\n" : EMPTY; 164 | char *separator = total_bytes ? "," : EMPTY; 165 | fprintf(output, "%s%s%*s0x%02X", separator, line_feed, indent, EMPTY, (uint8_t)buffer[i]); 166 | } 167 | } 168 | } 169 | 170 | void print_source_code(FILE *input, FILE *output, int output_type, const config *configuration) 171 | { 172 | long file_size = calculate_file_size(input); 173 | fprintf(output, HEADER_COMMENT, get_basename(configuration->input_filename), file_size); 174 | char include_guard[MAX_NAME_LENGTH + 1]; 175 | get_include_guard(include_guard, configuration); 176 | if (output_type == TYPE_DECLARATION) 177 | { 178 | fprintf(output, INCLUDE_GUARD, include_guard, include_guard); 179 | } 180 | else if (output_type == TYPE_DEFINITION) 181 | { 182 | fprintf(output, INLCUDE_HEADER_FILE "\n", get_basename(configuration->output_filename)); 183 | } 184 | char variable_name[MAX_NAME_LENGTH + 1]; 185 | get_varname_from(configuration->input_filename, variable_name, MAX_NAME_LENGTH); 186 | if (output_type & TYPE_DECLARATION) 187 | { 188 | print_last_modified(output, variable_name); 189 | fprintf(output, ARRAY_SIZE_DEFINITION "\n", variable_name, file_size); 190 | } 191 | char *modifier = EMPTY; 192 | if (configuration->progmem && (output_type & TYPE_DEFINITION)) 193 | { 194 | modifier = " PROGMEM"; 195 | fprintf(output, PROGMEM_IMPORT); 196 | } 197 | char *storage_class = (output_type == TYPE_DECLARATION) ? "extern " : EMPTY; 198 | transform_to_lowercase(variable_name); 199 | fprintf(output, ARRAY_DECLARATION, storage_class, variable_name, file_size, modifier); 200 | if (output_type & TYPE_DEFINITION) 201 | { 202 | fprintf(output, " = {\n"); 203 | print_content(input, output, configuration); 204 | fprintf(output, "}"); 205 | } 206 | fprintf(output, ";\n"); 207 | if (output_type == TYPE_DECLARATION) 208 | { 209 | fprintf(output, "\n" INCLUDE_GUARD_END, include_guard); 210 | } 211 | } 212 | 213 | bool is_header_file(const char *filename) 214 | { 215 | char *dot = strrchr(filename, '.'); 216 | return dot && (!strcmp(dot, ".h") || !strcmp(dot, ".hpp")); 217 | } 218 | 219 | char *convert_header_name_to_source_name(char *name) 220 | { 221 | char *dot = strrchr(name, '.'); 222 | if (*++dot == 'h') 223 | { 224 | *dot = 'c'; 225 | } 226 | return name; 227 | } 228 | 229 | void process_file(const config *configuration) 230 | { 231 | if (configuration->input_filename == NULL) 232 | { 233 | print_error_message("error: no input file\n" USAGE); 234 | exit(EXIT_FAILURE); 235 | } 236 | FILE *input_file = fopen(configuration->input_filename, "rb"); 237 | if (input_file == NULL) 238 | { 239 | print_error_message("cannot find %s: %s\n", configuration->input_filename, strerror(errno)); 240 | exit(EXIT_FAILURE); 241 | } 242 | char *output_filename = (configuration->output_filename) ? configuration->output_filename : DEFAULT_OUTPUT_FILENAME; 243 | FILE *output_file = fopen(output_filename, "wb"); 244 | if (output_file == NULL) 245 | { 246 | fclose(input_file); 247 | print_error_message("cannot open output file %s: %s\n", output_filename, strerror(errno)); 248 | exit(EXIT_FAILURE); 249 | } 250 | 251 | if (is_header_file(configuration->output_filename)) 252 | { 253 | print_source_code(input_file, output_file, TYPE_DECLARATION, configuration); 254 | char *definition_output_filename = strdup(output_filename); 255 | definition_output_filename = convert_header_name_to_source_name(definition_output_filename); 256 | FILE *definition_output_file = fopen(definition_output_filename, "wb"); 257 | if (definition_output_file == NULL) 258 | { 259 | fclose(input_file); 260 | fclose(output_file); 261 | print_error_message("cannot open output file %s: %s\n", definition_output_filename, strerror(errno)); 262 | free(definition_output_filename); 263 | exit(EXIT_FAILURE); 264 | } 265 | print_source_code(input_file, definition_output_file, TYPE_DEFINITION, configuration); 266 | fclose(definition_output_file); 267 | free(definition_output_filename); 268 | } 269 | else 270 | { 271 | print_source_code(input_file, output_file, TYPE_DECLARATION | TYPE_DEFINITION, configuration); 272 | } 273 | fclose(input_file); 274 | fclose(output_file); 275 | } 276 | 277 | const config *parse_run_configuration(int argc, char *argv[], config *dest) 278 | { 279 | size_t index; 280 | bool value = false; 281 | for (index = 1; index < argc && (*argv[index] == '-' || value); index++) 282 | { 283 | int arg_index = value ? (index - 1) : index; 284 | switch (argv[arg_index][1]) 285 | { 286 | case 'o': 287 | if (value) 288 | { 289 | dest->output_filename = argv[index]; 290 | } 291 | value = !value; 292 | break; 293 | case 'i': 294 | if (value) 295 | { 296 | dest->indent = atoi(argv[index]); 297 | } 298 | value = !value; 299 | break; 300 | case 'g': 301 | if (value) 302 | { 303 | dest->include_guard = argv[index]; 304 | } 305 | value = !value; 306 | break; 307 | case 'l': 308 | if (value) 309 | { 310 | dest->bytes_per_line = atol(argv[index]); 311 | } 312 | value = !value; 313 | break; 314 | case 'p': 315 | dest->progmem = true; 316 | break; 317 | case 'h': 318 | dest->mode = MODE_HELP; 319 | break; 320 | case 'v': 321 | dest->mode = MODE_VERSION; 322 | break; 323 | default: 324 | print_error_message("error: unrecognized command-line option '%s'\n", argv[index]); 325 | exit(EXIT_FAILURE); 326 | } 327 | } 328 | dest->input_filename = (index < argc) ? argv[index] : NULL; 329 | } 330 | 331 | void print_help() 332 | { 333 | printf(HELP); 334 | } 335 | 336 | void print_version() 337 | { 338 | printf(VERSION_INFO); 339 | } 340 | 341 | void configure_io_streams() 342 | { 343 | #ifdef _WIN32 344 | _setmode(0, _O_BINARY); 345 | _setmode(1, _O_BINARY); 346 | #endif 347 | } 348 | 349 | int main(int argc, char *argv[]) 350 | { 351 | program_name = argv[0]; 352 | configure_io_streams(); 353 | config run_configuration = config_s_default; 354 | parse_run_configuration(argc, argv, &run_configuration); 355 | switch (run_configuration.mode) 356 | { 357 | case MODE_PROCESS: 358 | process_file(&run_configuration); 359 | break; 360 | case MODE_HELP: 361 | print_help(); 362 | break; 363 | case MODE_VERSION: 364 | print_version(); 365 | break; 366 | default: 367 | break; 368 | } 369 | return 0; 370 | } -------------------------------------------------------------------------------- /filetoarray.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xreef/FileToArray/b8aff3fdc3a5265b3d0394dee90c34cf456e33d9/filetoarray.exe --------------------------------------------------------------------------------