aboutsummaryrefslogtreecommitdiffstats
path: root/src/vpp-api/java/jvpp/gen/jvppgen/jni_common_gen.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/vpp-api/java/jvpp/gen/jvppgen/jni_common_gen.py')
-rwxr-xr-xsrc/vpp-api/java/jvpp/gen/jvppgen/jni_common_gen.py267
1 files changed, 267 insertions, 0 deletions
diff --git a/src/vpp-api/java/jvpp/gen/jvppgen/jni_common_gen.py b/src/vpp-api/java/jvpp/gen/jvppgen/jni_common_gen.py
new file mode 100755
index 00000000000..6f2995d4f8c
--- /dev/null
+++ b/src/vpp-api/java/jvpp/gen/jvppgen/jni_common_gen.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python2
+#
+# Copyright (c) 2018 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+from string import Template
+
+from jvpp_model import is_array, Class, is_retval
+
+
+def generate_j2c_identifiers(element, class_ref_name, object_ref_name):
+ identifiers = []
+ for field in element.fields:
+ field_type = field.type
+ identifiers.append(_REQUEST_FIELD_IDENTIFIER_TEMPLATE.substitute(
+ java_name=field.java_name,
+ class_ref_name=class_ref_name,
+ jni_signature=field_type.jni_signature,
+ jni_type=field_type.jni_type,
+ jni_accessor=field_type.jni_accessor,
+ object_ref_name=object_ref_name
+ ))
+ return "".join(identifiers)
+
+_REQUEST_FIELD_IDENTIFIER_TEMPLATE = Template("""
+ jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}, "${java_name}", "${jni_signature}");
+ ${jni_type} ${java_name} = (*env)->Get${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId);
+""")
+
+
+# TODO(VPP-1185): introduce host_to_net functions wrappers and simplify j2c and c2j swap generation
+def generate_j2c_swap(element, struct_ref_name):
+ initialization = []
+ for field in element.fields:
+ field_type = field.type
+ if is_array(field):
+ template = _ARRAY_J2C_NO_SWAP_TEMPLATE
+ field_reference_name = field.java_name
+ c_name = field.name
+ swap_elements = None
+ jni_name = None
+ if field_type.is_swap_needed:
+ template = _ARRAY_J2C_SWAP_TEMPLATE
+ host = "%sArrayElements[_i]" % field_reference_name
+ net = "%s->%s[_i]" % (struct_ref_name, c_name)
+ swap_elements = field_type.get_host_to_net_function(host, net)
+ if isinstance(field_type.base_type, Class):
+ jni_name = field_type.base_type.jni_name
+ host = "%sArrayElement" % field_reference_name
+ net = "%s->%s[_i]" % (struct_ref_name, c_name)
+ swap_elements = field_type.get_host_to_net_function(host, net)
+ template = _CLASS_ARRAY_J2C_TEMPLATE
+
+ initialization.append(template.substitute(
+ field_reference_name=field_reference_name,
+ field_length_check=_generate_field_length_check(field),
+ base_type=field_type.base_type.jni_accessor,
+ jni_base_type=field_type.base_type.jni_type,
+ struct_reference_name=struct_ref_name,
+ jni_name=jni_name,
+ c_name=c_name,
+ swap_elements=swap_elements
+ ))
+ else:
+ if field_type.is_swap_needed:
+ host = field.java_name
+ net = "%s->%s" % (struct_ref_name, field.name)
+ initialization.append(" %s;" % field_type.get_host_to_net_function(host, net))
+ else:
+ initialization.append(" %s->%s = %s;" % (struct_ref_name, field.name, field.java_name))
+
+ return "\n".join(initialization)
+
+_ARRAY_J2C_NO_SWAP_TEMPLATE = Template("""
+ if (${field_reference_name}) {
+ jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+ ${field_length_check}
+ (*env)->Get${base_type}ArrayRegion(env, ${field_reference_name}, 0, cnt, (${jni_base_type} *)${struct_reference_name}->${c_name});
+ }
+""")
+
+_ARRAY_J2C_SWAP_TEMPLATE = Template("""
+ if (${field_reference_name}) {
+ ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL);
+ size_t _i;
+ jsize cnt = (*env)->GetArrayLength(env, ${field_reference_name});
+ ${field_length_check}
+ for (_i = 0; _i < cnt; _i++) {
+ ${swap_elements};
+ }
+ (*env)->Release${base_type}ArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
+ }
+ """)
+
+_CLASS_ARRAY_J2C_TEMPLATE = Template("""
+ {
+ if (${field_reference_name}) {
+ size_t _i;
+ jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+ ${field_length_check}
+ for (_i = 0; _i < cnt; _i++) {
+ jobject ${field_reference_name}ArrayElement = (*env)->GetObjectArrayElement(env, ${field_reference_name}, _i);
+ ${swap_elements};
+ }
+ }
+ }
+""")
+
+
+def _generate_field_length_check(field):
+ # Enforce max length if array has fixed length or uses variable length syntax
+ field_length = str(field.array_len)
+ if field.array_len_field:
+ field_length = field.array_len_field.java_name
+
+ # TODO: remove when ZLAs without length field are disabled
+ if field_length != "0":
+ return _FIELD_LENGTH_CHECK.substitute(field_length=field_length)
+ else:
+ return ""
+
+# Make sure we do not write more elements that are expected
+_FIELD_LENGTH_CHECK = Template("""
+ size_t max_size = ${field_length};
+ if (cnt > max_size) cnt = max_size;""")
+
+
+def generate_c2j_swap(element, object_ref_name, struct_ref_name):
+ msg_java_name = element.java_name_lower
+ setters = []
+ for field in element.fields:
+ field_type = field.type
+ if is_retval(field):
+ # For retval don't generate setters and generate retval check
+ continue
+ elif is_array(field):
+ jni_name = ""
+ template = _ARRAY_C2J_SWAP_TEMPLATE if field_type.is_swap_needed else _ARRAY_C2J_NO_SWAP_TEMPLATE
+ if isinstance(field_type.base_type, Class):
+ template = _ARRAY_C2J_CLASS_SWAP_TEMPLATE
+ jni_name = field_type.base_type.jni_name
+ setters.append(template.substitute(
+ field_reference_name=field.java_name,
+ class_ref_name=msg_java_name,
+ jni_signature=field_type.jni_signature,
+ jni_type=field_type.jni_type,
+ jni_name=jni_name,
+ base_type=field_type.base_type.jni_accessor,
+ field_length=_generate_array_length(field, struct_ref_name),
+ jni_base_type=field_type.base_type.jni_type,
+ object_ref_name=object_ref_name,
+ struct_ref_name=struct_ref_name,
+ net_to_host_function=field_type.net_to_host_function,
+ c_name=field.name
+ ))
+ else:
+ if field_type.is_swap_needed:
+ template = _SIMPLE_TYPE_FIELD_SETTER_TEMPLATE
+ jni_name = ""
+ if isinstance(field_type, Class):
+ template = _STRUCT_SETTER_TEMPLATE
+ jni_name = field_type.jni_name
+ setters.append(template.substitute(
+ java_name=field.java_name,
+ class_ref_name=msg_java_name,
+ jni_signature=field_type.jni_signature,
+ jni_name=jni_name,
+ jni_accessor=field_type.jni_accessor,
+ object_ref_name=object_ref_name,
+ struct_ref_name=struct_ref_name,
+ net_to_host_function=field_type.net_to_host_function,
+ c_name=field.name
+ ))
+ else:
+ setters.append(_SIMPLE_TYPE_NO_SWAP_FIELD_SETTER_TEMPLATE.substitute(
+ java_name=field.java_name,
+ class_ref_name=msg_java_name,
+ jni_signature=field_type.jni_signature,
+ jni_accessor=field_type.jni_accessor,
+ object_ref_name=object_ref_name,
+ struct_ref_name=struct_ref_name,
+ c_name=field.name
+ ))
+ return "".join(setters)
+
+
+_SIMPLE_TYPE_FIELD_SETTER_TEMPLATE = Template("""
+ jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
+ (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${net_to_host_function}(${struct_ref_name}->${c_name}));
+""")
+
+_STRUCT_SETTER_TEMPLATE = Template("""
+ jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
+ jclass ${java_name}Class = (*env)->FindClass(env, "${jni_name}");
+ jmethodID ${java_name}Constructor = (*env)->GetMethodID(env, ${java_name}Class, "<init>", "()V");
+ jobject ${java_name} = (*env)->NewObject(env, ${java_name}Class, ${java_name}Constructor);
+ ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}), ${java_name});
+ (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${java_name});
+ (*env)->DeleteLocalRef(env, ${java_name});
+""")
+
+_SIMPLE_TYPE_NO_SWAP_FIELD_SETTER_TEMPLATE = Template("""
+ jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
+ (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${struct_ref_name}->${c_name});
+""")
+
+_ARRAY_C2J_NO_SWAP_TEMPLATE = Template("""
+ jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
+ ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length});
+ (*env)->Set${base_type}ArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const ${jni_base_type}*)${struct_ref_name}->${c_name});
+ (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
+ (*env)->DeleteLocalRef(env, ${field_reference_name});
+""")
+
+_ARRAY_C2J_SWAP_TEMPLATE = Template("""
+ jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
+ {
+ ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length});
+ ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL);
+ unsigned int _i;
+ for (_i = 0; _i < ${field_length}; _i++) {
+ ${field_reference_name}ArrayElements[_i] = ${net_to_host_function}(${struct_ref_name}->${c_name}[_i]);
+ }
+
+ (*env)->Release${base_type}ArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
+ (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
+ (*env)->DeleteLocalRef(env, ${field_reference_name});
+ }
+""")
+
+_ARRAY_C2J_CLASS_SWAP_TEMPLATE = Template("""
+ jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
+ {
+ jclass ${field_reference_name}Class = (*env)->FindClass(env, "${jni_name}");
+ jobjectArray ${field_reference_name} = (*env)->NewObjectArray(env, ${field_length}, ${field_reference_name}Class, 0);
+ jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V");
+ unsigned int _i;
+ for (_i = 0; _i < ${field_length}; _i++) {
+ jobject ${field_reference_name}ArrayElement = (*env)->NewObject(env, ${field_reference_name}Class, ${field_reference_name}Constructor);
+ ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}[_i]), ${field_reference_name}ArrayElement);
+ (*env)->SetObjectArrayElement(env, ${field_reference_name}, _i, ${field_reference_name}ArrayElement);
+ (*env)->DeleteLocalRef(env, ${field_reference_name}ArrayElement);
+ }
+ (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
+ (*env)->DeleteLocalRef(env, ${field_reference_name});
+ }
+""")
+
+
+def _generate_array_length(field, struct_ref_name):
+ if field.array_len_field:
+ len_field = field.array_len_field
+ if len_field.type.is_swap_needed:
+ return "%s(%s->%s)" % (len_field.type.host_to_net_function, struct_ref_name, len_field.name)
+ else:
+ return "%s->%s" % (struct_ref_name, len_field.name)
+ return field.array_len