Marek Gradzki | 81c7dfc | 2016-09-29 13:22:35 +0200 | [diff] [blame^] | 1 | #!/usr/bin/env python |
| 2 | # |
| 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: |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 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. |
| 15 | |
| 16 | from string import Template |
| 17 | |
| 18 | import util |
| 19 | |
| 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})""") |
| 22 | |
| 23 | dto_field_id_template = Template(""" |
| 24 | jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_name}", "${jni_signature}");""") |
| 25 | |
| 26 | default_dto_field_setter_template = Template(""" |
| 27 | (*env)->Set${jni_setter}(env, ${object_name}, ${field_reference_name}FieldId, mp->${c_name}); |
| 28 | """) |
| 29 | |
| 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})""") |
| 32 | |
| 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})); |
| 35 | """) |
| 36 | |
| 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})); |
| 39 | """) |
| 40 | |
| 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})); |
| 43 | """) |
| 44 | |
| 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 | """) |
| 50 | |
| 51 | u16_array_dto_field_setter_template = Template(""" |
| 52 | { |
| 53 | jshortArray ${field_reference_name} = (*env)->NewShortArray(env, ${field_length}); |
| 54 | jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL); |
| 55 | unsigned int _i; |
| 56 | for (_i = 0; _i < ${field_length}; _i++) { |
| 57 | ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u16(mp->${c_name}[_i]); |
| 58 | } |
| 59 | |
| 60 | (*env)->ReleaseShortArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0); |
| 61 | (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name}); |
| 62 | } |
| 63 | """) |
| 64 | |
| 65 | u32_array_dto_field_setter_template = Template(""" |
| 66 | { |
| 67 | jintArray ${field_reference_name} = (*env)->NewIntArray(env, ${field_length}); |
| 68 | jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL); |
| 69 | unsigned int _i; |
| 70 | for (_i = 0; _i < ${field_length}; _i++) { |
| 71 | ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u32(mp->${c_name}[_i]); |
| 72 | } |
| 73 | |
| 74 | (*env)->ReleaseIntArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0); |
| 75 | (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name}); |
| 76 | } |
| 77 | """) |
| 78 | |
| 79 | # For each u64 array we get its elements. Then we convert values to host byte order. |
| 80 | # All changes to jlong* buffer are written to jlongArray (isCopy is set to NULL) |
| 81 | u64_array_dto_field_setter_template = Template(""" |
| 82 | { |
| 83 | jlongArray ${field_reference_name} = (*env)->NewLongArray(env, ${field_length}); |
| 84 | jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL); |
| 85 | unsigned int _i; |
| 86 | for (_i = 0; _i < ${field_length}; _i++) { |
| 87 | ${field_reference_name}ArrayElements[_i] = clib_net_to_host_u64(mp->${c_name}[_i]); |
| 88 | } |
| 89 | |
| 90 | (*env)->ReleaseLongArrayElements(env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0); |
| 91 | (*env)->SetObjectField(env, ${object_name}, ${field_reference_name}FieldId, ${field_reference_name}); |
| 92 | } |
| 93 | """) |
| 94 | |
| 95 | dto_field_setter_templates = {'u8': default_dto_field_setter_template, |
| 96 | 'u16': u16_dto_field_setter_template, |
| 97 | 'u32': u32_dto_field_setter_template, |
| 98 | 'i32': u32_dto_field_setter_template, |
| 99 | 'u64': u64_dto_field_setter_template, |
| 100 | 'f64': default_dto_field_setter_template, # fixme |
| 101 | 'u8[]': u8_array_dto_field_setter_template, |
| 102 | 'u16[]': u16_array_dto_field_setter_template, |
| 103 | 'u32[]': u32_array_dto_field_setter_template, |
| 104 | 'u64[]': u64_array_dto_field_setter_template |
| 105 | } |
| 106 | |
| 107 | |
| 108 | def jni_reply_handler_for_type(handler_name, ref_name, field_type, c_name, field_reference_name, |
| 109 | field_name, field_length, is_variable_len_array, length_field_type, |
| 110 | object_name="dto"): |
| 111 | """ |
| 112 | Generates jni code that initializes a field of java object (dto or custom type). |
| 113 | To be used in reply message handlers. |
| 114 | :param field_type: type of the field to be initialized (as defined in vpe.api) |
| 115 | :param c_name: name of the message struct member that stores initialization value |
| 116 | :param field_reference_name: name of the field reference in generated code |
| 117 | :param field_name: name of the field (camelcase) |
| 118 | :param field_length: integer or name of variable that stores field length |
| 119 | :param object_name: name of the object to be initialized |
| 120 | """ |
| 121 | |
| 122 | # todo move validation to vppapigen |
| 123 | if field_type.endswith('[]') and field_length == '0': |
| 124 | raise Exception('Variable array \'%s\' defined in \'%s\' ' |
| 125 | 'should have defined length (e.g. \'%s[%s_length]\'' |
| 126 | % (c_name, handler_name, c_name, c_name)) |
| 127 | |
| 128 | if is_variable_len_array: |
| 129 | length_var_name = field_length |
| 130 | field_length = variable_length_array_value_template.substitute(length_var_name=length_var_name) |
| 131 | if length_field_type != 'u8': # we need net to host conversion: |
| 132 | field_length = variable_length_array_template.substitute( |
| 133 | length_field_type=length_field_type, value=field_length) |
| 134 | |
| 135 | # for retval don't generate setters |
| 136 | if util.is_retval_field(c_name): |
| 137 | return "" |
| 138 | |
| 139 | jni_signature = util.jni_2_signature_mapping[field_type] |
| 140 | jni_setter = util.jni_field_accessors[field_type] |
| 141 | |
| 142 | result = dto_field_id_template.substitute( |
| 143 | field_reference_name=field_reference_name, |
| 144 | field_name=field_name, |
| 145 | class_ref_name=ref_name, |
| 146 | jni_signature=jni_signature) |
| 147 | |
| 148 | dto_setter_template = dto_field_setter_templates[field_type] |
| 149 | |
| 150 | result += dto_setter_template.substitute( |
| 151 | jni_signature=jni_signature, |
| 152 | object_name=object_name, |
| 153 | field_reference_name=field_reference_name, |
| 154 | c_name=c_name, |
| 155 | jni_setter=jni_setter, |
| 156 | field_length=field_length) |
| 157 | return result |
| 158 | |
| 159 | |
| 160 | request_field_identifier_template = Template(""" |
| 161 | jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${object_name}Class, "${field_name}", "${jni_signature}"); |
| 162 | ${jni_type} ${field_reference_name} = (*env)->Get${jni_getter}(env, ${object_name}, ${field_reference_name}FieldId); |
| 163 | """) |
| 164 | |
| 165 | array_length_enforcement_template = Template(""" |
| 166 | size_t max_size = ${field_length}; |
| 167 | if (cnt > max_size) cnt = max_size;""") |
| 168 | |
| 169 | u8_struct_setter_template = Template(""" |
| 170 | mp->${c_name} = ${field_reference_name};""") |
| 171 | |
| 172 | u16_struct_setter_template = Template(""" |
| 173 | mp->${c_name} = clib_host_to_net_u16(${field_reference_name});""") |
| 174 | |
| 175 | u32_struct_setter_template = Template(""" |
| 176 | mp->${c_name} = clib_host_to_net_u32(${field_reference_name});""") |
| 177 | |
| 178 | i32_struct_setter_template = Template(""" |
| 179 | mp->${c_name} = clib_host_to_net_i32(${field_reference_name});!""") |
| 180 | |
| 181 | u64_struct_setter_template = Template(""" |
| 182 | mp->${c_name} = clib_host_to_net_u64(${field_reference_name});""") |
| 183 | |
| 184 | array_length_enforcement_template = Template(""" |
| 185 | size_t max_size = ${field_length}; |
| 186 | if (cnt > max_size) cnt = max_size;""") |
| 187 | |
| 188 | u8_array_struct_setter_template = Template(""" |
| 189 | if (${field_reference_name}) { |
| 190 | jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name}); |
| 191 | ${field_length_check} |
| 192 | (*env)->GetByteArrayRegion(env, ${field_reference_name}, 0, cnt, (jbyte *)mp->${c_name}); |
| 193 | } |
| 194 | """) |
| 195 | |
| 196 | u16_array_struct_setter_template = Template(""" |
| 197 | jshort * ${field_reference_name}ArrayElements = (*env)->GetShortArrayElements(env, ${field_reference_name}, NULL); |
| 198 | if (${field_reference_name}) { |
| 199 | size_t _i; |
| 200 | jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name}); |
| 201 | ${field_length_check} |
| 202 | for (_i = 0; _i < cnt; _i++) { |
| 203 | mp->${c_name}[_i] = clib_host_to_net_u16(${field_reference_name}ArrayElements[_i]); |
| 204 | } |
| 205 | } |
| 206 | (*env)->ReleaseShortArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0); |
| 207 | """) |
| 208 | |
| 209 | u32_array_struct_setter_template = Template(""" |
| 210 | jint * ${field_reference_name}ArrayElements = (*env)->GetIntArrayElements(env, ${field_reference_name}, NULL); |
| 211 | if (${field_reference_name}) { |
| 212 | size_t _i; |
| 213 | jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name}); |
| 214 | ${field_length_check} |
| 215 | for (_i = 0; _i < cnt; _i++) { |
| 216 | mp->${c_name}[_i] = clib_host_to_net_u32(${field_reference_name}ArrayElements[_i]); |
| 217 | } |
| 218 | } |
| 219 | (*env)->ReleaseIntArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0); |
| 220 | """) |
| 221 | |
| 222 | u64_array_struct_setter_template = Template(""" |
| 223 | jlong * ${field_reference_name}ArrayElements = (*env)->GetLongArrayElements(env, ${field_reference_name}, NULL); |
| 224 | if (${field_reference_name}) { |
| 225 | size_t _i; |
| 226 | jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name}); |
| 227 | ${field_length_check} |
| 228 | for (_i = 0; _i < cnt; _i++) { |
| 229 | mp->${c_name}[_i] = clib_host_to_net_u64(${field_reference_name}ArrayElements[_i]); |
| 230 | } |
| 231 | } |
| 232 | (*env)->ReleaseLongArrayElements (env, ${field_reference_name}, ${field_reference_name}ArrayElements, 0); |
| 233 | """) |
| 234 | |
| 235 | struct_setter_templates = {'u8': u8_struct_setter_template, |
| 236 | 'u16': u16_struct_setter_template, |
| 237 | 'u32': u32_struct_setter_template, |
| 238 | 'i32': u32_struct_setter_template, |
| 239 | 'u64': u64_struct_setter_template, |
| 240 | 'u8[]': u8_array_struct_setter_template, |
| 241 | 'u16[]': u16_array_struct_setter_template, |
| 242 | 'u32[]': u32_array_struct_setter_template, |
| 243 | 'u64[]': u64_array_struct_setter_template |
| 244 | } |
| 245 | |
| 246 | |
| 247 | def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_name, field_length, |
| 248 | is_variable_len_array, object_name="request"): |
| 249 | """ |
| 250 | Generates jni code that initializes C structure that corresponds to a field of java object |
| 251 | (dto or custom type). To be used in request message handlers. |
| 252 | :param field_type: type of the field to be initialized (as defined in vpe.api) |
| 253 | :param c_name: name of the message struct member to be initialized |
| 254 | :param field_reference_name: name of the field reference in generated code |
| 255 | :param field_name: name of the field (camelcase) |
| 256 | :param field_length: integer or name of variable that stores field length |
| 257 | :param object_name: name of the object to be initialized |
| 258 | """ |
| 259 | # field identifiers |
| 260 | jni_type = util.vpp_2_jni_type_mapping[field_type] |
| 261 | jni_signature = util.jni_2_signature_mapping[field_type] |
| 262 | jni_getter = util.jni_field_accessors[field_type] |
| 263 | |
| 264 | # field identifier |
| 265 | msg_initialization = request_field_identifier_template.substitute( |
| 266 | jni_type=jni_type, |
| 267 | field_reference_name=field_reference_name, |
| 268 | field_name=field_name, |
| 269 | jni_signature=jni_signature, |
| 270 | jni_getter=jni_getter, |
| 271 | object_name=object_name) |
| 272 | |
| 273 | # field setter |
| 274 | field_length_check = "" |
| 275 | |
| 276 | # check if we are processing variable length array: |
| 277 | if is_variable_len_array: |
| 278 | field_length = util.underscore_to_camelcase(field_length) |
| 279 | |
| 280 | # enforce max length if array has fixed length or uses variable length syntax |
| 281 | if str(field_length) != "0": |
| 282 | field_length_check = array_length_enforcement_template.substitute(field_length=field_length) |
| 283 | |
| 284 | struct_setter_template = struct_setter_templates[field_type] |
| 285 | |
| 286 | msg_initialization += struct_setter_template.substitute( |
| 287 | c_name=c_name, |
| 288 | field_reference_name=field_reference_name, |
| 289 | field_length_check=field_length_check) |
| 290 | |
| 291 | return msg_initialization |