Re-implement output_variable_encoded to remove allocations

This commit is contained in:
RunasSudo 2025-05-15 23:14:14 +10:00
parent dc8d140707
commit ab72cefd67
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
2 changed files with 13 additions and 32 deletions

View File

@ -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). 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. 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(); !}`. * `{! ... !}` inserts raw C code, e.g. `{! foo.bar(); !}`.
* `{# ... #}` is a comment, which is not included in the generated template. * `{# ... #}` 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 ## Example
```html ```html

View File

@ -22,42 +22,21 @@ class StdoutEmitter(Emitter):
def emit_preamble(self) -> None: def emit_preamble(self) -> None:
self.emit(r'''#include <stdbool.h> self.emit(r'''#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
void output_variable_encoded(char *variable, bool encode_quotes) { void output_variable_encoded(char *variable, bool encode_quotes) {
// First compute size of buffer required for (char *c = variable; *c != '\0'; c++) {
size_t extra_chars = 0; if (*c == '&') {
char *ptr = variable; printf("%s", "&amp;");
for (; *ptr != '\0'; ptr++) { } else if (*c == '<') {
if (*ptr == '&') { extra_chars += 4; } printf("%s", "&lt;");
if (*ptr == '<') { extra_chars += 3; } } else if (*c == '"' && encode_quotes) {
if (*ptr == '"' && encode_quotes) { extra_chars += 5; } printf("%s", "&quot;");
if (*ptr == '\'' && encode_quotes) { extra_chars += 4; } } else if (*c == '\'' && encode_quotes) {
} printf("%s", "&#39;");
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++ = ';';
} else { } else {
*c_out++ = *c_inp; putchar(*c);
} }
} }
*c_out = '\0';
printf("%s", buf);
free(buf);
} }
void output_variable_as_attr(char *variable) { void output_variable_as_attr(char *variable) {