aboutsummaryrefslogtreecommitdiffstats
path: root/extras/japi
diff options
context:
space:
mode:
authorMichal Cmarada <mcmarada@cisco.com>2018-12-06 10:17:39 +0100
committerOle Trøan <otroan@employees.org>2018-12-06 14:04:44 +0000
commit1f0dd7a0664bc217b7d69773574ac7eae3813bd7 (patch)
tree475e9d1900babd0241b3060aa0ac389132d553c5 /extras/japi
parentad69c1fddc4f3d1054cb527e550dfa1698355244 (diff)
Update japi to support type aliases
Change-Id: I6d6068d641d4c91e5c5b52eefb898affc5c0d2c0 Signed-off-by: Michal Cmarada <mcmarada@cisco.com>
Diffstat (limited to 'extras/japi')
-rwxr-xr-xextras/japi/java/jvpp/gen/jvppgen/jni_common_gen.py87
-rwxr-xr-xextras/japi/java/jvpp/gen/jvppgen/jni_impl_gen.py2
-rwxr-xr-xextras/japi/java/jvpp/gen/jvppgen/jni_msg_handlers_gen.py2
-rwxr-xr-xextras/japi/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py21
-rwxr-xr-xextras/japi/java/jvpp/gen/jvppgen/jvpp_model.py46
5 files changed, 126 insertions, 32 deletions
diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_common_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_common_gen.py
index 397b92b528f..708cc1cba81 100755
--- a/extras/japi/java/jvpp/gen/jvppgen/jni_common_gen.py
+++ b/extras/japi/java/jvpp/gen/jvppgen/jni_common_gen.py
@@ -39,21 +39,21 @@ _REQUEST_FIELD_IDENTIFIER_TEMPLATE = Template("""
# TODO(VPP-1187): do not inline JNI object creation inside message handlers to reduce number of special cases
-def generate_j2c_swap(element, struct_ref_name):
+def generate_j2c_swap(element, struct_ref_name, is_alias):
initialization = []
for field in element.fields:
- initialization.append(generate_j2c_field_swap(field, struct_ref_name))
+ initialization.append(generate_j2c_field_swap(field, struct_ref_name, is_alias))
return "\n".join(initialization)
-def generate_j2c_field_swap(field, struct_ref_name):
+def generate_j2c_field_swap(field, struct_ref_name, is_alias):
if is_array(field):
- return _generate_j2c_array_swap(field, struct_ref_name)
+ return _generate_j2c_array_swap(field, struct_ref_name, is_alias)
else:
- return _generate_j2c_scalar_swap(field, struct_ref_name)
+ return _generate_j2c_scalar_swap(field, struct_ref_name, is_alias)
-def _generate_j2c_array_swap(field, struct_ref_name):
+def _generate_j2c_array_swap(field, struct_ref_name, is_alias):
# TODO(VPP-1186): move the logic to JNI generators
base_type = field.type.base_type
if isinstance(base_type, (Class, Enum, Union)):
@@ -61,7 +61,7 @@ def _generate_j2c_array_swap(field, struct_ref_name):
elif base_type.is_swap_needed:
return _generate_j2c_primitive_type_array_swap(field, struct_ref_name)
else:
- return _generate_j2c_primitive_type_array_no_swap(field, struct_ref_name)
+ return _generate_j2c_primitive_type_array_no_swap(field, struct_ref_name, is_alias)
def _generate_j2c_object_array_swap(field, struct_ref_name):
@@ -119,9 +119,14 @@ _J2C_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE = Template("""
""")
-def _generate_j2c_primitive_type_array_no_swap(field, struct_ref_name):
+def _generate_j2c_primitive_type_array_no_swap(field, struct_ref_name, is_alias):
field_type = field.type
- return _J2C_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE.substitute(
+ if not is_alias:
+ template = _J2C_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE
+ else:
+ template = _J2C_ALIAS_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE
+
+ return template.substitute(
field_reference_name=field.java_name,
field_length_check=_generate_field_length_check(field),
base_type=field_type.base_type.jni_accessor,
@@ -139,6 +144,15 @@ _J2C_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE = Template("""
""")
+_J2C_ALIAS_PRIMITIVE_TYPE_ARRAY_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});
+ }
+""")
+
+
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)
@@ -157,17 +171,21 @@ _FIELD_LENGTH_CHECK = Template("""
if (cnt > max_size) cnt = max_size;""")
-def _generate_j2c_scalar_swap(field, struct_ref_name):
+def _generate_j2c_scalar_swap(field, struct_ref_name, is_alias):
field_type = field.type
if field_type.is_swap_needed:
host = field.java_name
- net = "%s->%s" % (struct_ref_name, field.name)
- return " %s;" % field_type.get_host_to_net_function(host, net)
+ if not is_alias:
+ net = "%s->%s" % (struct_ref_name, field.name)
+ return " %s;" % field_type.get_host_to_net_function(host, net)
+ else:
+ net = "%s" % (struct_ref_name)
+ return " *%s;" % field_type.get_host_to_net_function(host, net)
else:
return " %s->%s = %s;" % (struct_ref_name, field.name, field.java_name)
-def generate_c2j_swap(element, object_ref_name, struct_ref_name):
+def generate_c2j_swap(element, object_ref_name, struct_ref_name, is_alias):
msg_java_name = element.java_name_lower
initialization = []
for field in element.fields:
@@ -175,13 +193,13 @@ def generate_c2j_swap(element, object_ref_name, struct_ref_name):
# For retval don't generate setters and generate retval check
continue
elif is_array(field):
- initialization.append(_generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_name))
+ initialization.append(_generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias))
else:
- initialization.append(_generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_name))
+ initialization.append(_generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias))
return "".join(initialization)
-def _generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+def _generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias):
# TODO(VPP-1186): move the logic to JNI generators
base_type = field.type.base_type
if isinstance(base_type, (Class, Union)):
@@ -191,7 +209,7 @@ def _generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_n
elif base_type.is_swap_needed:
return _generate_c2j_primitive_type_array_swap(msg_java_name, field, object_ref_name, struct_ref_name)
else:
- return _generate_c2j_primitive_type_array_no_swap(msg_java_name, field, object_ref_name, struct_ref_name)
+ return _generate_c2j_primitive_type_array_no_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias)
def _generate_c2j_object_array_swap(msg_java_name, field, object_ref_name, struct_ref_name):
@@ -294,9 +312,13 @@ _C2J_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE = Template("""
""")
-def _generate_c2j_primitive_type_array_no_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+def _generate_c2j_primitive_type_array_no_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias):
field_type = field.type
- return _C2J_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE.substitute(
+ if not is_alias:
+ template = _C2J_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE
+ else:
+ template = _C2J_ALIAS_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE
+ return template.substitute(
field_reference_name=field.java_name,
class_ref_name=msg_java_name,
jni_signature=field_type.jni_signature,
@@ -318,6 +340,15 @@ _C2J_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE = Template("""
""")
+_C2J_ALIAS_PRIMITIVE_TYPE_ARRAY_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});
+ (*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
@@ -328,7 +359,7 @@ def _generate_array_length(field, struct_ref_name):
return field.array_len
-def _generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+def _generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias):
field_type = field.type
if field_type.is_swap_needed:
# TODO(VPP-1186): move the logic to JNI generators
@@ -337,7 +368,7 @@ def _generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_
elif isinstance(field_type, Enum):
return _generate_c2j_enum_swap(msg_java_name, field, object_ref_name, struct_ref_name)
else:
- return _generate_c2j_primitive_type_swap(msg_java_name, field, object_ref_name, struct_ref_name)
+ return _generate_c2j_primitive_type_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias)
else:
return _generate_c2j_primitive_type_no_swap(msg_java_name, field, object_ref_name, struct_ref_name)
@@ -390,9 +421,13 @@ _C2J_ENUM_SWAP_TEMPLATE = Template("""
""")
-def _generate_c2j_primitive_type_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+def _generate_c2j_primitive_type_swap(msg_java_name, field, object_ref_name, struct_ref_name, is_alias):
field_type = field.type
- return _C2J_PRIMITIVE_TYPE_SWAP_TEMPLATE.substitute(
+ if not is_alias:
+ template = _C2J_PRIMITIVE_TYPE_SWAP_TEMPLATE
+ else:
+ template = _C2J_ALIAS_PRIMITIVE_TYPE_SWAP_TEMPLATE
+ return template.substitute(
java_name=field.java_name,
class_ref_name=msg_java_name,
jni_signature=field_type.jni_signature,
@@ -409,6 +444,12 @@ _C2J_PRIMITIVE_TYPE_SWAP_TEMPLATE = Template("""
""")
+_C2J_ALIAS_PRIMITIVE_TYPE_SWAP_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}));
+""")
+
+
def _generate_c2j_primitive_type_no_swap(msg_java_name, field, object_ref_name, struct_ref_name):
field_type = field.type
return _C2J_PRIMITIVE_TYPE_NO_SWAP_TEMPLATE.substitute(
diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_impl_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_impl_gen.py
index bf7523670a4..717a42c452a 100755
--- a/extras/japi/java/jvpp/gen/jvppgen/jni_impl_gen.py
+++ b/extras/japi/java/jvpp/gen/jvppgen/jni_impl_gen.py
@@ -43,7 +43,7 @@ def generate_jni_impl(model):
java_dto_name=msg.java_name_upper
)
jni_identifiers = generate_j2c_identifiers(msg, class_ref_name="requestClass", object_ref_name="request")
- msg_initialization = generate_j2c_swap(msg, struct_ref_name="mp")
+ msg_initialization = generate_j2c_swap(msg, struct_ref_name="mp", is_alias=False)
jni_impl.append(_JNI_IMPL_TEMPLATE.substitute(
c_name=msg.name,
diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_msg_handlers_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_msg_handlers_gen.py
index 8f6410f1af2..5f274a3e1dd 100755
--- a/extras/japi/java/jvpp/gen/jvppgen/jni_msg_handlers_gen.py
+++ b/extras/japi/java/jvpp/gen/jvppgen/jni_msg_handlers_gen.py
@@ -41,7 +41,7 @@ def generate_jni_handlers(model):
err_handler=_generate_error_handler(msg),
class_ref_name=msg.java_name_lower,
dto_name=msg.java_name_upper,
- dto_setters=generate_c2j_swap(msg, object_ref_name="dto", struct_ref_name="mp")
+ dto_setters=generate_c2j_swap(msg, object_ref_name="dto", struct_ref_name="mp", is_alias=False)
))
return "".join(jni_impl)
diff --git a/extras/japi/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py b/extras/japi/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py
index 2447974d878..59aaf95065a 100755
--- a/extras/japi/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py
+++ b/extras/japi/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py
@@ -42,6 +42,11 @@ def generate_type_handlers(model, logger):
def _generate_class(model, t, type_handlers):
ref_name = t.java_name_lower
+ if t.name in model._aliases:
+ is_alias = True
+ else:
+ is_alias = False
+
type_handlers.append(_TYPE_HOST_TO_NET_TEMPLATE.substitute(
c_name=t.name,
json_filename=model.json_api_files,
@@ -49,7 +54,7 @@ def _generate_class(model, t, type_handlers):
type_reference_name=ref_name,
class_FQN=t.jni_name,
jni_identifiers=generate_j2c_identifiers(t, class_ref_name="%sClass" % ref_name, object_ref_name="_host"),
- type_swap=generate_j2c_swap(t, struct_ref_name="_net")
+ type_swap=generate_j2c_swap(t, struct_ref_name="_net", is_alias=is_alias)
))
type_handlers.append(_TYPE_NET_TO_HOST_TEMPLATE.substitute(
c_name=t.name,
@@ -57,7 +62,7 @@ def _generate_class(model, t, type_handlers):
json_definition=t.doc,
type_reference_name=ref_name,
class_FQN=t.jni_name,
- type_swap=generate_c2j_swap(t, object_ref_name="_host", struct_ref_name="_net")
+ type_swap=generate_c2j_swap(t, object_ref_name="_host", struct_ref_name="_net", is_alias=is_alias)
))
_TYPE_HOST_TO_NET_TEMPLATE = Template("""
@@ -159,13 +164,17 @@ def _generate_union_host_to_net(model, t):
swap = []
for i, field in enumerate(t.fields):
field_type = field.type
+ if t.name in model._aliases:
+ is_alias = True
+ else:
+ is_alias = False
swap.append(_UNION_FIELD_HOST_TO_NET_TEMPLATE.substitute(
field_index=i,
java_name=field.java_name,
jni_signature=field_type.jni_signature,
jni_type=field_type.jni_type,
jni_accessor=field_type.jni_accessor,
- swap=generate_j2c_field_swap(field, struct_ref_name="_net")
+ swap=generate_j2c_field_swap(field, struct_ref_name="_net", is_alias=is_alias)
))
return _UNION_HOST_TO_NET_TEMPLATE.substitute(
@@ -200,13 +209,17 @@ $swap
def _generate_union_net_to_host(model, t):
+ if t.name in model._aliases:
+ is_alias = True
+ else:
+ is_alias = False
return _UNION_NET_TO_HOST_TEMPLATE.substitute(
c_name=t.name,
json_filename=model.json_api_files,
json_definition=t.doc,
type_reference_name=t.java_name_lower,
class_FQN=t.jni_name,
- swap=generate_c2j_swap(t, object_ref_name="_host", struct_ref_name="_net")
+ swap=generate_c2j_swap(t, object_ref_name="_host", struct_ref_name="_net", is_alias=is_alias)
)
_UNION_NET_TO_HOST_TEMPLATE = Template("""
diff --git a/extras/japi/java/jvpp/gen/jvppgen/jvpp_model.py b/extras/japi/java/jvpp/gen/jvppgen/jvpp_model.py
index 3c2db15d176..16099689880 100755
--- a/extras/japi/java/jvpp/gen/jvppgen/jvpp_model.py
+++ b/extras/japi/java/jvpp/gen/jvppgen/jvpp_model.py
@@ -17,6 +17,8 @@ import json
import pprint
from collections import OrderedDict
+import binascii
+
BASE_PACKAGE = "io.fd.vpp.jvpp"
@@ -303,6 +305,11 @@ def is_control_ping_reply(msg):
return msg.name == u'control_ping_reply'
+def crc(block):
+ s = str(block).encode()
+ return binascii.crc32(s) & 0xffffffff
+
+
class JVppModel(object):
def __init__(self, logger, json_api_files, plugin_name):
self.logger = logger
@@ -333,8 +340,43 @@ class JVppModel(object):
self._parse_types(types)
+ def _parse_aliases(self, types):
+ for alias_name in self._aliases:
+ alias = self._aliases[alias_name]
+ alias_type = {"type": "type"}
+ java_name_lower = _underscore_to_camelcase_lower(alias_name)
+ vpp_type = alias["type"]
+ crc_value = '0x%08x' % crc(alias_name)
+ if "length" in alias:
+ length = alias["length"]
+ alias_type["data"] = [
+ alias_name,
+ [
+ vpp_type,
+ java_name_lower,
+ length
+ ],
+ {
+ "crc": crc_value
+ }
+ ]
+ else:
+ alias_type["data"] = [
+ alias_name,
+ [
+ vpp_type,
+ java_name_lower
+ ],
+ {
+ "crc": crc_value
+ }
+ ]
+
+ types[alias_name] = alias_type
+
def _parse_types(self, types):
self._parse_simple_types()
+ self._parse_aliases(types)
i = 0
while True:
unresolved = {}
@@ -484,9 +526,6 @@ class JVppModel(object):
def _parse_field(self, field, fields):
type_name = _extract_type_name(field[0])
- if type_name in self._aliases and type_name not in self._types_by_name:
- aliased_type = self._types_by_name.get(self._aliases.get(type_name).get("type"))
- self._types_by_name[type_name] = aliased_type
if type_name in self._types_by_name:
if len(field) > 2:
@@ -524,6 +563,7 @@ class JVppModel(object):
self.messages = self._messages_by_name.values()
+
_ARRAY_SUFFIX = '[]'