gso: use the header offsets from buffer metadata
[vpp.git] / src / tools / vppapigen / vppapigen_json.py
1 # JSON generation
2 import json
3 import sys
4 import os
5
6 process_imports = True
7
8
9 def walk_imports(s):
10     r = []
11     for e in s:
12         r.append(str(e))
13     return r
14
15
16 def walk_counters(s, pathset):
17     r = []
18     for e in s:
19         r2 = {"name": e.name, "elements": e.block}
20         r.append(r2)
21
22     r3 = []
23     for p in pathset:
24         r3.append(p.paths)
25
26     return r, r3
27
28
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)
36         d.append({"enumtype": e.enumtype})
37         r.append(d)
38     return r
39
40
41 def walk_services(s):
42     r = {}
43     for e in s:
44         d = {"reply": e.reply}
45         if e.stream:
46             d["stream"] = True
47         if e.stream_message:
48             d["stream_msg"] = e.stream_message
49         if e.events:
50             d["events"] = e.events
51         r[e.caller] = d
52     return r
53
54
55 def walk_defs(s, is_message=False):
56     r = []
57     for t in s:
58         d = []
59         d.append(t.name)
60         for b in t.block:
61             if b.type == "Option":
62                 continue
63             if b.type == "Field":
64                 if b.limit:
65                     d.append([b.fieldtype, b.fieldname, b.limit])
66                 else:
67                     d.append([b.fieldtype, b.fieldname])
68             elif b.type == "Array":
69                 if b.lengthfield:
70                     d.append([b.fieldtype, b.fieldname, b.length, b.lengthfield])
71                 else:
72                     d.append([b.fieldtype, b.fieldname, b.length])
73             elif b.type == "Union":
74                 pass
75             else:
76                 raise ValueError("Error in processing array type %s" % b)
77
78         if is_message and t.crc:
79             c = {}
80             c["crc"] = "{0:#0{1}x}".format(t.crc, 10)
81             c["options"] = t.options
82             if t.comment:
83                 c["comment"] = t.comment
84             d.append(c)
85
86         r.append(d)
87     return r
88
89
90 #
91 # Plugin entry point
92 #
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
113     j = {}
114
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"])
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