Files
CapySR/tools/gen_cmdids.py
T

74 lines
3.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Turns proto/cmdids.txt into a constant header plus a name table for logging."""
import argparse
import os
def write_if_changed(path, text):
if os.path.exists(path):
with open(path, encoding="utf-8") as fh:
if fh.read() == text:
return
with open(path, "w", encoding="utf-8", newline="\n") as fh:
fh.write(text)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--input", required=True)
ap.add_argument("--out-dir", required=True)
args = ap.parse_args()
entries = []
with open(args.input, encoding="utf-8") as fh:
for line in fh:
line = line.split("#", 1)[0].strip()
if not line or "=" not in line:
continue
name, value = (part.strip() for part in line.split("=", 1))
if name == "None":
continue
entries.append((name, int(value)))
entries.sort(key=lambda e: e[0])
h = ["// generated by tools/gen_cmdids.py -- do not edit", "#pragma once", "#include <cstdint>",
"#include <string>", "", "namespace cmd {", ""]
for name, value in entries:
h.append(f"constexpr uint16_t {name} = {value};")
h += ["", "// packet name for logging; \"Unknown(<id>)\" when the dump has no name for it",
"std::string name(uint16_t id);", "",
"// 0 when the dump has no packet by that name",
"uint16_t id(const std::string& name);", "", "} // namespace cmd", ""]
write_if_changed(os.path.join(args.out_dir, "cmd_ids.h"), "\n".join(h))
# first name wins for aliased ids, so the table stays 1:1
by_id = {}
for name, value in entries:
by_id.setdefault(value, name)
c = ["// generated by tools/gen_cmdids.py -- do not edit", '#include "net/cmd_ids.h"', "",
"#include <unordered_map>", "", "namespace cmd {", "namespace {",
"const std::unordered_map<uint16_t, const char*>& table() {",
" static const std::unordered_map<uint16_t, const char*> t = {"]
for value, name in sorted(by_id.items()):
c.append(f' {{{value}, "{name}"}},')
c += [" };", " return t;", "}", "",
"const std::unordered_map<std::string, uint16_t>& reverse() {",
" static const std::unordered_map<std::string, uint16_t> t = [] {",
" std::unordered_map<std::string, uint16_t> m;",
" for (const auto& [k, v] : table()) m.emplace(v, k);",
" return m;", " }();", " return t;", "}",
"} // namespace", "",
"std::string name(uint16_t id) {", " auto it = table().find(id);",
" if (it != table().end()) return it->second;",
' return "Unknown(" + std::to_string(id) + ")";', "}", "",
"uint16_t id(const std::string& n) {", " auto it = reverse().find(n);",
" return it == reverse().end() ? 0 : it->second;", "}", "",
"} // namespace cmd", ""]
write_if_changed(os.path.join(args.out_dir, "cmd_ids.cpp"), "\n".join(c))
print(f" {len(entries)} cmd ids, {len(by_id)} unique")
if __name__ == "__main__":
main()