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:
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
16 from string import Template
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})""")
23 dto_field_id_template = Template("""
24 jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_name}", "${jni_signature}");""")
26 default_dto_field_setter_template = Template("""
27 (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, mp->${c_name});
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})""")
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}));
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}));
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}));
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});
52 u16_array_dto_field_setter_template = Template("""
54 jshortArray ${field_reference_name} = (*env)->NewShortArray(env, ${field_length});
55 jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL);
57 for (_i = 0; _i < ${field_length}; _i++) {
58 ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u16(mp->${c_name}[_i]);
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});
67 u32_array_dto_field_setter_template = Template("""
69 jintArray ${field_reference_name} = (*env)->NewIntArray(env, ${field_length});
70 jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL);
72 for (_i = 0; _i < ${field_length}; _i++) {
73 ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u32(mp->${c_name}[_i]);
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});
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("""
86 jlongArray ${field_reference_name} = (*env)->NewLongArray(env, ${field_length});
87 jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL);
89 for (_i = 0; _i < ${field_length}; _i++) {
90 ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u64(mp->${c_name}[_i]);
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});
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
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,
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
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))
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)
139 # for retval don't generate setters
140 if util.is_retval_field(c_name):
143 jni_signature = util.jni_2_signature_mapping[field_type]
144 jni_setter = util.jni_field_accessors[field_type]
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)
152 dto_setter_template = dto_field_setter_templates[field_type]
154 result += dto_setter_template.substitute(
155 jni_signature=jni_signature,
156 object_name=object_name,
157 field_reference_name=field_reference_name,
159 jni_setter=jni_setter,
160 field_length=field_length)
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);
169 array_length_enforcement_template = Template("""
170 size_t max_size = ${field_length};
171 if (cnt > max_size) cnt = max_size;""")
173 u8_struct_setter_template = Template("""
174 mp->${c_name} = ${field_reference_name};""")
176 u16_struct_setter_template = Template("""
177 mp->${c_name} = clib_host_to_net_u16(${field_reference_name});""")
179 u32_struct_setter_template = Template("""
180 mp->${c_name} = clib_host_to_net_u32(${field_reference_name});""")
182 i32_struct_setter_template = Template("""
183 mp->${c_name} = clib_host_to_net_i32(${field_reference_name});!""")
185 u64_struct_setter_template = Template("""
186 mp->${c_name} = clib_host_to_net_u64(${field_reference_name});""")
188 array_length_enforcement_template = Template("""
189 size_t max_size = ${field_length};
190 if (cnt > max_size) cnt = max_size;""")
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});
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);
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]);
209 (*env)->ReleaseShortArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
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);
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]);
222 (*env)->ReleaseIntArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
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);
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]);
235 (*env)->ReleaseLongArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
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
251 def jni_request_identifiers_for_type(field_type, field_reference_name, field_name, object_name="request"):
253 Generates jni code that defines C variable corresponding to field of java object
254 (dto or custom type). To be used in request message handlers.
255 :param field_type: type of the field to be initialized (as defined in vpe.api)
256 :param field_reference_name: name of the field reference in generated code
257 :param field_name: name of the field (camelcase)
258 :param object_name: name of the object to be initialized
261 jni_type = util.vpp_2_jni_type_mapping[field_type]
262 jni_signature = util.jni_2_signature_mapping[field_type]
263 jni_getter = util.jni_field_accessors[field_type]
266 return request_field_identifier_template.substitute(
268 field_reference_name=field_reference_name,
269 field_name=field_name,
270 jni_signature=jni_signature,
271 jni_getter=jni_getter,
272 object_name=object_name)
275 def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_length, is_variable_len_array):
277 Generates jni code that initializes C structure that corresponds to a field of java object
278 (dto or custom type). To be used in request message handlers.
279 :param field_type: type of the field to be initialized (as defined in vpe.api)
280 :param c_name: name of the message struct member to be initialized
281 :param field_reference_name: name of the field reference in generated code
282 :param field_length: integer or name of variable that stores field length
286 field_length_check = ""
288 # check if we are processing variable length array:
289 if is_variable_len_array:
290 field_length = util.underscore_to_camelcase(field_length)
292 # enforce max length if array has fixed length or uses variable length syntax
293 if str(field_length) != "0":
294 field_length_check = array_length_enforcement_template.substitute(field_length=field_length)
296 struct_setter_template = struct_setter_templates[field_type]
298 msg_initialization = struct_setter_template.substitute(
300 field_reference_name=field_reference_name,
301 field_length_check=field_length_check)
303 return msg_initialization