From ab72cefd6745a647dbd41a9814397873ab198e48 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Thu, 15 May 2025 23:14:14 +1000 Subject: [PATCH] Re-implement output_variable_encoded to remove allocations --- README.md | 4 +++- htmlcc/emitter/stdout.py | 41 ++++++++++------------------------------ 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 36cf907..73502e6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ python -m htmlcc input.html > output.c By default, htmlcc emits C code which prints the generated HTML to standard output. An extensible framework is provided to customise this behaviour via the `--emitter` flag (see *htmlcc/emitter/cgit.py* for an example implementation). -## Syntax +## Features htmlcc syntax is based loosely on [Jinja](https://jinja.palletsprojects.com/en/stable/), using double curly braces. @@ -28,6 +28,8 @@ The following language features are supported: * `{! ... !}` inserts raw C code, e.g. `{! foo.bar(); !}`. * `{# ... #}` is a comment, which is not included in the generated template. +Using the default emitter, generated C code is cross-platform, has no dependencies, and requires no memory allocations. + ## Example ```html diff --git a/htmlcc/emitter/stdout.py b/htmlcc/emitter/stdout.py index e566896..69a529e 100644 --- a/htmlcc/emitter/stdout.py +++ b/htmlcc/emitter/stdout.py @@ -22,42 +22,21 @@ class StdoutEmitter(Emitter): def emit_preamble(self) -> None: self.emit(r'''#include #include -#include void output_variable_encoded(char *variable, bool encode_quotes) { - // First compute size of buffer required - size_t extra_chars = 0; - char *ptr = variable; - for (; *ptr != '\0'; ptr++) { - if (*ptr == '&') { extra_chars += 4; } - if (*ptr == '<') { extra_chars += 3; } - if (*ptr == '"' && encode_quotes) { extra_chars += 5; } - if (*ptr == '\'' && encode_quotes) { extra_chars += 4; } - } - - size_t len = ptr - variable; - char *buf = malloc(len + extra_chars + 1); - - // Replace characters - char *c_inp = variable; - char *c_out = buf; - for (; *c_inp != '\0'; c_inp++) { - if (*c_inp == '&') { - *c_out++ = '&'; *c_out++ = 'a'; *c_out++ = 'm'; *c_out++ = 'p'; *c_out++ = ';'; - } else if (*c_inp == '<') { - *c_out++ = '&'; *c_out++ = 'l'; *c_out++ = 't'; *c_out++ = ';'; - } else if (*c_inp == '"' && encode_quotes) { - *c_out++ = '&'; *c_out++ = 'q'; *c_out++ = 'u'; *c_out++ = 'o'; *c_out++ = 't'; *c_out++ = ';'; - } else if (*c_inp == '\'' && encode_quotes) { - *c_out++ = '&'; *c_out++ = '#'; *c_out++ = '3'; *c_out++ = '9'; *c_out++ = ';'; + for (char *c = variable; *c != '\0'; c++) { + if (*c == '&') { + printf("%s", "&"); + } else if (*c == '<') { + printf("%s", "<"); + } else if (*c == '"' && encode_quotes) { + printf("%s", """); + } else if (*c == '\'' && encode_quotes) { + printf("%s", "'"); } else { - *c_out++ = *c_inp; + putchar(*c); } } - *c_out = '\0'; - - printf("%s", buf); - free(buf); } void output_variable_as_attr(char *variable) {