1# Copyright 2024 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4"""Codegen related to @JniType.""" 5 6from codegen import header_common 7import java_types 8 9 10def conversion_declarations(java_to_cpp_types, cpp_to_java_types): 11 declarations = set() 12 for java_type in java_to_cpp_types: 13 T = java_type.converted_type() 14 J = java_type.to_cpp() 15 declarations.add(f'template<> {T} ' 16 f'FromJniType<{T}, {J}>(JNIEnv*, const JavaRef<{J}>&);') 17 18 for java_type in cpp_to_java_types: 19 T = java_type.converted_type() 20 J = java_type.to_cpp() 21 declarations.add(f'template<> jni_zero::ScopedJavaLocalRef<{J}> ' 22 f'ToJniType<{T}, {J}>(JNIEnv*, {T} const&);') 23 24 if not declarations: 25 return '' 26 27 declaration_lines = '\n'.join(sorted(declarations)) 28 return f"""\ 29// Forward declare used conversion functions to avoid a compiler warning that 30// triggers if a conversion specialization exists within the including .cc file. 31namespace jni_zero {{ 32{declaration_lines} 33}} // namespace jni_zero 34""" 35 36 37def to_jni_expression(sb, rvalue, java_type, clazz_param=None): 38 """Returns a conversion call expression from specified @JniType to default jni type.""" 39 if java_type.is_primitive(): 40 if java_type.primitive_name == 'int' and not java_type.converted_type(): 41 rvalue = f'as_jint({rvalue})' 42 sb(f'static_cast<{java_type.to_cpp()}>({rvalue})') 43 return 44 45 T = java_type.converted_type() 46 if not java_type.is_array(): 47 sb(f'jni_zero::ToJniType<{T}, {java_type.to_cpp()}>') 48 sb.param_list(['env', rvalue]) 49 return 50 51 element_type = java_type.to_array_element_type() 52 if element_type.is_array(): 53 raise Exception( 54 '@JniType() for multi-dimensional arrays are not yet supported. ' 55 'Found ' + T) 56 if element_type.is_primitive(): 57 sb(f'jni_zero::ConvertArray<{T}>::ToJniType') 58 sb.param_list(['env', rvalue]) 59 return 60 61 if clazz_param: 62 clazz_expr = clazz_param.name 63 else: 64 clazz_expr = header_common.class_accessor_expression( 65 element_type.java_class) 66 J = element_type.to_cpp() 67 sb(f'jni_zero::ConvertArray<{T}>::ToJniType<{J}>') 68 sb.param_list(['env', rvalue, clazz_expr]) 69 70 71def to_jni_assignment(sb, dest_var_name, src_var_name, java_type): 72 """Returns a conversion statement from specified @JniType to default jni type.""" 73 with sb.statement(): 74 if java_type.is_primitive(): 75 var_type = java_type.to_cpp() 76 else: 77 var_type = f'jni_zero::ScopedJavaLocalRef<{java_type.to_cpp()}>' 78 sb(f'{var_type} {dest_var_name} = ') 79 to_jni_expression(sb, src_var_name, java_type) 80 81 82def from_jni_expression(sb, rvalue, java_type): 83 """Returns a conversion call expression from default jni type to specified @JniType.""" 84 T = java_type.converted_type() 85 J = java_type.to_cpp() 86 if java_type.is_primitive(): 87 sb(f'static_cast<{T}>({rvalue})') 88 return 89 90 if not java_type.is_primitive(): 91 rvalue = header_common.java_param_ref_expression(J, rvalue) 92 93 if not java_type.is_array(): 94 sb(f'jni_zero::FromJniType<{T}, {J}>') 95 sb.param_list(['env', rvalue]) 96 return 97 98 element_type = java_type.to_array_element_type() 99 if element_type.is_array(): 100 raise Exception( 101 '@JniType() for multi-dimensional arrays are not yet supported. ' 102 'Found ' + T) 103 if element_type.is_primitive(): 104 sb(f'jni_zero::ConvertArray<{T}>::FromJniType') 105 sb.param_list(['env', rvalue]) 106 return 107 108 J = java_type.to_array_element_type().to_cpp() 109 sb(f'jni_zero::ConvertArray<{T}>::FromJniType<{J}>') 110 sb.param_list(['env', rvalue]) 111 112 113def from_jni_assignment(sb, dst_var_name, src_var_name, java_type): 114 """Returns a conversion statement from default jni type to specified @JniType.""" 115 with sb.statement(): 116 sb(f'{java_type.converted_type()} {dst_var_name} = ') 117 from_jni_expression(sb, src_var_name, java_type) 118