Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 1 | # JSON generation |
| 2 | import json |
Ole Troan | ac0babd | 2024-01-23 18:56:23 +0100 | [diff] [blame] | 3 | import sys |
| 4 | import os |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 5 | |
Paul Vinciguerra | 9046e44 | 2020-11-20 23:10:09 -0500 | [diff] [blame] | 6 | process_imports = True |
| 7 | |
Ole Troan | 148c7b7 | 2020-10-07 18:05:37 +0200 | [diff] [blame] | 8 | |
Ondrej Fabry | eec5d48 | 2020-02-03 23:25:23 +0100 | [diff] [blame] | 9 | def walk_imports(s): |
| 10 | r = [] |
| 11 | for e in s: |
| 12 | r.append(str(e)) |
| 13 | return r |
| 14 | |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 15 | |
Ole Troan | 148c7b7 | 2020-10-07 18:05:37 +0200 | [diff] [blame] | 16 | def walk_counters(s, pathset): |
| 17 | r = [] |
| 18 | for e in s: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 19 | r2 = {"name": e.name, "elements": e.block} |
Ole Troan | 148c7b7 | 2020-10-07 18:05:37 +0200 | [diff] [blame] | 20 | r.append(r2) |
| 21 | |
| 22 | r3 = [] |
| 23 | for p in pathset: |
| 24 | r3.append(p.paths) |
| 25 | |
| 26 | return r, r3 |
| 27 | |
| 28 | |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 29 | def walk_enums(s): |
| 30 | r = [] |
| 31 | for e in s: |
| 32 | d = [] |
| 33 | d.append(e.name) |
| 34 | for b in e.block: |
| 35 | d.append(b) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 36 | d.append({"enumtype": e.enumtype}) |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 37 | r.append(d) |
| 38 | return r |
| 39 | |
| 40 | |
| 41 | def walk_services(s): |
Marek Gradzki | d05b926 | 2018-02-09 13:39:22 +0100 | [diff] [blame] | 42 | r = {} |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 43 | for e in s: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 44 | d = {"reply": e.reply} |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 45 | if e.stream: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 46 | d["stream"] = True |
Ole Troan | f5db371 | 2020-05-20 15:47:06 +0200 | [diff] [blame] | 47 | if e.stream_message: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 48 | d["stream_msg"] = e.stream_message |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 49 | if e.events: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 50 | d["events"] = e.events |
Marek Gradzki | d05b926 | 2018-02-09 13:39:22 +0100 | [diff] [blame] | 51 | r[e.caller] = d |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 52 | return r |
| 53 | |
| 54 | |
Ole Troan | 33a5817 | 2019-09-04 09:12:29 +0200 | [diff] [blame] | 55 | def walk_defs(s, is_message=False): |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 56 | r = [] |
| 57 | for t in s: |
| 58 | d = [] |
| 59 | d.append(t.name) |
| 60 | for b in t.block: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 61 | if b.type == "Option": |
Ole Troan | 33a5817 | 2019-09-04 09:12:29 +0200 | [diff] [blame] | 62 | continue |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 63 | if b.type == "Field": |
Ole Troan | 9ac1138 | 2019-04-23 17:11:01 +0200 | [diff] [blame] | 64 | if b.limit: |
| 65 | d.append([b.fieldtype, b.fieldname, b.limit]) |
| 66 | else: |
| 67 | d.append([b.fieldtype, b.fieldname]) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 68 | elif b.type == "Array": |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 69 | if b.lengthfield: |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 70 | d.append([b.fieldtype, b.fieldname, b.length, b.lengthfield]) |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 71 | else: |
Ole Troan | 413f4a5 | 2018-11-28 11:36:05 +0100 | [diff] [blame] | 72 | d.append([b.fieldtype, b.fieldname, b.length]) |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 73 | elif b.type == "Union": |
Ole Troan | 413f4a5 | 2018-11-28 11:36:05 +0100 | [diff] [blame] | 74 | pass |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 75 | else: |
| 76 | raise ValueError("Error in processing array type %s" % b) |
Ole Troan | 413f4a5 | 2018-11-28 11:36:05 +0100 | [diff] [blame] | 77 | |
Ole Troan | 8dbfb43 | 2019-04-24 14:31:18 +0200 | [diff] [blame] | 78 | if is_message and t.crc: |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 79 | c = {} |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 80 | c["crc"] = "{0:#0{1}x}".format(t.crc, 10) |
| 81 | c["options"] = t.options |
Ondrej Fabry | a4f994f | 2023-02-03 11:33:39 +0100 | [diff] [blame] | 82 | if t.comment: |
| 83 | c["comment"] = t.comment |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 84 | d.append(c) |
| 85 | |
| 86 | r.append(d) |
| 87 | return r |
| 88 | |
Ole Troan | 148c7b7 | 2020-10-07 18:05:37 +0200 | [diff] [blame] | 89 | |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 90 | # |
| 91 | # Plugin entry point |
| 92 | # |
Ole Troan | ac0babd | 2024-01-23 18:56:23 +0100 | [diff] [blame] | 93 | |
| 94 | |
| 95 | def contents_to_c_string(contents): |
| 96 | # Escape backslashes and double quotes |
| 97 | contents = contents.replace("\\", "\\\\").replace('"', '\\"') |
| 98 | # Replace newlines with \n |
| 99 | contents = contents.replace("\n", "\\n") |
| 100 | return '"' + contents + '"' |
| 101 | |
| 102 | |
| 103 | def run(output_dir, apifilename, s): |
| 104 | if not output_dir: |
| 105 | sys.stderr.write("Missing --outputdir argument") |
| 106 | return None |
| 107 | |
| 108 | basename = os.path.basename(apifilename) |
| 109 | filename_json_repr = os.path.join(output_dir + "/" + basename + "_json.h") |
| 110 | filename, _ = os.path.splitext(basename) |
| 111 | modulename = filename.replace(".", "_") |
| 112 | |
Ole Troan | 9d42087 | 2017-10-12 13:06:35 +0200 | [diff] [blame] | 113 | j = {} |
| 114 | |
Klement Sekera | d9b0c6f | 2022-04-26 19:02:15 +0200 | [diff] [blame] | 115 | j["types"] = walk_defs([o for o in s["types"] if o.__class__.__name__ == "Typedef"]) |
| 116 | j["messages"] = walk_defs(s["Define"], True) |
| 117 | j["unions"] = walk_defs([o for o in s["types"] if o.__class__.__name__ == "Union"]) |
| 118 | j["enums"] = walk_enums([o for o in s["types"] if o.__class__.__name__ == "Enum"]) |
| 119 | j["enumflags"] = walk_enums( |
| 120 | [o for o in s["types"] if o.__class__.__name__ == "EnumFlag"] |
| 121 | ) |
| 122 | j["services"] = walk_services(s["Service"]) |
| 123 | j["options"] = s["Option"] |
| 124 | j["aliases"] = { |
| 125 | o.name: o.alias for o in s["types"] if o.__class__.__name__ == "Using" |
| 126 | } |
| 127 | j["vl_api_version"] = hex(s["file_crc"]) |
| 128 | j["imports"] = walk_imports(i for i in s["Import"]) |
| 129 | j["counters"], j["paths"] = walk_counters(s["Counters"], s["Paths"]) |
Ole Troan | ac0babd | 2024-01-23 18:56:23 +0100 | [diff] [blame] | 130 | r = json.dumps(j, indent=4, separators=(",", ": ")) |
| 131 | c_string = contents_to_c_string(r) |
| 132 | with open(filename_json_repr, "w", encoding="UTF-8") as f: |
| 133 | print(f"const char *json_api_repr_{modulename} = {c_string};", file=f) |
| 134 | # return json.dumps(j, indent=4, separators=(",", ": ")) |
| 135 | return r |