Repair Doxygen build infrastructure
[vpp.git] / vpp-api / java / jvpp / gen / jvppgen / jni_gen.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2016 Cisco and/or its affiliates.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 from string import Template
17
18 import util
19
20 variable_length_array_value_template = Template("""mp->${length_var_name}""")
21 variable_length_array_template = Template("""clib_net_to_host_${length_field_type}(${value})""")
22
23 dto_field_id_template = Template("""
24     jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_name}", "${jni_signature}");""")
25
26 default_dto_field_setter_template = Template("""
27     (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, mp->${c_name});
28 """)
29
30 variable_length_array_value_template = Template("""mp->${length_var_name}""")
31 variable_length_array_template = Template("""clib_net_to_host_${length_field_type}(${value})""")
32
33 u16_dto_field_setter_template = Template("""
34     (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u16(mp->${c_name}));
35 """)
36
37 u32_dto_field_setter_template = Template("""
38     (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u32(mp->${c_name}));
39 """)
40
41 u64_dto_field_setter_template = Template("""
42     (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u64(mp->${c_name}));
43 """)
44
45 u8_array_dto_field_setter_template = Template("""
46     jbyteArray ${field_reference_name} = (*env)->NewByteArray(env, ${field_length});
47     (*env)->SetByteArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const jbyte*)mp->${c_name});
48     (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
49     (*env)->DeleteLocalRef(env, ${field_reference_name});
50 """)
51
52 u16_array_dto_field_setter_template = Template("""
53     {
54         jshortArray ${field_reference_name} = (*env)->NewShortArray(env, ${field_length});
55         jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL);
56         unsigned int _i;
57         for (_i = 0; _i < ${field_length}; _i++) {
58             ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u16(mp->${c_name}[_i]);
59         }
60
61         (*env)->ReleaseShortArrayElements(env,  ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
62         (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
63         (*env)->DeleteLocalRef(env, ${field_reference_name});
64     }
65 """)
66
67 u32_array_dto_field_setter_template = Template("""
68     {
69         jintArray ${field_reference_name} = (*env)->NewIntArray(env, ${field_length});
70         jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL);
71         unsigned int _i;
72         for (_i = 0; _i < ${field_length}; _i++) {
73             ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u32(mp->${c_name}[_i]);
74         }
75
76         (*env)->ReleaseIntArrayElements(env,  ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
77         (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
78         (*env)->DeleteLocalRef(env, ${field_reference_name});
79     }
80 """)
81
82 # For each u64 array we get its elements. Then we convert values to host byte order.
83 # All changes to  jlong* buffer are written to jlongArray (isCopy is set to NULL)
84 u64_array_dto_field_setter_template = Template("""
85     {
86         jlongArray ${field_reference_name} = (*env)->NewLongArray(env, ${field_length});
87         jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL);
88         unsigned int _i;
89         for (_i = 0; _i < ${field_length}; _i++) {
90             ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u64(mp->${c_name}[_i]);
91         }
92
93         (*env)->ReleaseLongArrayElements(env,  ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
94         (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
95         (*env)->DeleteLocalRef(env, ${field_reference_name});
96     }
97 """)
98
99 dto_field_setter_templates = {'u8': default_dto_field_setter_template,
100                               'u16': u16_dto_field_setter_template,
101                               'u32': u32_dto_field_setter_template,
102                               'i32': u32_dto_field_setter_template,
103                               'u64': u64_dto_field_setter_template,
104                               'f64': default_dto_field_setter_template,  # fixme
105                               'u8[]': u8_array_dto_field_setter_template,
106                               'u16[]': u16_array_dto_field_setter_template,
107                               'u32[]': u32_array_dto_field_setter_template,
108                               'u64[]': u64_array_dto_field_setter_template
109                               }
110
111
112 def jni_reply_handler_for_type(handler_name, ref_name, field_type, c_name, field_reference_name,
113                                field_name, field_length, is_variable_len_array, length_field_type,
114                                object_name="dto"):
115     """
116     Generates jni code that initializes a field of java object (dto or custom type).
117     To be used in reply message handlers.
118     :param field_type: type of the field to be initialized (as defined in vpe.api)
119     :param c_name: name of the message struct member that stores initialization value
120     :param field_reference_name: name of the field reference in generated code
121     :param field_name: name of the field (camelcase)
122     :param field_length: integer or name of variable that stores field length
123     :param object_name: name of the object to be initialized
124     """
125
126     # todo move validation to vppapigen
127     if field_type.endswith('[]') and field_length == '0':
128         raise Exception('Variable array \'%s\' defined in \'%s\' '
129                         'should have defined length (e.g. \'%s[%s_length]\''
130                         % (c_name, handler_name, c_name, c_name))
131
132     if is_variable_len_array:
133         length_var_name = field_length
134         field_length = variable_length_array_value_template.substitute(length_var_name=length_var_name)
135         if length_field_type != 'u8':  # we need net to host conversion:
136             field_length = variable_length_array_template.substitute(
137                     length_field_type=length_field_type, value=field_length)
138
139     # for retval don't generate setters
140     if util.is_retval_field(c_name):
141         return ""
142
143     jni_signature = util.jni_2_signature_mapping[field_type]
144     jni_setter = util.jni_field_accessors[field_type]
145
146     result = dto_field_id_template.substitute(
147             field_reference_name=field_reference_name,
148             field_name=field_name,
149             class_ref_name=ref_name,
150             jni_signature=jni_signature)
151
152     dto_setter_template = dto_field_setter_templates[field_type]
153
154     result += dto_setter_template.substitute(
155             jni_signature=jni_signature,
156             object_name=object_name,
157             field_reference_name=field_reference_name,
158             c_name=c_name,
159             jni_setter=jni_setter,
160             field_length=field_length)
161     return result
162
163
164 request_field_identifier_template = Template("""
165     jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${object_name}Class, "${field_name}", "${jni_signature}");
166     ${jni_type} ${field_reference_name} = (*env)->Get${jni_getter}(env, ${object_name}, ${field_reference_name}FieldId);
167     """)
168
169 array_length_enforcement_template = Template("""
170         size_t max_size = ${field_length};
171         if (cnt > max_size) cnt = max_size;""")
172
173 u8_struct_setter_template = Template("""
174     mp->${c_name} = ${field_reference_name};""")
175
176 u16_struct_setter_template = Template("""
177     mp->${c_name} = clib_host_to_net_u16(${field_reference_name});""")
178
179 u32_struct_setter_template = Template("""
180     mp->${c_name} = clib_host_to_net_u32(${field_reference_name});""")
181
182 i32_struct_setter_template = Template("""
183     mp->${c_name} = clib_host_to_net_i32(${field_reference_name});!""")
184
185 u64_struct_setter_template = Template("""
186     mp->${c_name} = clib_host_to_net_u64(${field_reference_name});""")
187
188 array_length_enforcement_template = Template("""
189         size_t max_size = ${field_length};
190         if (cnt > max_size) cnt = max_size;""")
191
192 u8_array_struct_setter_template = Template("""
193     if (${field_reference_name}) {
194         jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
195         ${field_length_check}
196         (*env)->GetByteArrayRegion(env, ${field_reference_name}, 0, cnt, (jbyte *)mp->${c_name});
197     }
198 """)
199
200 u16_array_struct_setter_template = Template("""
201     if (${field_reference_name}) {
202         jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL);
203         size_t _i;
204         jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
205         ${field_length_check}
206         for (_i = 0; _i < cnt; _i++) {
207             mp->${c_name}[_i] = clib_host_to_net_u16(${field_reference_name}ArrayElements[_i]);
208         }
209         (*env)->ReleaseShortArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
210     }
211     """)
212
213 u32_array_struct_setter_template = Template("""
214     if (${field_reference_name}) {
215         jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL);
216         size_t _i;
217         jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
218         ${field_length_check}
219         for (_i = 0; _i < cnt; _i++) {
220             mp->${c_name}[_i] = clib_host_to_net_u32(${field_reference_name}ArrayElements[_i]);
221         }
222         (*env)->ReleaseIntArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
223     }
224     """)
225
226 u64_array_struct_setter_template = Template("""
227     if (${field_reference_name}) {
228         jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL);
229         size_t _i;
230         jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
231         ${field_length_check}
232         for (_i = 0; _i < cnt; _i++) {
233             mp->${c_name}[_i] = clib_host_to_net_u64(${field_reference_name}ArrayElements[_i]);
234         }
235         (*env)->ReleaseLongArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
236     }
237     """)
238
239 struct_setter_templates = {'u8': u8_struct_setter_template,
240                            'u16': u16_struct_setter_template,
241                            'u32': u32_struct_setter_template,
242                            'i32': u32_struct_setter_template,
243                            'u64': u64_struct_setter_template,
244                            'u8[]': u8_array_struct_setter_template,
245                            'u16[]': u16_array_struct_setter_template,
246                            'u32[]': u32_array_struct_setter_template,
247                            'u64[]': u64_array_struct_setter_template
248                            }
249
250
251 def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_name, field_length,
252                                  is_variable_len_array, object_name="request"):
253     """
254     Generates jni code that initializes C structure that corresponds to a field of java object
255     (dto or custom type). To be used in request message handlers.
256     :param field_type: type of the field to be initialized (as defined in vpe.api)
257     :param c_name: name of the message struct member to be initialized
258     :param field_reference_name: name of the field reference in generated code
259     :param field_name: name of the field (camelcase)
260     :param field_length: integer or name of variable that stores field length
261     :param object_name: name of the object to be initialized
262     """
263     # field identifiers
264     jni_type = util.vpp_2_jni_type_mapping[field_type]
265     jni_signature = util.jni_2_signature_mapping[field_type]
266     jni_getter = util.jni_field_accessors[field_type]
267
268     # field identifier
269     msg_initialization = request_field_identifier_template.substitute(
270             jni_type=jni_type,
271             field_reference_name=field_reference_name,
272             field_name=field_name,
273             jni_signature=jni_signature,
274             jni_getter=jni_getter,
275             object_name=object_name)
276
277     # field setter
278     field_length_check = ""
279
280     # check if we are processing variable length array:
281     if is_variable_len_array:
282         field_length = util.underscore_to_camelcase(field_length)
283
284     # enforce max length if array has fixed length or uses variable length syntax
285     if str(field_length) != "0":
286         field_length_check = array_length_enforcement_template.substitute(field_length=field_length)
287
288     struct_setter_template = struct_setter_templates[field_type]
289
290     msg_initialization += struct_setter_template.substitute(
291             c_name=c_name,
292             field_reference_name=field_reference_name,
293             field_length_check=field_length_check)
294
295     return msg_initialization