Skip to content

Commit da62c32

Browse files
committed
Add optional gzip compressed content and uint8_t arrays
Change embedded file handling to use uint8_t arrays and add optional gzip support. FilesContent.content is now uint8_t* and a gzip bool field was added. A new ConvertToHCompressed() (enabled with USE_GZIP) compresses files via gzip and emits uint8_t arrays and length constants; ConvertToH now emits uint8_t arrays as well. The content table generation was updated to include the gzip flag, and main() prints a message when gzip is enabled. Minor formatting and include order adjustments and a small feature-guard whitespace fix are also included.
1 parent b2538cb commit da62c32

1 file changed

Lines changed: 125 additions & 7 deletions

File tree

lib-remoteconfig/http/content/generate_content.cpp

Lines changed: 125 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
* THE SOFTWARE.
2424
*/
2525

26-
#include <cstdint>
2726
#undef NDEBUG
28-
27+
28+
#include <cstdint>
2929
#include <cstdlib>
3030
#include <cstdio>
3131
#include <cstring>
@@ -40,16 +40,22 @@ struct SupportedExtension {
4040
http::ContentTypes content_type;
4141
};
4242

43-
static constexpr SupportedExtension kSupportedExtensions[] = {{"html", http::ContentTypes::kTextHtml}, {"css", http::ContentTypes::kTextCss}, {"js", http::ContentTypes::kTextJs}, {"json", http::ContentTypes::kApplicationJson}};
43+
static constexpr SupportedExtension kSupportedExtensions[] = {
44+
{"html", http::ContentTypes::kTextHtml},
45+
{"css", http::ContentTypes::kTextCss},
46+
{"js", http::ContentTypes::kTextJs},
47+
{"json", http::ContentTypes::kApplicationJson}
48+
};
4449

4550
static constexpr char kContentHeader[] =
4651
"\n"
4752
"struct FilesContent {\n"
4853
"\tuint32_t hash;\n"
4954
"\tconst char *file_name;\n"
50-
"\tconst char *content;\n"
55+
"\tconst uint8_t *content;\n"
5156
"\tuint32_t content_length;\n"
5257
"\thttp::ContentTypes content_type;\n"
58+
"\tbool gzip;\n"
5359
"};\n\n"
5460
"inline constexpr struct FilesContent kHttpContent[] = {\n";
5561

@@ -120,7 +126,7 @@ static constexpr FeatureGuard kFeatureGuards[] = {
120126
{"dmxpca9685", kHaveDmxPca9585Begin, kHaveDmxPca9585End},
121127
{"dmx.", kHaveDmxSendBegin, kHaveDmxSendEnd},
122128
{"rdm", kHaveRdmBegin, kHaveRdmEnd},
123-
{"display.js", kHaveDisplayUdfBegin, kHaveDisplayUdfEnd},
129+
{"display.js", kHaveDisplayUdfBegin, kHaveDisplayUdfEnd},
124130
{"showfile.js", kHaveShowfileBegin, kHaveShowfileEnd},
125131
{"time", kHaveTimeBegin, kHaveTimeEnd},
126132
{"rtc", kHaveRtcBegin, kHaveRtcEnd}};
@@ -232,6 +238,108 @@ static void BuildFinalContentHeader() {
232238
assert(kJ == 0);
233239
}
234240

241+
#if defined(USE_GZIP)
242+
static int ConvertToHCompressed(const char* dir_name, const char* file_name) {
243+
assert(dir_name != nullptr);
244+
assert(file_name != nullptr);
245+
246+
printf("File to convert: %s/%s, ", dir_name, file_name);
247+
248+
char path[128];
249+
auto n = snprintf(path, sizeof(path), "%s/%s", dir_name, file_name);
250+
assert(n > 0);
251+
assert(n < static_cast<int>(sizeof(path)));
252+
253+
const auto kFileNameLength = strlen(file_name);
254+
255+
char file_name_out[128];
256+
n = snprintf(file_name_out, sizeof(file_name_out), "%s.h", file_name);
257+
assert(n > 0);
258+
assert(n < static_cast<int>(sizeof(file_name_out)));
259+
260+
printf("Header file: \"%s\", ", file_name_out);
261+
262+
auto* file_out = fopen(file_name_out, "w");
263+
if (file_out == nullptr) {
264+
perror(file_name_out);
265+
return -1;
266+
}
267+
268+
char constant_name[128];
269+
assert((kFileNameLength + 4) < sizeof(constant_name));
270+
271+
MakeConstantName(file_name, constant_name, sizeof(constant_name));
272+
273+
char constant_name_gz[128];
274+
n = snprintf(constant_name_gz, sizeof(constant_name_gz), "%s_gz", constant_name);
275+
assert(n > 0);
276+
assert(n < static_cast<int>(sizeof(constant_name_gz)));
277+
278+
printf("Constant name: %s, ", constant_name_gz);
279+
280+
WriteFeatureGuardsBegin(file_includes, file_name_out);
281+
282+
char buffer[128];
283+
n = snprintf(buffer, sizeof(buffer), "#include \"%s\"\n", file_name_out);
284+
assert(n > 0);
285+
assert(n < static_cast<int>(sizeof(buffer)));
286+
287+
fwrite(buffer, sizeof(char), n, file_includes);
288+
289+
WriteFeatureGuardsEnd(file_includes, file_name_out);
290+
291+
fprintf(file_out, "#pragma once\n\n");
292+
fprintf(file_out, "#include <cstdint>\n\n");
293+
294+
fprintf(file_out, "static constexpr uint8_t %s[] = {\n", constant_name_gz);
295+
296+
char command[256];
297+
n = snprintf(command, sizeof(command), "gzip -n -9 -c \"%s\"", path);
298+
assert(n > 0);
299+
assert(n < static_cast<int>(sizeof(command)));
300+
301+
auto* gzip_pipe = popen(command, "r");
302+
if (gzip_pipe == nullptr) {
303+
fclose(file_out);
304+
perror("gzip");
305+
return -1;
306+
}
307+
308+
unsigned offset = 0;
309+
int c;
310+
311+
while ((c = fgetc(gzip_pipe)) != EOF) {
312+
n = snprintf(buffer, sizeof(buffer), "0x%02X,%c", static_cast<unsigned>(static_cast<uint8_t>(c)), (++offset % 16U == 0U) ? '\n' : ' ');
313+
assert(n > 0);
314+
assert(n < static_cast<int>(sizeof(buffer)));
315+
316+
fwrite(buffer, sizeof(char), n, file_out);
317+
}
318+
319+
const auto kGzipStatus = pclose(gzip_pipe);
320+
321+
if (kGzipStatus != 0) {
322+
fclose(file_out);
323+
fprintf(stderr, "gzip failed for %s\n", path);
324+
return -1;
325+
}
326+
327+
if ((offset % 16U) != 0U) {
328+
fwrite("\n", sizeof(char), 1, file_out);
329+
}
330+
331+
fprintf(file_out, "};\n\n");
332+
fprintf(file_out, "static constexpr uint32_t %s_len = sizeof(%s);\n", constant_name_gz, constant_name_gz);
333+
334+
fclose(file_out);
335+
336+
fwrite(constant_name_gz, sizeof(char), strlen(constant_name_gz), file_content);
337+
338+
printf("Compressed size: %u\n", offset);
339+
340+
return static_cast<int>(offset);
341+
}
342+
#else
235343
static int ConvertToH(const char* dir_name, const char* file_name) {
236344
assert(file_name != nullptr);
237345

@@ -278,7 +386,7 @@ static int ConvertToH(const char* dir_name, const char* file_name) {
278386

279387
WriteFeatureGuardsEnd(file_includes, file_name_out);
280388

281-
fwrite("static constexpr char ", sizeof(char), 22, file_out);
389+
fwrite("static constexpr uint8_t ", sizeof(char), 25, file_out);
282390

283391
char constant_name[128];
284392
assert((kFileNameLength + 1) < sizeof(constant_name));
@@ -323,6 +431,7 @@ static int ConvertToH(const char* dir_name, const char* file_name) {
323431

324432
return file_size;
325433
}
434+
#endif
326435

327436
static uint32_t CreateHash(const char* filename) {
328437
char hash_name[128];
@@ -343,6 +452,9 @@ static uint32_t CreateHash(const char* filename) {
343452

344453
int main(int argc, char* argv[]) // NOLINT
345454
{
455+
#if defined(USE_GZIP)
456+
puts("Using gzip.");
457+
#endif
346458
file_includes = fopen("includes.h", "w");
347459
assert(file_includes != nullptr);
348460

@@ -387,9 +499,15 @@ int main(int argc, char* argv[]) // NOLINT
387499

388500
fwrite(buffer, sizeof(char), i, file_content);
389501

502+
auto use_gzip = false;
503+
#if defined(USE_GZIP)
504+
use_gzip = true;
505+
const auto kContentLength = ConvertToHCompressed(dir_name, dir_entry->d_name);
506+
#else
390507
const auto kContentLength = ConvertToH(dir_name, dir_entry->d_name);
508+
#endif
391509

392-
i = snprintf(buffer, sizeof(buffer), ", %d, static_cast<http::ContentTypes>(%d) },\n", kContentLength, static_cast<int>(kContentType));
510+
i = snprintf(buffer, sizeof(buffer), ", %d, static_cast<http::ContentTypes>(%d), %s },\n", kContentLength, static_cast<int>(kContentType), use_gzip ? "true" : "false");
393511
assert(i > 0);
394512
assert(i < static_cast<int>(sizeof(buffer)));
395513

0 commit comments

Comments
 (0)