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