├── .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
--------------------------------------------------------------------------------