xtgettcap: switch from a table based internal structure, to a single char array

Having the builtin terminfo DB as a table, with one entry per
capability/value pair was ineffective memory-wise - we ended up adding
~20K to the final binary size.

This patch changes the internal representation from a table, to a
single NULL-separated (and NULL-terminated) char array:

  cap1-name \0 cap1-value \0 cap2-name \0 cap2-value \0

The capabilities are still sorted; to lookup a capability we need to
scan from the beginning until we either find a match, or until the
capabilities from the DB sort higher (lexicographically) than the
searched-for capability.

The terminfo char array is 3.3K - more better than before.
This commit is contained in:
Daniel Eklöf 2022-01-13 13:37:44 +01:00
parent 7258e0b005
commit 5a032c4c6f
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 75 additions and 46 deletions

View file

@ -49,7 +49,19 @@ class IntCapability(Capability):
class StringCapability(Capability):
pass
def __init__(self, name: str, value: str):
# Expand \E to literal ESC in non-parameterized capabilities
if '%' not in value:
value = re.sub(r'\\E([0-7])', r'\\033" "\1', value)
value = re.sub(r'\\E', r'\\033', value)
else:
# Need to double-escape \E in C string literals
value = value.replace('\\E', '\\\\E')
# Dont escape :
value = value.replace('\\:', ':')
super().__init__(name, value)
class Fragment:
@ -156,48 +168,27 @@ def main():
entry.add_capability(StringCapability('TN', target_entry_name))
entry.add_capability(IntCapability('RGB', 8)) # 8 bits per channel
target.write('#pragma once\n')
target.write('\n')
# target.write('enum terminfo_capability_type {\n')
# target.write(' TERMINFO_CAP_BOOL,\n')
# target.write(' TERMINFO_CAP_INT,\n')
# target.write(' TERMINFO_CAP_STRING,\n')
# target.write('};\n')
# target.write('\n')
target.write('struct foot_terminfo_entry {\n')
target.write(' const char *name;\n')
# target.write(' enum terminfo_capability_type type;\n')
target.write(' const char *value;\n')
target.write('};\n')
target.write('\n')
target.write(
'static const struct foot_terminfo_entry terminfo_capabilities[] = {\n')
terminfo_parts = []
for cap in sorted(entry.caps.values()):
name = cap.name
value = str(cap.value)
# Expand \E to literal ESC in non-parameterized capabilities
if '%' not in value:
value = re.sub(r'\\E([0-7])', r'\\033" "\1', value)
value = re.sub(r'\\E', r'\\033', value)
else:
# Need to double-escape \E in C string literals
value = value.replace('\\E', '\\\\E')
# Dont escape :
value = value.replace('\\:', ':')
# Do escape ‘“‘
# Escape ‘“‘
name = name.replace('"', '\"')
value = value.replace('"', '\"')
terminfo_parts.append(name)
if isinstance(cap, BoolCapability):
target.write(f' {{"{name}", NULL}},\n')
terminfo_parts.append('')
else:
target.write(f' {{"{name}", "{value}"}},\n')
terminfo_parts.append(value)
target.write('};\n')
terminfo = '\\0" "'.join(terminfo_parts)
target.write('#pragma once\n')
target.write('\n')
target.write(f'static const char terminfo_capabilities[] = "{terminfo}";')
target.write('\n')
if __name__ == '__main__':