summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Epler <jepler@gmail.com>2020-05-28 11:29:28 -0500
committerJeff Epler <jepler@gmail.com>2020-05-28 11:30:46 -0500
commitd0f9b5901e37a751a0bf5770c2f26a5c6c039dd4 (patch)
tree579ac83fb354e6085790194eb0d9d7ab5d608295
parentfe3e8d1589e54de999cccc775f269a39443c82d6 (diff)
translations: document the compressed format
-rw-r--r--py/makeqstrdata.py3
-rw-r--r--supervisor/shared/translate.h27
2 files changed, 30 insertions, 0 deletions
diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py
index 64e4d26f4..df2c687e5 100644
--- a/py/makeqstrdata.py
+++ b/py/makeqstrdata.py
@@ -2,6 +2,9 @@
Process raw qstr file and output qstr data with length, hash and data bytes.
This script works with Python 2.7, 3.3 and 3.4.
+
+For documentation about the format of compressed translated strings, see
+supervisor/shared/translate.h
"""
from __future__ import print_function
diff --git a/supervisor/shared/translate.h b/supervisor/shared/translate.h
index 067a44e1f..731b26d12 100644
--- a/supervisor/shared/translate.h
+++ b/supervisor/shared/translate.h
@@ -29,11 +29,38 @@
#include <stdint.h>
+// The format of the compressed data is:
+// - the size of the uncompressed string in UTF-8 bytes, encoded as a
+// (compress_max_length_bits)-bit number. compress_max_length_bits is
+// computed during dictionary generation time, and happens to be 8
+// for all current platforms. However, it'll probably end up being
+// 9 in some translations sometime in the future. This length excludes
+// the trailing NUL, though notably decompress_length includes it.
+//
+// - followed by the huffman encoding of the individual UTF-16 code
+// points that make up the string. The trailing "\0" is not
+// represented by a huffman code, but is implied by the length.
+// (building the huffman encoding on UTF-16 code points gave better
+// compression than building it on UTF-8 bytes)
+//
+// The "data" / "tail" construct is so that the struct's last member is a
+// "flexible array". However, the _only_ member is not permitted to be
+// a flexible member, so we have to declare the first byte as a separte
+// member of the structure.
+//
+// For translations where length needs 8 bits, this saves about 1.5
+// bytes per string on average compared to a structure of {uint16_t,
+// flexible array}, but is also future-proofed against strings with
+// UTF-8 length above 256, with a savings of about 1.375 bytes per
+// string.
typedef struct {
uint8_t data;
const uint8_t tail[];
} compressed_string_t;
+// Return the compressed, translated version of a source string
+// Usually, due to LTO, this is optimized into a load of a constant
+// pointer.
const compressed_string_t* translate(const char* c);
void serial_write_compressed(const compressed_string_t* compressed);
char* decompress(const compressed_string_t* compressed, char* decompressed);