blob: 7239d1ea732ad1ca204bbd7a2b94d89b03c1a7f4 [file] [log] [blame]
Ole Troan9d420872017-10-12 13:06:35 +02001# JSON generation
2import json
Ole Troanac0babd2024-01-23 18:56:23 +01003import sys
4import os
Ole Troan9d420872017-10-12 13:06:35 +02005
Paul Vinciguerra9046e442020-11-20 23:10:09 -05006process_imports = True
7
Ole Troan148c7b72020-10-07 18:05:37 +02008
Ondrej Fabryeec5d482020-02-03 23:25:23 +01009def walk_imports(s):
10 r = []
11 for e in s:
12 r.append(str(e))
13 return r
14
Ole Troan9d420872017-10-12 13:06:35 +020015
Ole Troan148c7b72020-10-07 18:05:37 +020016def walk_counters(s, pathset):
17 r = []
18 for e in s:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020019 r2 = {"name": e.name, "elements": e.block}
Ole Troan148c7b72020-10-07 18:05:37 +020020 r.append(r2)
21
22 r3 = []
23 for p in pathset:
24 r3.append(p.paths)
25
26 return r, r3
27
28
Ole Troan9d420872017-10-12 13:06:35 +020029def 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 Sekerad9b0c6f2022-04-26 19:02:15 +020036 d.append({"enumtype": e.enumtype})
Ole Troan9d420872017-10-12 13:06:35 +020037 r.append(d)
38 return r
39
40
41def walk_services(s):
Marek Gradzkid05b9262018-02-09 13:39:22 +010042 r = {}
Ole Troan9d420872017-10-12 13:06:35 +020043 for e in s:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020044 d = {"reply": e.reply}
Ole Troan9d420872017-10-12 13:06:35 +020045 if e.stream:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020046 d["stream"] = True
Ole Troanf5db3712020-05-20 15:47:06 +020047 if e.stream_message:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020048 d["stream_msg"] = e.stream_message
Ole Troan9d420872017-10-12 13:06:35 +020049 if e.events:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020050 d["events"] = e.events
Marek Gradzkid05b9262018-02-09 13:39:22 +010051 r[e.caller] = d
Ole Troan9d420872017-10-12 13:06:35 +020052 return r
53
54
Ole Troan33a58172019-09-04 09:12:29 +020055def walk_defs(s, is_message=False):
Ole Troan9d420872017-10-12 13:06:35 +020056 r = []
57 for t in s:
58 d = []
59 d.append(t.name)
60 for b in t.block:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020061 if b.type == "Option":
Ole Troan33a58172019-09-04 09:12:29 +020062 continue
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020063 if b.type == "Field":
Ole Troan9ac11382019-04-23 17:11:01 +020064 if b.limit:
65 d.append([b.fieldtype, b.fieldname, b.limit])
66 else:
67 d.append([b.fieldtype, b.fieldname])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020068 elif b.type == "Array":
Ole Troan9d420872017-10-12 13:06:35 +020069 if b.lengthfield:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020070 d.append([b.fieldtype, b.fieldname, b.length, b.lengthfield])
Ole Troan9d420872017-10-12 13:06:35 +020071 else:
Ole Troan413f4a52018-11-28 11:36:05 +010072 d.append([b.fieldtype, b.fieldname, b.length])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020073 elif b.type == "Union":
Ole Troan413f4a52018-11-28 11:36:05 +010074 pass
Ole Troan9d420872017-10-12 13:06:35 +020075 else:
76 raise ValueError("Error in processing array type %s" % b)
Ole Troan413f4a52018-11-28 11:36:05 +010077
Ole Troan8dbfb432019-04-24 14:31:18 +020078 if is_message and t.crc:
Ole Troan9d420872017-10-12 13:06:35 +020079 c = {}
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020080 c["crc"] = "{0:#0{1}x}".format(t.crc, 10)
81 c["options"] = t.options
Ondrej Fabrya4f994f2023-02-03 11:33:39 +010082 if t.comment:
83 c["comment"] = t.comment
Ole Troan9d420872017-10-12 13:06:35 +020084 d.append(c)
85
86 r.append(d)
87 return r
88
Ole Troan148c7b72020-10-07 18:05:37 +020089
Ole Troan9d420872017-10-12 13:06:35 +020090#
91# Plugin entry point
92#
Ole Troanac0babd2024-01-23 18:56:23 +010093
94
95def 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
103def 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 Troan9d420872017-10-12 13:06:35 +0200113 j = {}
114
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200115 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 Troanac0babd2024-01-23 18:56:23 +0100130 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