
Generates java classes based on typeonly definitions (hashcode, equals and toString methods are also included). Adds JNI handling for request and reply messages (also arrays of custom types). Change-Id: I16f1cea17899704426aa083fad1cb800a8d115df Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
292 lines
13 KiB
Python
292 lines
13 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# Copyright (c) 2016 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
|
|
|
|
import util
|
|
|
|
variable_length_array_value_template = Template("""mp->${length_var_name}""")
|
|
variable_length_array_template = Template("""clib_net_to_host_${length_field_type}(${value})""")
|
|
|
|
dto_field_id_template = Template("""
|
|
jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_name}", "${jni_signature}");""")
|
|
|
|
default_dto_field_setter_template = Template("""
|
|
(*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, mp->${c_name});
|
|
""")
|
|
|
|
variable_length_array_value_template = Template("""mp->${length_var_name}""")
|
|
variable_length_array_template = Template("""clib_net_to_host_${length_field_type}(${value})""")
|
|
|
|
u16_dto_field_setter_template = Template("""
|
|
(*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u16(mp->${c_name}));
|
|
""")
|
|
|
|
u32_dto_field_setter_template = Template("""
|
|
(*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u32(mp->${c_name}));
|
|
""")
|
|
|
|
u64_dto_field_setter_template = Template("""
|
|
(*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, clib_net_to_host_u64(mp->${c_name}));
|
|
""")
|
|
|
|
u8_array_dto_field_setter_template = Template("""
|
|
jbyteArray ${field_reference_name} = (*env)->NewByteArray(env, ${field_length});
|
|
(*env)->SetByteArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const jbyte*)mp->${c_name});
|
|
(*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
|
|
""")
|
|
|
|
u16_array_dto_field_setter_template = Template("""
|
|
{
|
|
jshortArray ${field_reference_name} = (*env)->NewShortArray(env, ${field_length});
|
|
jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL);
|
|
unsigned int _i;
|
|
for (_i = 0; _i < ${field_length}; _i++) {
|
|
${field_reference_name}ArrayElements[_i] = clib_net_to_host_u16(mp->${c_name}[_i]);
|
|
}
|
|
|
|
(*env)->ReleaseShortArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
|
|
(*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
|
|
}
|
|
""")
|
|
|
|
u32_array_dto_field_setter_template = Template("""
|
|
{
|
|
jintArray ${field_reference_name} = (*env)->NewIntArray(env, ${field_length});
|
|
jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL);
|
|
unsigned int _i;
|
|
for (_i = 0; _i < ${field_length}; _i++) {
|
|
${field_reference_name}ArrayElements[_i] = clib_net_to_host_u32(mp->${c_name}[_i]);
|
|
}
|
|
|
|
(*env)->ReleaseIntArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
|
|
(*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
|
|
}
|
|
""")
|
|
|
|
# For each u64 array we get its elements. Then we convert values to host byte order.
|
|
# All changes to jlong* buffer are written to jlongArray (isCopy is set to NULL)
|
|
u64_array_dto_field_setter_template = Template("""
|
|
{
|
|
jlongArray ${field_reference_name} = (*env)->NewLongArray(env, ${field_length});
|
|
jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL);
|
|
unsigned int _i;
|
|
for (_i = 0; _i < ${field_length}; _i++) {
|
|
${field_reference_name}ArrayElements[_i] = clib_net_to_host_u64(mp->${c_name}[_i]);
|
|
}
|
|
|
|
(*env)->ReleaseLongArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
|
|
(*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name});
|
|
}
|
|
""")
|
|
|
|
dto_field_setter_templates = {'u8': default_dto_field_setter_template,
|
|
'u16': u16_dto_field_setter_template,
|
|
'u32': u32_dto_field_setter_template,
|
|
'i32': u32_dto_field_setter_template,
|
|
'u64': u64_dto_field_setter_template,
|
|
'f64': default_dto_field_setter_template, # fixme
|
|
'u8[]': u8_array_dto_field_setter_template,
|
|
'u16[]': u16_array_dto_field_setter_template,
|
|
'u32[]': u32_array_dto_field_setter_template,
|
|
'u64[]': u64_array_dto_field_setter_template
|
|
}
|
|
|
|
|
|
def jni_reply_handler_for_type(handler_name, ref_name, field_type, c_name, field_reference_name,
|
|
field_name, field_length, is_variable_len_array, length_field_type,
|
|
object_name="dto"):
|
|
"""
|
|
Generates jni code that initializes a field of java object (dto or custom type).
|
|
To be used in reply message handlers.
|
|
:param field_type: type of the field to be initialized (as defined in vpe.api)
|
|
:param c_name: name of the message struct member that stores initialization value
|
|
:param field_reference_name: name of the field reference in generated code
|
|
:param field_name: name of the field (camelcase)
|
|
:param field_length: integer or name of variable that stores field length
|
|
:param object_name: name of the object to be initialized
|
|
"""
|
|
|
|
# todo move validation to vppapigen
|
|
if field_type.endswith('[]') and field_length == '0':
|
|
raise Exception('Variable array \'%s\' defined in \'%s\' '
|
|
'should have defined length (e.g. \'%s[%s_length]\''
|
|
% (c_name, handler_name, c_name, c_name))
|
|
|
|
if is_variable_len_array:
|
|
length_var_name = field_length
|
|
field_length = variable_length_array_value_template.substitute(length_var_name=length_var_name)
|
|
if length_field_type != 'u8': # we need net to host conversion:
|
|
field_length = variable_length_array_template.substitute(
|
|
length_field_type=length_field_type, value=field_length)
|
|
|
|
# for retval don't generate setters
|
|
if util.is_retval_field(c_name):
|
|
return ""
|
|
|
|
jni_signature = util.jni_2_signature_mapping[field_type]
|
|
jni_setter = util.jni_field_accessors[field_type]
|
|
|
|
result = dto_field_id_template.substitute(
|
|
field_reference_name=field_reference_name,
|
|
field_name=field_name,
|
|
class_ref_name=ref_name,
|
|
jni_signature=jni_signature)
|
|
|
|
dto_setter_template = dto_field_setter_templates[field_type]
|
|
|
|
result += dto_setter_template.substitute(
|
|
jni_signature=jni_signature,
|
|
object_name=object_name,
|
|
field_reference_name=field_reference_name,
|
|
c_name=c_name,
|
|
jni_setter=jni_setter,
|
|
field_length=field_length)
|
|
return result
|
|
|
|
|
|
request_field_identifier_template = Template("""
|
|
jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${object_name}Class, "${field_name}", "${jni_signature}");
|
|
${jni_type} ${field_reference_name} = (*env)->Get${jni_getter}(env, ${object_name}, ${field_reference_name}FieldId);
|
|
""")
|
|
|
|
array_length_enforcement_template = Template("""
|
|
size_t max_size = ${field_length};
|
|
if (cnt > max_size) cnt = max_size;""")
|
|
|
|
u8_struct_setter_template = Template("""
|
|
mp->${c_name} = ${field_reference_name};""")
|
|
|
|
u16_struct_setter_template = Template("""
|
|
mp->${c_name} = clib_host_to_net_u16(${field_reference_name});""")
|
|
|
|
u32_struct_setter_template = Template("""
|
|
mp->${c_name} = clib_host_to_net_u32(${field_reference_name});""")
|
|
|
|
i32_struct_setter_template = Template("""
|
|
mp->${c_name} = clib_host_to_net_i32(${field_reference_name});!""")
|
|
|
|
u64_struct_setter_template = Template("""
|
|
mp->${c_name} = clib_host_to_net_u64(${field_reference_name});""")
|
|
|
|
array_length_enforcement_template = Template("""
|
|
size_t max_size = ${field_length};
|
|
if (cnt > max_size) cnt = max_size;""")
|
|
|
|
u8_array_struct_setter_template = Template("""
|
|
if (${field_reference_name}) {
|
|
jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
|
|
${field_length_check}
|
|
(*env)->GetByteArrayRegion(env, ${field_reference_name}, 0, cnt, (jbyte *)mp->${c_name});
|
|
}
|
|
""")
|
|
|
|
u16_array_struct_setter_template = Template("""
|
|
jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL);
|
|
if (${field_reference_name}) {
|
|
size_t _i;
|
|
jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
|
|
${field_length_check}
|
|
for (_i = 0; _i < cnt; _i++) {
|
|
mp->${c_name}[_i] = clib_host_to_net_u16(${field_reference_name}ArrayElements[_i]);
|
|
}
|
|
}
|
|
(*env)->ReleaseShortArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
|
|
""")
|
|
|
|
u32_array_struct_setter_template = Template("""
|
|
jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL);
|
|
if (${field_reference_name}) {
|
|
size_t _i;
|
|
jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
|
|
${field_length_check}
|
|
for (_i = 0; _i < cnt; _i++) {
|
|
mp->${c_name}[_i] = clib_host_to_net_u32(${field_reference_name}ArrayElements[_i]);
|
|
}
|
|
}
|
|
(*env)->ReleaseIntArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
|
|
""")
|
|
|
|
u64_array_struct_setter_template = Template("""
|
|
jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL);
|
|
if (${field_reference_name}) {
|
|
size_t _i;
|
|
jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
|
|
${field_length_check}
|
|
for (_i = 0; _i < cnt; _i++) {
|
|
mp->${c_name}[_i] = clib_host_to_net_u64(${field_reference_name}ArrayElements[_i]);
|
|
}
|
|
}
|
|
(*env)->ReleaseLongArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
|
|
""")
|
|
|
|
struct_setter_templates = {'u8': u8_struct_setter_template,
|
|
'u16': u16_struct_setter_template,
|
|
'u32': u32_struct_setter_template,
|
|
'i32': u32_struct_setter_template,
|
|
'u64': u64_struct_setter_template,
|
|
'u8[]': u8_array_struct_setter_template,
|
|
'u16[]': u16_array_struct_setter_template,
|
|
'u32[]': u32_array_struct_setter_template,
|
|
'u64[]': u64_array_struct_setter_template
|
|
}
|
|
|
|
|
|
def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_name, field_length,
|
|
is_variable_len_array, object_name="request"):
|
|
"""
|
|
Generates jni code that initializes C structure that corresponds to a field of java object
|
|
(dto or custom type). To be used in request message handlers.
|
|
:param field_type: type of the field to be initialized (as defined in vpe.api)
|
|
:param c_name: name of the message struct member to be initialized
|
|
:param field_reference_name: name of the field reference in generated code
|
|
:param field_name: name of the field (camelcase)
|
|
:param field_length: integer or name of variable that stores field length
|
|
:param object_name: name of the object to be initialized
|
|
"""
|
|
# field identifiers
|
|
jni_type = util.vpp_2_jni_type_mapping[field_type]
|
|
jni_signature = util.jni_2_signature_mapping[field_type]
|
|
jni_getter = util.jni_field_accessors[field_type]
|
|
|
|
# field identifier
|
|
msg_initialization = request_field_identifier_template.substitute(
|
|
jni_type=jni_type,
|
|
field_reference_name=field_reference_name,
|
|
field_name=field_name,
|
|
jni_signature=jni_signature,
|
|
jni_getter=jni_getter,
|
|
object_name=object_name)
|
|
|
|
# field setter
|
|
field_length_check = ""
|
|
|
|
# check if we are processing variable length array:
|
|
if is_variable_len_array:
|
|
field_length = util.underscore_to_camelcase(field_length)
|
|
|
|
# enforce max length if array has fixed length or uses variable length syntax
|
|
if str(field_length) != "0":
|
|
field_length_check = array_length_enforcement_template.substitute(field_length=field_length)
|
|
|
|
struct_setter_template = struct_setter_templates[field_type]
|
|
|
|
msg_initialization += struct_setter_template.substitute(
|
|
c_name=c_name,
|
|
field_reference_name=field_reference_name,
|
|
field_length_check=field_length_check)
|
|
|
|
return msg_initialization
|