74 lines
3.1 KiB
Python
74 lines
3.1 KiB
Python
#!/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()
|