3 # Copyright (c) 2018 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
18 from jvpp_model import is_array, Class, is_retval
21 def generate_j2c_identifiers(element, class_ref_name, object_ref_name):
23 for field in element.fields:
24 field_type = field.type
25 identifiers.append(_REQUEST_FIELD_IDENTIFIER_TEMPLATE.substitute(
26 java_name=field.java_name,
27 class_ref_name=class_ref_name,
28 jni_signature=field_type.jni_signature,
29 jni_type=field_type.jni_type,
30 jni_accessor=field_type.jni_accessor,
31 object_ref_name=object_ref_name
33 return "".join(identifiers)
35 _REQUEST_FIELD_IDENTIFIER_TEMPLATE = Template("""
36 jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}, "${java_name}", "${jni_signature}");
37 ${jni_type} ${java_name} = (*env)->Get${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId);
41 # TODO(VPP-1185): introduce host_to_net functions wrappers and simplify j2c and c2j swap generation
42 def generate_j2c_swap(element, struct_ref_name):
44 for field in element.fields:
45 field_type = field.type
47 template = _ARRAY_J2C_NO_SWAP_TEMPLATE
48 field_reference_name = field.java_name
52 if field_type.is_swap_needed:
53 template = _ARRAY_J2C_SWAP_TEMPLATE
54 host = "%sArrayElements[_i]" % field_reference_name
55 net = "%s->%s[_i]" % (struct_ref_name, c_name)
56 swap_elements = field_type.get_host_to_net_function(host, net)
57 if isinstance(field_type.base_type, Class):
58 jni_name = field_type.base_type.jni_name
59 host = "%sArrayElement" % field_reference_name
60 net = "%s->%s[_i]" % (struct_ref_name, c_name)
61 swap_elements = field_type.get_host_to_net_function(host, net)
62 template = _CLASS_ARRAY_J2C_TEMPLATE
64 initialization.append(template.substitute(
65 field_reference_name=field_reference_name,
66 field_length_check=_generate_field_length_check(field),
67 base_type=field_type.base_type.jni_accessor,
68 jni_base_type=field_type.base_type.jni_type,
69 struct_reference_name=struct_ref_name,
72 swap_elements=swap_elements
75 if field_type.is_swap_needed:
76 host = field.java_name
77 net = "%s->%s" % (struct_ref_name, field.name)
78 initialization.append(" %s;" % field_type.get_host_to_net_function(host, net))
80 initialization.append(" %s->%s = %s;" % (struct_ref_name, field.name, field.java_name))
82 return "\n".join(initialization)
84 _ARRAY_J2C_NO_SWAP_TEMPLATE = Template("""
85 if (${field_reference_name}) {
86 jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
88 (*env)->Get${base_type}ArrayRegion(env, ${field_reference_name}, 0, cnt, (${jni_base_type} *)${struct_reference_name}->${c_name});
92 _ARRAY_J2C_SWAP_TEMPLATE = Template("""
93 if (${field_reference_name}) {
94 ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL);
96 jsize cnt = (*env)->GetArrayLength(env, ${field_reference_name});
98 for (_i = 0; _i < cnt; _i++) {
101 (*env)->Release${base_type}ArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
105 _CLASS_ARRAY_J2C_TEMPLATE = Template("""
107 if (${field_reference_name}) {
109 jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
110 ${field_length_check}
111 for (_i = 0; _i < cnt; _i++) {
112 jobject ${field_reference_name}ArrayElement = (*env)->GetObjectArrayElement(env, ${field_reference_name}, _i);
120 def _generate_field_length_check(field):
121 # Enforce max length if array has fixed length or uses variable length syntax
122 field_length = str(field.array_len)
123 if field.array_len_field:
124 field_length = field.array_len_field.java_name
126 # TODO: remove when ZLAs without length field are disabled
127 if field_length != "0":
128 return _FIELD_LENGTH_CHECK.substitute(field_length=field_length)
132 # Make sure we do not write more elements that are expected
133 _FIELD_LENGTH_CHECK = Template("""
134 size_t max_size = ${field_length};
135 if (cnt > max_size) cnt = max_size;""")
138 def generate_c2j_swap(element, object_ref_name, struct_ref_name):
139 msg_java_name = element.java_name_lower
141 for field in element.fields:
142 field_type = field.type
144 # For retval don't generate setters and generate retval check
146 elif is_array(field):
148 template = _ARRAY_C2J_SWAP_TEMPLATE if field_type.is_swap_needed else _ARRAY_C2J_NO_SWAP_TEMPLATE
149 if isinstance(field_type.base_type, Class):
150 template = _ARRAY_C2J_CLASS_SWAP_TEMPLATE
151 jni_name = field_type.base_type.jni_name
152 setters.append(template.substitute(
153 field_reference_name=field.java_name,
154 class_ref_name=msg_java_name,
155 jni_signature=field_type.jni_signature,
156 jni_type=field_type.jni_type,
158 base_type=field_type.base_type.jni_accessor,
159 field_length=_generate_array_length(field, struct_ref_name),
160 jni_base_type=field_type.base_type.jni_type,
161 object_ref_name=object_ref_name,
162 struct_ref_name=struct_ref_name,
163 net_to_host_function=field_type.net_to_host_function,
167 if field_type.is_swap_needed:
168 template = _SIMPLE_TYPE_FIELD_SETTER_TEMPLATE
170 if isinstance(field_type, Class):
171 template = _STRUCT_SETTER_TEMPLATE
172 jni_name = field_type.jni_name
173 setters.append(template.substitute(
174 java_name=field.java_name,
175 class_ref_name=msg_java_name,
176 jni_signature=field_type.jni_signature,
178 jni_accessor=field_type.jni_accessor,
179 object_ref_name=object_ref_name,
180 struct_ref_name=struct_ref_name,
181 net_to_host_function=field_type.net_to_host_function,
185 setters.append(_SIMPLE_TYPE_NO_SWAP_FIELD_SETTER_TEMPLATE.substitute(
186 java_name=field.java_name,
187 class_ref_name=msg_java_name,
188 jni_signature=field_type.jni_signature,
189 jni_accessor=field_type.jni_accessor,
190 object_ref_name=object_ref_name,
191 struct_ref_name=struct_ref_name,
194 return "".join(setters)
197 _SIMPLE_TYPE_FIELD_SETTER_TEMPLATE = Template("""
198 jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
199 (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${net_to_host_function}(${struct_ref_name}->${c_name}));
202 _STRUCT_SETTER_TEMPLATE = Template("""
203 jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
204 jclass ${java_name}Class = (*env)->FindClass(env, "${jni_name}");
205 jmethodID ${java_name}Constructor = (*env)->GetMethodID(env, ${java_name}Class, "<init>", "()V");
206 jobject ${java_name} = (*env)->NewObject(env, ${java_name}Class, ${java_name}Constructor);
207 ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}), ${java_name});
208 (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${java_name});
209 (*env)->DeleteLocalRef(env, ${java_name});
212 _SIMPLE_TYPE_NO_SWAP_FIELD_SETTER_TEMPLATE = Template("""
213 jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
214 (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${struct_ref_name}->${c_name});
217 _ARRAY_C2J_NO_SWAP_TEMPLATE = Template("""
218 jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
219 ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length});
220 (*env)->Set${base_type}ArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const ${jni_base_type}*)${struct_ref_name}->${c_name});
221 (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
222 (*env)->DeleteLocalRef(env, ${field_reference_name});
225 _ARRAY_C2J_SWAP_TEMPLATE = Template("""
226 jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
228 ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length});
229 ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL);
231 for (_i = 0; _i < ${field_length}; _i++) {
232 ${field_reference_name}ArrayElements[_i] = ${net_to_host_function}(${struct_ref_name}->${c_name}[_i]);
235 (*env)->Release${base_type}ArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
236 (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
237 (*env)->DeleteLocalRef(env, ${field_reference_name});
241 _ARRAY_C2J_CLASS_SWAP_TEMPLATE = Template("""
242 jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
244 jclass ${field_reference_name}Class = (*env)->FindClass(env, "${jni_name}");
245 jobjectArray ${field_reference_name} = (*env)->NewObjectArray(env, ${field_length}, ${field_reference_name}Class, 0);
246 jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V");
248 for (_i = 0; _i < ${field_length}; _i++) {
249 jobject ${field_reference_name}ArrayElement = (*env)->NewObject(env, ${field_reference_name}Class, ${field_reference_name}Constructor);
250 ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}[_i]), ${field_reference_name}ArrayElement);
251 (*env)->SetObjectArrayElement(env, ${field_reference_name}, _i, ${field_reference_name}ArrayElement);
252 (*env)->DeleteLocalRef(env, ${field_reference_name}ArrayElement);
254 (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
255 (*env)->DeleteLocalRef(env, ${field_reference_name});
260 def _generate_array_length(field, struct_ref_name):
261 if field.array_len_field:
262 len_field = field.array_len_field
263 if len_field.type.is_swap_needed:
264 return "%s(%s->%s)" % (len_field.type.host_to_net_function, struct_ref_name, len_field.name)
266 return "%s->%s" % (struct_ref_name, len_field.name)
267 return field.array_len