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